2023/10/16

網路效應

nfx.com 有一份 The Network Effects Bible 討論網路效應的重要性,每增加一個使用者,會讓這個產品/服務更有價值,也就是大者恆大的局面,在網路時代,所有系統發展的初期,都還是在獲取使用者的眼球的競爭下,只有大量的使用者,才算是拿到了入場門票,才會有下一個維持跟進化的問題。

分類

文中提到 16 種不同的網路效應(該文章有持續在更新),根據網路化的程度由小到大排列

  1. Physical (e.g. landline telephones)
  2. Protocol (e.g. Ethernet)
  3. Personal Utility (e.g. iMessage, WhatsApp)
  4. Personal (e.g. Facebook)
  5. Market Network (e.g. HoneyBook, AngelList)
  6. Marketplace (e.g. eBay, Craigslist)
  7. Platform (e.g. Windows, iOS, Android)
  8. Asymptotic Marketplace (e.g. Uber, Lyft)
  9. Data (e.g. Waze, Yelp!)
  10. Tech Performance (e.g. Bittorrent,Skype)
  11. Language (e.g. Google, Xerox)
  12. Belief (currencies, religions)
  13. Bandwagon (e.g. Slack, Apple)
  14. Expertise (Figma, Microsoft Excel)
  15. Tribal (Apple, Harvard, NY Yankees…)
  16. Hub-and-Spoke  (TikTok, Medium, Craigslist)

網路就是 node 與 link 的組合,網路大小以 node 的數量計算,但該數量不完全代表價值,因為該網路內的活動頻繁程度,也會影響價值。

網路密度 Density 是另一個網路的價值屬性,密度越高,代表價值越高,也就是 nodes 之間的 link 強度跟數量。

link 是有方向性的,例如 twitter 的知名人士,以單向方式跟 fans 提供資訊,單向交流,也有可能沒有方向,例如 Messenger 的交談一定是雙向的,因此沒有必要定義方向。

nodes 之間的關係有 1-1 (ex: Facebook) 與 1-to-many (ex: Youtube),1-1 的互動是雙向的,1-to-many 的互動是單向的。網路的 nodes 分佈會有 cluster 的特性,是一群一群的。

數學模型

有幾個網路效應的法則,試圖以數學模型說明網路效應的價值

  1. Sarnoff’s Law

    早期的電視廣播,其價值直接跟使用者數量成正比。該網路都是從網路中心單向發送連結到使用者

    V = N
  2. Metcalfe’s Law

    在 Internet 時代,連上網路的電腦都可以用任何方式互相傳送資訊。因此網路的價值每增加一個 node,該 node 都可以跟原本的其他 node 連結,價值應該要是所有的節點數量。

    V = N * (N-1) /2 => 約等於 N^2
  3. Reed’s Law

    David P. Reed 於 1999 年提出,增加一個 node 的網路價值,除了連結的節點數量以外,還要再乘上該 node 帶來的潛在的 cluster,該 node 還會產生更多 sub-groups/clusters

    V = 2^N

網路特徵

  1. 不規則性

    nodes 與 cluster 的分佈並不均勻,各節點之間的 link 狀況,也跟真實世界一樣,沒有固定的樣式

  2. 身份:真實、假名、匿名

    有真實身份的網路,會比假名的網路能更有效地建構網路。但在加密或間諜應用中,反而需要匿名的網路,但卻可能因為匿名,該網路關係更容易被破壞。

  3. 不對稱性

    有不同的角色組合的網路,且某一邊的使用者取得比其他的困難。這被稱為是 Demand-Side 或是 Supply-Side Marketplace,例如 Uber

  4. 同質、異質網路

    當所有 nodes 的角色都一樣時,這是同質網路,如果網路內有分不同的角色,則是異質網路,例如網拍網站,有分買家及賣家兩種角色。

  5. 漸近 Asymptotic

    通常使用者增加,每個使用者產生的價值也在增加,但當網路成長到某個程度後,網路效應的增加就開始減弱。ex: Uber 乘客的等待時間,隨著司機數量增加到某個程度後,等待時間就無法再一直縮短了

  6. 同邊 Same-Side

    同樣使用 Windows Office 的使用者,因為檔案相容性的關係,會因為使用者增加而讓該檔案更加流通

  7. 橫向 Cross-Side

    例如 Uber,driver 增加會增加客人,客人增加也會再吸引更多 driver

  8. Indirect

    例如 ebay,新賣家的加入,只會讓賣家之間的競爭更激烈,但由於賣家增加,更吸引買家加入,整體來說,還是會讓所有賣家間接受惠。

  9. Negative

    網路的負面效應有兩種:Congestion (增加使用量) 及 Pollution (增加規模)

    因為更多人使用網路,會讓網路壅塞,速度變慢。

    FB, Twitter 會因為更多人使用,而污染自己個人的 News Feed

