我正在制作一个网络连接设备(内部使用 Raspberry Pi 4),并且我希望这些设备能够发现彼此(当位于同一本地子网时)。我隐约知道 SSDP / UPnP 等协议可以帮助解决此类问题,但复杂性和安全问题使我相信这不是最好的选择。
更新:我目前收到的反馈表明移动DNS&DNS-SD,在现有软件中实现avahi
,是这项工作更可取的工具。在了解这些内容的过程中,我发现以下链接很有帮助(如果您有更多链接,请在答案或评论中添加它们!):
- avahi 守护进程是什么?
- 如何使用 Avahi 来宣传 HTTP 服务
- P2P 对等点发现
- Flutter/Multicast DNS:如何使用 MDNS 测试网络发现
- avahi、zeroconf、mdns + mqtt 网络
我制作的所有设备都运行一个 HTTPS 服务器(nginx),监听 tcp/443,并配置了对主机名有效的(合法)证书www.example.com
(*.example.com
其中 example.com 替换为我自己的域名)。
我目前尝试支持此对等发现功能的方式如下:
- 用户连接到一个设备的 Web 界面(例如,通过预先了解 IP)
- 用户触发“发现对等点”功能(例如 HTTP/WebSockets 请求)
- 设备用途
nmap
的ssl-cert
剧本像这样扫描来识别同伴:nmap --script ssl-cert --script-args=tls.servername=www.example.com <local network>
- 收集、解析和过滤输出,然后向用户显示生成的 IP 地址列表。
首先,是否有其他可能“更好”(更少“侵入性”/噪音、更可靠等)的方法可以做到这一点?
其次,步骤 3 中列出的 nmap 命令的输出很难解析。它看起来像这样(此处针对已知的测试服务器):
# nmap -p 443 --script ssl-cert --script-args=tls.servername=www.example.com 192.168.1.40
Starting Nmap 7.80 ( https://nmap.org ) at 2023-03-08 13:20 CST
Nmap scan report for 192.168.1.40
Host is up (0.00017s latency).
PORT STATE SERVICE
443/tcp open https
| ssl-cert: Subject: commonName=*.example.com
| Subject Alternative Name: DNS:*.example.com, DNS:example.com
| Issuer: commonName=...
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2022-06-08T00:00:00
| Not valid after: 2023-07-09T23:59:59
| MD5: ...
|_SHA-1: ...
Nmap done: 1 IP address (1 host up) scanned in 0.90 seconds
如果我启用-oG
greppable 输出,证书信息似乎会被忽略。(如果有办法改变这种情况,我很想知道。)因此,我尝试使用“行前”选项通过管道传输到 grep,nmap ...|grep -B 5 "ssl-cert: Subject: commonName=\*.example.com"|
然后再次 grep 并使用 awk 仅选择主机名/IP 地址。结果如下:
#!/bin/bash
NMAP=/usr/bin/nmap
HOSTNAME="www.example.com"
TCP_PORT_FOR_HTTPS=443
DESIRED_COMMON_NAME="\*.example.com"
TARGET="192.168.1.30-100"
# Attempt TLS handshake with each host specified by TARGET, using SNI to request HOSTNAME
# Filter results for hosts with certificates matching DESIRED_COMMON_NAME
RESULTS=$($NMAP -p $TCP_PORT_FOR_HTTPS --script ssl-cert --script-args=tls.servername=$HOSTNAME $TARGET \
|grep -B 5 "Subject: commonName=$DESIRED_COMMON_NAME" \
|grep "Nmap scan report for" \
|awk '{split($0, array, "Nmap scan report for "); print "\x27"array[2]"\x27"}' \
)
# Output as JSON array: "'x.x.x.x' 'y.y.y.y'" --> "['x.x.x.x','y.y.y.y']"
echo "[$(echo -n $RESULTS|tr ' ' ,)]"
# Example output: ['192.168.1.37','192.168.1.43','192.168.1.40']
由于我只是想让它发挥作用,我怀疑有更好/更优雅的方法。有人愿意提供反馈、建议等吗?
答案1
只需使用 ssdp/mdns 进行发现,然后尝试连接以检查证书是否存在并验证