Avahi 是一套使應用程式能夠公布或發現區域網上運行的服務和主機的系統
Avahi 啟動時,需要依賴 D-Bus
目的:找尋區域網路服務或設備
先了解知識:mDNS (Multicast DNS) 和 DNS-SD (DNS-based Service Discovery)
mDNS 就是對區網做「廣播」而廣播的內容則是我們熟悉的 DNS Query
DNS-SD -- 參考網頁中的「根據 DNS-SD 篩選出 Airplay / Chromecast 裝置」
Zeroconf 全稱為 Zero configuration networking,中文名則為零配置網路服務規範,是一種用於自動生成可用IP地址的網路技術,不需要額外的手動配置和專屬的配置伺服器。
精神在於希望把網路設定這件事情自動化,達到零設定(無須手動設定)的目的
主要是定義了三個層次
1. 指派位址(Address Selection)- 不需利用 dhcp server 取得 裝置地址如 IP 的相關資料
RFC 3927 , Dynamic Configuration of IPv4 Link-Local Addresses
2. 名稱解析(Name Resolution) - 不需要通過 DNS server 就轉換 domain name 和 IP 的關係
3. 服務搜尋(Service Discovery)- 利用 DNS-SD 來取得裝置服務,而不需通過 directory server
DNS-based Service Discovery, or DNS-SD.
- DNS-SD 的 FQDN 結構
- DNS-SD 會使用的 Record
Apple 的 zeroconf 協議技術實現 – Bonjour
apple 的 airplay,airprint 都是依賴了zeroconf 的基礎上,才展現出強大的功能
例子說明:
使用者擁有一臺apple tv和一臺iPhone4s,那之只要都連入到同一個無線區域網內,iphone4s就會自動找出apple tv,那麼在播放音樂或者視訊時候,使用者只要點選推送,就可以講音樂和視訊推送到apple tv上播放。
開源的 zeroconf 協議技術實現 – Avahi
Avahi 是 Zeroconf 規範的開源實現,可以分成 server 以及 client
server 的部份主要是要告訴大家你自己是誰, 提供區網有什麼服務
client 的部份主要是用來聽廣播, 取得區網上所有可使用的服務
環境
version: avahi-daemon (0.8-5ubuntu5)
johnnysu@johnnysu-VirtualBox:/etc/avahi/services$ ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.114 netmask 255.255.255.0 broadcast 192.168.50.255
inet6 fe80::49b2:8ba6:6532:9d0e prefixlen 64 scopeid 0x20<link>
ether 08:00:27:75:08:d1 txqueuelen 1000 (Ethernet)
RX packets 172828 bytes 65464536 (65.4 MB)
RX errors 21 dropped 0 overruns 0 frame 0
TX packets 17493 bytes 1902108 (1.9 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 19 base 0xd020
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 9106 bytes 919852 (919.8 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 9106 bytes 919852 (919.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ubuntu 安裝 avahi
avahi-utils - Avahi browsing, publishing and discovery utilities
sudo apt-get install avahi-daemon avahi-utils
查詢是否啟動
johnnysu@johnnysu-VirtualBox:~$ systemctl list-units --all | grep -E "dbus|avahi-daemon"
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
dbus.service loaded active running D-Bus System Message Bus
getty-static.service loaded inactive dead getty on tty2-tty6 if dbus and logind are not available
avahi-daemon.socket loaded active running Avahi mDNS/DNS-SD Stack Activation Socket
dbus.socket loaded active running D-Bus System Message Bus Socket
查詢監聽
johnnysu@johnnysu-VirtualBox:~/airplay$ sudo netstat -tlunp | grep avahi
udp 0 0 0.0.0.0:5353 0.0.0.0:* 5357/avahi-daemon:
udp 0 0 0.0.0.0:49226 0.0.0.0:* 5357/avahi-daemon:
udp6 0 0 :::5353 :::* 5357/avahi-daemon:
udp6 0 0 :::52810 :::* 5357/avahi-daemon:
設定檔
/etc/avahi/avahi-daemon.conf
[server]
host-name=johnny
domain-name=local
如果有設定 ipv6=no 的話,
use-ipv6=no
以下就會沒有
udp6 0 0 :::5353 :::* 5357/avahi-daemon:
udp6 0 0 :::52810 :::* 5357/avahi-daemon:
重新啟動
sudo systemctl restart avahi-daemon
找另一台主機確定 mDNS server 是否通
wolfe@wolfe-VirtualBox:~/work/UxPlay-master$ ping johnny.local
PING johnny.local (192.168.50.114) 56(84) bytes of data.
64 bytes from 192.168.50.114 (192.168.50.114): icmp_seq=1 ttl=64 time=27.8 ms
64 bytes from 192.168.50.114 (192.168.50.114): icmp_seq=2 ttl=64 time=18.1 ms
64 bytes from 192.168.50.114 (192.168.50.114): icmp_seq=3 ttl=64 time=2.33 ms
register an mDNS/DNS-SD service 有 2 種方式
1. 透過 avahi-publish 方式 register an mDNS/DNS-SD service
avahi-publish -s [options] name service-type port [TXT data ...]
avahi-publish-service [options] name service-type port [TXT data ...]
avahi-publish -s "My service" _myservic._tcp 1234
johnnysu@johnnysu-VirtualBox:/etc/avahi/services$ avahi-browse -a -r
= enp0s3 IPv4 My service _myservic._tcp local
hostname = [johnny.local]
address = [192.168.50.114]
port = [1234]
txt = []
2. 編寫你自己的服務 (提供 DNS-SD 會使用的 Record)
預設是放在 /etc/avahi/services
johnnysu@johnnysu-VirtualBox:/etc/avahi/services$ ls
ftp.service smb.service
ftp.service
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">FTP</name>
<service>
<type>_ftp._tcp</type>
<host-name>ftp.johnny.local</host-name>
<port>21</port>
<txt-record>path=/share</txt-record>
<txt-record>u=guest</txt-record>
<txt-record>p=pass</txt-record>
</service>
</service-group>
smb.service
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">Samba</name>
<service>
<type>_smb._tcp</type>
<host-name>smb.johnny.local</host-name>
<port>445</port>
<txt-record>path=/share</txt-record>
<txt-record>u=guest</txt-record>
<txt-record>p=pass</txt-record>
</service>
</service-group>
其它細節可以參考這裡 http://manpages.ubuntu.com/manpages/precise/man5/avahi.service.5.html
Service type 定義在 avahi/service-type-database/service-types 根據 DNS SRV (RFC 2782) Service Types
_ftp._tcp:FTP File Transfer
_airplay._tcp:AirPlay Remote Video
Finished register an mDNS/DNS-SD service,設定 host name/address mapping
avahi 預設會為 hosts 的 IP 去反查域名,所以不能多個 domain name 指向同 1 個 IP
設定 host name 對映 address (擇一)
way1
sudo vim /etc/avahi/hosts
192.168.50.114 ftp.johnny.local
way2 (一定要有 .local)
/usr/local/bin/avahi-add-names.sh
/usr/bin/avahi-publish -a -R ftp.johnny.local 192.168.50.114 > /dev/null 2>&1 &
/usr/bin/avahi-publish -a -R smb.johnny.local 192.168.50.115 > /dev/null 2>&1 &
chmod +x /usr/local/bin/avahi-add-names.sh
sed -i '/ExecStart/aExecStartPost=\/usr\/local\/bin\/avahi-add-names\.sh' /lib/systemd/system/avahi-daemon.service
sudo systemctl daemon-reload
啟動,擇一
1. sudo /etc/init.d/avahi-daemon start
2. sudo systemctl start avahi-daemon
查看狀況
johnnysu@johnnysu-VirtualBox:~/airplay/test-avahi$ sudo systemctl status avahi-daemon
● avahi-daemon.service - Avahi mDNS/DNS-SD Stack
Loaded: loaded (/lib/systemd/system/avahi-daemon.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2022-12-27 17:01:49 CST; 2s ago
TriggeredBy: ● avahi-daemon.socket
Process: 6718 ExecStartPost=/usr/local/bin/avahi-add-names.sh (code=exited, status=0/SUCCESS)
Main PID: 6716 (avahi-daemon)
Status: "avahi-daemon 0.8 starting up."
Tasks: 4 (limit: 4626)
Memory: 1.6M
CPU: 23ms
CGroup: /system.slice/avahi-daemon.service
├─6716 "avahi-daemon: running [johnnysu-VirtualBox.local]"
├─6717 "avahi-daemon: chroot helper"
├─6719 /usr/bin/avahi-publish -a -R ftp.johnny.local 192.168.50.114
└─6720 /usr/bin/avahi-publish -a -R smb.johnny.local 192.168.50.115
十二 27 17:01:49 johnnysu-VirtualBox avahi-daemon[6716]: Network interface enumeration completed.
十二 27 17:01:49 johnnysu-VirtualBox avahi-daemon[6716]: Registering new address record for fe80::49b2:8ba6:6532:9d0e on enp0s3.*.
十二 27 17:01:49 johnnysu-VirtualBox avahi-daemon[6716]: Registering new address record for 192.168.50.114 on enp0s3.IPv4.
十二 27 17:01:49 johnnysu-VirtualBox avahi-daemon[6716]: Registering new address record for ::1 on lo.*.
十二 27 17:01:49 johnnysu-VirtualBox avahi-daemon[6716]: Registering new address record for 127.0.0.1 on lo.IPv4.
十二 27 17:01:49 johnnysu-VirtualBox systemd[1]: Started Avahi mDNS/DNS-SD Stack.
十二 27 17:01:49 johnnysu-VirtualBox avahi-daemon[6716]: Server startup complete. Host name is johnnysu-VirtualBox.local. Local service cookie is 2433229662.
十二 27 17:01:50 johnnysu-VirtualBox avahi-daemon[6716]: Service "FTP" (/services/ftp.service) successfully established.
十二 27 17:01:50 johnnysu-VirtualBox avahi-add-names.sh[6720]: Established under name 'smb.johnny.local'
十二 27 17:01:50 johnnysu-VirtualBox avahi-add-names.sh[6719]: Established under name 'ftp.johnny.local'
立即測試的話,可用:nohup ./avahi-add-names.sh
以下用 client 來測試
使用 avahi-browse 測試
wolfe@wolfe-VirtualBox:~/work/UxPlay-master$ avahi-browse -r -t _ftp._tcp
+ enp0s3 IPv4 FTP FTP File Transfer local
= enp0s3 IPv4 FTP FTP File Transfer local
hostname = [ftp.johnny.local]
address = [192.168.50.114]
port = [21]
txt = ["p=pass" "u=guest" "path=/share"]
FTP File Transfer local= enp0s3 IPv4 FTP
FTP File Transfer local
hostname = [ftp.johnny.local]
address = [192.168.50.114]
port = [21]
txt = ["p=pass" "u=guest" "path=/share"]
Johnnysu@johnnysu-VirtualBox:~$ avahi-browse -r -t _smb._tcp
+ enp0s3 IPv4 JOHNNYSU-VIRTUALBOX Microsoft Windows Network local
+ lo IPv4 JOHNNYSU-VIRTUALBOX Microsoft Windows Network local
= enp0s3 IPv4 JOHNNYSU-VIRTUALBOX Microsoft Windows Network local
hostname = [johnny.local]
address = [192.168.50.114]
port = [445]
txt = []
= lo IPv4 JOHNNYSU-VIRTUALBOX Microsoft Windows Network local
hostname = [johnny.local]
address = [127.0.0.1]
port = [445]
txt = []
其它指令:
##發現所有已註冊的服務
avahi-browse -a -r
使用 dig 測試服務是否活著
成功
johnnysu@johnnysu-VirtualBox:/etc/avahi/services$ dig -p 5353 @192.168.50.114 ftp.johnny.local
; <<>> DiG 9.18.1-1ubuntu1.1-Ubuntu <<>> -p 5353 @192.168.50.114 ftp.johnny.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34416
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;ftp.johnny.local. IN A
;; ANSWER SECTION:
ftp.johnny.local. 10 IN A 192.168.50.114
;; Query time: 0 msec
;; SERVER: 192.168.50.114#5353(192.168.50.114) (UDP)
;; WHEN: Tue Dec 27 17:24:30 CST 2022
;; MSG SIZE rcvd: 50
因為沒有 192.168.50.115 server,所以沒找到
johnnysu@johnnysu-VirtualBox:/etc/avahi/services$ dig -p 5353 @192.168.50.115 _smb._tcp.local ptr
; <<>> DiG 9.18.1-1ubuntu1.1-Ubuntu <<>> -p 5353 @192.168.50.115 _smb._tcp.local ptr
; (1 server found)
;; global options: +cmd
;; connection timed out; no servers could be reached
使用 nmap 測試
johnnysu@johnnysu-VirtualBox:~$ sudo nmap -Pn -sUC -p5353 192.168.50.114
Starting Nmap 7.80 ( https://nmap.org ) at 2022-12-28 10:03 CST
Nmap scan report for johnnysu-VirtualBox (192.168.50.114)
Host is up (0.000072s latency).
PORT STATE SERVICE
5353/udp open zeroconf
| dns-service-discovery:
| 21/tcp ftp
| Address=192.168.50.114
| 445/tcp smb
| Address=192.168.50.114 fe80::49b2:8ba6:6532:9d0e
| Device Information
|_ Address=192.168.50.114 fe80::49b2:8ba6:6532:9d0e