建構與維護

  1. Multiplayer vs. Single-Player Mode

    單人模式只會線性增長,多人的聯網產品同時具有單人與多人的價值

  2. 轉換成本 switching cost

    切換到不相容的產品,會花時間、精神與金錢,這會讓使用者傾向於使用同一個廠商的商品,並待在同一個生態體系下

  3. Chicken or Egg Problem (Cold Start Problem)

    這是 2-sided martketplace 常見的問題,buyers/sellers 或是 developers/users

    當有一邊的使用者增加,才會讓另一邊也加入。有 19 Tactics to Solve the Chicken-or-Egg Problem and Grow Your Marketplace 能解決此問題

  4. Multi-Tenanting

    同時加入多個互相競爭的網路 ex: Lyft, Uber,同時加入多個社交平台

    越大的網路會越有知名度,越能吸引新客戶

  5. Disintermediation 去中心化

    在 marketplace 或 merket network 產品中很常見。一開始透過該網路進行交易,後續就改為不透過網路平台而直接交易。

  6. Retention 留存率

    客戶回頭再使用產品的頻率。留存率高的網路效應才高。

結語

經過這些年的社交網路更迭,有很明顯的世代交替狀況,使用者的增加,確實放大了網路的價值,也許大部分的人會因為要跟其他人溝通與交流,而加入某些網路 ,雖然人數增加了,卻也凸顯了沒有一個系統能夠適用於所有人的情況,系統可以瞬間爆紅,也可能會一下子就因為技術替換與世代交替消失。

References

# 网络效应“圣经”(上):网络效应为什么重要?其运作原理是什么?

# 网络效应“圣经”(下):如何建立和维护网络效应?相关概念有哪些?

《NFX:网络效应圣经》笔记

The Network Effects Manual: 16 Different Network Effects (and counting)

# 网络效应是什么?网络效应定律简介

2023/10/2

erlang poolboy

poolboy: A hunky Erlang worker pool factory 是一個通用用途的 erlang pool library,主要是用在 pool 管理,對於 server 程式來說,最常見的就是連接資料庫的 connection pool。

連接資料庫最簡單的做法,是在程式中要呼叫使用資料庫時,要經過連線與認證,使用完畢後,就馬上關閉該資料庫連線,但對於 server 來說,因為大量的連線建立關閉,消耗了很多運算資源,故通常會以資料庫 connection pool 的方式來處理。

一般的 connection pool,會有初始的連線 pool 數量,就是一開始啟動時,固定會產生並維持幾個連線數量,然後在所有連線都被佔用時,有一個 overflow 的數量,設定超量使用時,一次多產生幾個連線。另外為了確保該網路連線是正常連線的狀態,DB pool 通常會定時發送一個 SQL 指令,以該指令有沒有回應來確認連線狀態。例如 MySQL 可以使用 SELECT CURRENT_TIMESTAMP 這樣的 SQL 指令。

poolboy 就是用 erlang process 來作為一個 connection 的資源,該 process 的 state 裡面,就記錄該資料庫連線,另外有個 supervisor 用來做連線的資源管理。

使用方式

poolboy 以 epgsql 為例,說明如何使用 poolboy,要實作兩個部分 worker 跟 supervisor,另外要做 pool 的設定。細節直接看 poolboy 的 github 首頁即可。

poolboy 裡面的 transaction 就是使用該 pool 的最簡單的方式,先 checkout 一個 worker,然後呼叫 worker 裡面的某一個 function,最終使用完成後,呼叫 checkin 釋放 worker。

transaction(Pool, Fun, Timeout) ->
     Worker = poolboy:checkout(Pool, true, Timeout),
     try
         Fun(Worker)
     after
         ok = poolboy:checkin(Pool, Worker)
     end.

checkout 有三種方式

% 取得可以使用的 worker process,如果沒有,預設會等待 5s
1> Worker = poolboy:checkout(PoolName).
% returns PID in under 5 seconds or full.

% 不等待,直接回傳可使用的 worker
2> Worker = poolboy:checkout(PoolName, false).
% no waiting, either you have an idle worker for me or not.

% 等待 10s
3> Worker = poolboy:checkout(PoolName, true, 10000).
% like the first one but wait 10 secs instead of 5

注意事項

poolboy 的坑(Erlang) - 开发者头条

使用 poolboy 時,要注意幾個問題,產生 worker process 時,不能失敗,如果 worker 失敗,會導致整個 gen_server crash,無法啟動 pool。

解決方法是使用 proxy,也就是在建立 worker 時,並不直接產生 db 的連線,而是直接將 worker process 建立起來,後續在使用到該 worker 時,才去檢查 worker 裡面的 conn state。

這邊的問題是在如何做連線維持,因為 worker 把連線建立延後了,這表示使用 worker 以前,不能確認該 worker 擁有的 conn 到底是不是正常的連線,連線也可能因為 idle 太久而被資料庫直接斷線。

連線維護的部分,會需要在 worker 裡面另外寫 timer,定時做 callback,然後定時發送一個 SQL 指令,以該指令有沒有回應來確認連線狀態。

References

GitHub - interline/epgsql_pool: Pooled epgsql connections using Poolboy

GitHub - hiroeorz/eredis_pool: eredis_pool is Pool of Redis clients, using eredis and poolboy.

erlang进程池-poolboy源码分析_食鱼酱的博客-CSDN博客

# erlang线程池poolboy源码阅读

Erlang poolboy notes – Triggers-World

2023/9/25

firewalld

在 rockylinux 8 以前,可以不使用firewalld,還是沿用舊的 iptables

# Stop firewalld
systemctl stop firewalld
# disable firewalld
systemctl disable firewalld
# hide firewalld
systemctl mask firewalld

安裝 iptables

dnf -y install iptables iptables-services

systemctl enable iptables
systemctl start iptables
systemctl status --no-pager iptables

在 rockylinux 9 以後,firewalld 成為預設的 firewall

  • firewalld 支援 network/firewall zones,定義 trust level of network connections

  • 同時支援 IPv4, IPv6

  • 支援由 service/applcation 直接建立 firewall rules

如果有圖形介面,可透過 firewall-config 進行 firewall 設定

啟用 firewalld

systemctl enable --now firewalld
systemctl restart firewalld

systemctl status --no-pager firewalld

基本指令

以下是 firewalld 幾個基本常用的指令

# 檢查 firewalld 狀態
firewall-cmd --state

# 設定完成後,要重新載入設定,讓設定永久生效
firewall-cmd --reload

# 查閱設定
firewall-cmd --list-all

# 查閱詳細設定
firewall-cmd --list-rich-rules

# 將設定永久儲存
firewall-cmd --runtime-to-permanent

# 在設定過程中,直接增加rule 並永久儲存
firewall-cmd --permanent [the rest of your command]

zone

firewalld 最重要的是加入了 zone 的概念,以下是內建基本的 zones

zone 說明 example use
drop 不回應任何封包,直接拒絕所有外部連線,只允許內部往外傳送的 packets。 drop incoming connections without reply - only outgoing packets are allowed
block 以 icmp-host-prohibited, icmp6-adm-prohibited 拒絕外部連線 incoming connections are rejected with an icmp-host-prohibited message for IPv4 and icmp6-adm-prohibited for IPv6
public 允許所有外部連線 all incoming connections are allowed
external 有使用 IP 偽裝時,用在外部網路 for use on external networks with masquerading enabled
dmz 給 DMZ 的電腦使用 for computers on your demilitarized zone that are publicly-accessible with limited access to your internal network
work for computers in work areas (nope, I don't get this one either)
home for use in home areas (nope, I don't get this one either)
internal 內部網路使用 for your internal network device access
trusted 允許所有網路連線 all network connections are accepted

如果滿足以下兩個條件中某一個,該 zone 就會是在 active 狀態

  1. zone 被綁定到某一個 network interface

  2. zone 被綁定 source IPs 或 network ranges

一般使用者比較會使用 trusted, home, public 這幾個 zone

zone 的相關指令

# 查詢 default zone
firewall-cmd --get-default-zone

# 查詢 active zones
firewall-cmd --get-active-zones

# 修改 default zone
firewall-cmd --set-default-zone [your-zone]

# 將某個 zone 綁定 network interface
firewall-cmd --zone=[your-zone] --add-interface=[your-network-device]

# 修改 zone 的 network interface
firewall-cmd --zone=[your-zone] --change-interface=[your-network-device]

# 移除 network interface
firewall-cmd --zone=[your-zone] --remove-interface=[your-network-device]

# 新增 zones
firewall-cmd --new-zone=[your-new-zone]
firewall-cmd --get-zones

rule

port

# 查詢
firewall-cmd --list-ports

# add remove
firewall-cmd --zone=public --add-port=9001/tcp
firewall-cmd --zone=public --add-port=20000-20100/tcp

firewall-cmd --zone=public --remove-port=9001/tcp

service

# 查詢可使用的 services
firewall-cmd --get-services

# 查詢目前的 active services
firewall-cmd --list-services

# add/remove
firewall-cmd --zone=public --add-service=http
firewall-cmd --zone=public --remove-service=http

ip

firewall-cmd --permanent --zone=trusted --add-source=192.168.1.0/24

firewall-cmd --permanent --zone=trusted --remove-source=192.168.1.0/24

rich rule

#單一IP

firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.168.1.100' reject"
#除了針對特定單一IP外,再針對特別連線port進行設定
firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="3306" accept'
#針對IP範圍
firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.168.1.0/24' reject"

firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.77.100/32" accept'

在 iptables, firewalld 允許某個 ip 使用 ssh

# iptables
iptables -A INPUT -p tcp -m tcp -s 192.168.1.122 --dport 22 -j ACCEPT

# firewalld
firewall-cmd --zone=trusted --add-source=192.168.1.122 --permanent
firewall-cmd --zone=trusted --add-service=ssh --permanent

# remove
firewall-cmd --zone=trusted --remove-source=192.168.1.122
firewall-cmd --zone=trusted --remove-service ssh

# 儲存設定
firewall-cmd --runtime-to-permanent
firewall-cmd --reload

ICMP rule

# iptables
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -s 192.168.1.136 -j ACCEPT

# "public" zone 的 ICMP 預設是開啟的
# block ICMP in "public" "trusted" zone
firewall-cmd --zone=public --add-icmp-block={echo-request,echo-reply} --permanent
firewall-cmd --zone=trusted --add-icmp-block={echo-request,echo-reply} --permanent

web server ports

# iptables
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

# add service
firewall-cmd --zone=public --add-service=http --add-service=https --permanent

# 移除
firewall-cmd --zone=public --remove-service=http --remove-service=https --permanent

DNS

# iptables
iptables -A INPUT -p udp -m udp -s 192.168.1.0/24 --dport 53 -j ACCEPT

# 
firewall-cmd --zone=trusted --add-service=dns
firewall-cmd --zone=public --add-service=dns

TCP state

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# firewalld 不需要做這個設定

mysql

# iptables
iptables -A INPUT -p tcp -m tcp --dport=3600 -j ACCEPT

# firewalld
firewall-cmd --zone=public --add-service=mysql --permanent

postgresql

# iptables
iptables -A INPUT -p tcp -m tcp --dport 5432 -s 192.168.1.0/24 -j ACCEPT

# firewalld
firewall-cmd --zone=trusted --add-service=postgresql

References

Enabling iptables Firewall - Documentation

firewalld from iptables - Documentation

firewalld for Beginners - Documentation

基本防火牆設定 | 晟鑫科技線上手冊

Firewalld 防火牆 - HackMD

Linux Firewall-cmd 防火牆安裝, 允許/禁止 IP, Port 用法介紹

2023/9/18

OAuth

傳統的 Client-Server 架構裡, Client 要拿取受保護的資源 (Protected Resoruce) 的時候,要向 Server 出示使用者 (Resource Owner) 的帳號密碼才行。如果要讓第三方應用程式也可以使用這些 Resources ,則需要 Resource Owner 把帳號密碼給這個第三方應用程式,這時候會產生以下的問題:

  • 第三方應用程式必須以明碼儲存 Resource Owner 的帳號密碼
  • Server 要支援密碼認證
  • 第三方應用程式會得到完整存取 Protected Resources 的權限,無法限制時效
  • Resource Owner 無法只撤回某一個第三方應用程式的存取權,必須要修改密碼才能撤回。
  • 當某一個第三方應用程式被破解,就會導致使用該密碼的所有資料被破解。

OAuth 解決這些問題的方式,是引入一個認證層 (authorization layer) ,並把 client 跟 resource owner 的角色分開。Client 會先索取存取權,來存取 Resource Owner 擁有的資源,這些資源會放在 Resource Server 上面,並且 Client 會得到一組不同於 Resource Owner 所持有的認證碼,也就是 access token。

角色定義

  • Resource Owner

    可授權別人去存取 Protected Resource。如果這個角色是人類的話,就是指使用者 (end-user)。

  • Resource Server

    存放 Protected Resource 的伺服器,可以根據 Access Token 來接受使用 Protected Resource 的請求。

  • Client

    讓 Resource Owner 授權後,可以去存取 Protected Resource 的應用程式。

  • Authorization Server

    認證 Resource Owner 並獲得 Resource Owner 許可後,核發 Access Token 的伺服器。

+--------+                               +---------------+
|        |--(A)- Authorization Request ->|   Resource    |
|        |                               |     Owner     |
|        |<-(B)-- Authorization Grant ---|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(C)-- Authorization Grant -->| Authorization |
| Client |                               |     Server    |
|        |<-(D)----- Access Token -------|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(E)----- Access Token ------>|    Resource   |
|        |                               |     Server    |
|        |<-(F)--- Protected Resource ---|               |
+--------+                               +---------------+

Refresh Token 流程

+--------+                                           +---------------+
|        |--(A)------- Authorization Grant --------->|               |
|        |                                           |               |
|        |<-(B)----------- Access Token -------------|               |
|        |               & Refresh Token             |               |
|        |                                           |               |
|        |                            +----------+   |               |
|        |--(C)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(D)- Protected Resource --| Resource |   | Authorization |
| Client |                            |  Server  |   |     Server    |
|        |--(E)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(F)- Invalid Token Error -|          |   |               |
|        |                            +----------+   |               |
|        |                                           |               |
|        |--(G)----------- Refresh Token ----------->|               |
|        |                                           |               |
|        |<-(H)----------- Access Token -------------|               |
+--------+           & Optional Refresh Token        +---------------+

Grant Flow

Authorization Code Grant Type Flow

+----------+
| Resource |
|   Owner  |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier      +---------------+
|         -+----(A)-- & Redirection URI ---->|               |
|  User-   |                                 | Authorization |
|  Agent  -+----(B)-- User authenticates --->|     Server    |
|          |                                 |               |
|         -+----(C)-- Authorization Code ---<|               |
+-|----|---+                                 +---------------+
  |    |                                         ^      v
 (A)  (C)                                        |      |
  |    |                                         |      |
  ^    v                                         |      |
+---------+                                      |      |
|         |>---(D)-- Authorization Code ---------'      |
|  Client |          & Redirection URI                  |
|         |                                             |
|         |<---(E)----- Access Token -------------------'
+---------+       (w/ Optional Refresh Token)
  • 要向 Authorization Server 先取得 Grant Code 再取得 Access Token。
  • 適合 Confidential Clients ,如部署在 Server 上面的應用程式。
  • 可以核發 Refresh Token。
  • 需要 User-Agent Redirection。

Implicit Grant Type Flow

+----------+
| Resource |
|  Owner   |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier     +---------------+
|         -+----(A)-- & Redirection URI --->|               |
|  User-   |                                | Authorization |
|  Agent  -|----(B)-- User authenticates -->|     Server    |
|          |                                |               |
|          |<---(C)--- Redirection URI ----<|               |
|          |          with Access Token     +---------------+
|          |            in Fragment
|          |                                +---------------+
|          |----(D)--- Redirection URI ---->|   Web-Hosted  |
|          |          without Fragment      |     Client    |
|          |                                |    Resource   |
|     (F)  |<---(E)------- Script ---------<|               |
|          |                                +---------------+
+-|--------+
  |    |
 (A)  (G) Access Token
  |    |
  ^    v
+---------+
|         |
|  Client |
|         |
+---------+
  • Authorization Server 直接向 Client 核發 Access Token (一步)。
  • 適合非常特定的 Public Clients ,例如跑在 Browser 裡面的應用程式。
  • Authorization Server 不必(也無法)驗證 Client 的身份。
  • 禁止核發 Refresh Token。
  • 需要 User-Agent Redirection。
  • 有資料外洩風險。

Resource Owner Password Credentials Grant Type Flow

+----------+
| Resource |
|  Owner   |
|          |
+----------+
     v
     |    Resource Owner
    (A) Password Credentials
     |
     v
+---------+                                  +---------------+
|         |>--(B)---- Resource Owner ------->|               |
|         |         Password Credentials     | Authorization |
| Client  |                                  |     Server    |
|         |<--(C)---- Access Token ---------<|               |
|         |    (w/ Optional Refresh Token)   |               |
+---------+                                  +---------------+
  • Resource Owner 的帳號密碼直接拿來當做 Grant。
  • 適用於 Resource Owner 高度信賴的 Client (像是 OS 內建的)或是官方應用程式。
  • 其他流程不適用時才能用。
  • 可以核發 Refresh Token。
  • 沒有 User-Agent Redirection。

Client Credentials Grant Type Flow

+---------+                                  +---------------+
|         |                                  |               |
|         |>--(A)- Client Authentication --->| Authorization |
| Client  |                                  |     Server    |
|         |<--(B)---- Access Token ---------<|               |
|         |                                  |               |
+---------+                                  +---------------+
  • Client 的帳號與密碼直接用來 Grant
  • 適用於跑在 Server 上面的 Confidential Client
  • 不建議核發 Refresh Token
  • 沒有 User-Agent Redirection

References

OAuth 2.0 筆記 (1) 世界觀

OAuth 2.0 筆記 (4.1) Authorization Code Grant Flow 細節

OAuth 2.0 筆記 (4.2) Implicit Grant Flow 細節

OAuth 2.0 筆記 (4.3) Resource Owner Password Credentials Grant Flow 細節

OAuth 2.0 筆記 (4.4) Client Credentials Grant Flow 細節

各大網站 OAuth 2.0 實作差異 2013

2023/9/11

mDNS DNS-SD

DNS-SD(DNS Service Discovery) 跟 mDNS (multicast DNS) 是不同的 protocol,但可以互相相容。DNS-SD 能透過標準的 DNS 技術,尋找區域網路中,提供某些服務的協定。而 mDNS 是能夠在區域網路中,在不需要 DNS Server 的情況下,就能透過機器名稱,直接查出 IP。

apple 的 Bonjour protocol 就是合併了 mDNS 與 DNS-SD 實作的。

mDNS

可用在沒有 DNS server 的區域網路中,用來作機器 domain name 的 IP 查詢。設備會透過對 224.0.0.251 這個 multicast address,Port 為 5353,進行廣播,mDNS 使用跟 DNS 一樣的封包格式。mDNS 只接受 .local 的網域名稱,可同時運作在一個設備中,跟原本的 DNS 並存。

mDNS 也有為自己命名的功能,在自選了一個 domain name 後,會用記錄類型為 any 的 mDNS 封包查詢是否有同樣的 domain name 的另一台機器,如果沒有,就會設定為自己的 domain name。

DNS-SD

基於 DNS,主要用到三種記錄類型:PTR、SRV、TXT

  • Service Discovery

    設備會先發送一個 PTR 記錄的 multicast 查詢封包,查詢的格式為

    <service>.<transport>.<domain>

    service 是查詢的服務,transport 為傳輸協定: TCP 或 UDP,domain 為查詢網域,在 mDNS 為 .local。查詢後,具有該服務的設備就會回應

    <instance>.<service>.<transport>.<domain>

    ex: 查詢 _easylink._tcp.local,EMW3031 Module#500A3F._easylink._tcp.local 回應

    就表示 EMW3031 Module#500A3F 是符合該 service 的 instance

  • 取得 instance 的 domain name 與 port

    當有多個 instance 回應後,選擇某一個 instance,然後需要查詢該 instance 的 domain name 與 port,也就是查詢 SRV 記錄

    _service._proto.name. TTL class SRV priority weight port target.

    priority 和 weight 沒有作用,通常設定為 0

    port 與 target 就分別是 port 與 domain name

    ex:

    EMW3031 Module#500A3F._easylink._tcp.local. 3 IN SRV 0 0 8002 EMW3031 Module#500A3F.local.
  • 更詳細的資訊

    除了 domain name 與 port 以外,還能夠提供更多資訊,就是記錄在 TXT record 中,以 key=value 格式記錄的資訊

    ex:

    MAC=D0:BA:E4:50:0A:3F

CentOS7 avahi

Avahi is a system which facilitates service discovery on a local network via the mDNS/DNS-SD protocol suite.

安裝 avahi

yum install nss-mdns avahi avahi-tools

啟動

systemctl start avahi-daemon

出現錯誤訊息

 dbus_bus_request_name(): Connection ":1.44573" is not allowed to own the service "org.freedesktop.Avahi" due to security policies in the configuration file

要重新啟動 dbus, NetworkManager

systemctl restart dbus.service

# /var/log/messages 會出現錯誤訊息
# (NetworkManager:624): GLib-GIO-CRITICAL **: Error while sending AddMatch () message: 這個連線已關閉
systemctl restart NetworkManager
# 避免 ssh 登入問題
# Failed to activate service 'org.freedesktop.login1': timed out
systemctl restart systemd-logind

再啟動 avahi-demon

systemctl start avahi-daemon

然後就能查詢 LAN 的機器

# avahi-browse -a
+ enp3s0 IPv4 lzstg [6c:62:6d:ce:71:c7]                     Workstation          local
+ enp3s0 IPv4 macmini2                                      Microsoft Windows Network local
+ enp3s0 IPv4 macmini2                                      Apple File Sharing   local
+ enp3s0 IPv4 macmini2                                      Apple Net Assistant  local
+ enp3s0 IPv4 Michael's MacBook Pro                         Microsoft Windows Network local
+ enp3s0 IPv4 Michael's MacBook Pro                         _companion-link._tcp local

也可以直接 ping *.local 的機器

# ping macmini2.local
PING macmini2.local (192.168.1.159) 56(84) bytes of data.
64 bytes from 192.168.1.159 (192.168.1.159): icmp_seq=1 ttl=64 time=0.675 ms
64 bytes from 192.168.1.159 (192.168.1.159): icmp_seq=2 ttl=64 time=0.374 ms

發布 service

avahi-publish-service SERVICE-NAME _APPLICATIONPROTOCOL._TRANPOSRT-PROTOCOL PORT "DESCRIPTION" --sub SUBPROTOCOL

ex:

avahi-publish-service light _coap._udp 5683 “/mylight” --sub
_floor1._sub._coap._udp

發布 service name: light,使用 CoAP protocol,在 UDP 5683 提供服務

該 service 可透過 _coap._udp.local 及 _floor1._sub._coap._udp.local 被發現

References

UWP - mDNS 找尋附近的設備

MDNS/DNS-SD TUTORIAL

使用 mDNS 在區域網中輕鬆發現系統

Bonjour手把手搭建一:mDNS(apple & multicastdns.org)

區域網設備發現之Bonjour協議