如何使用特定主机名的证书在本地网络上发现 HTTPS 服务器

如何使用特定主机名的证书在本地网络上发现 HTTPS 服务器

我正在制作一个网络连接设备(内部使用 Raspberry Pi 4),并且我希望这些设备能够发现彼此(当位于同一本地子网时)。我隐约知道 SSDP / UPnP 等协议可以帮助解决此类问题,但复杂性和安全问题使我相信这不是最好的选择。


更新:我目前收到的反馈表明移动DNS&DNS-SD,在现有软件中实现avahi,是这项工作更可取的工具。在了解这些内容的过程中,我发现以下链接很有帮助(如果您有更多链接,请在答案或评论中添加它们!):


我制作的所有设备都运行一个 HTTPS 服务器(nginx),监听 tcp/443,并配置了对主机名有效的(合法)证书www.example.com*.example.com其中 example.com 替换为我自己的域名)。

我目前尝试支持此对等发现功能的方式如下:

  1. 用户连接到一个设备的 Web 界面(例如,通过预先了解 IP)
  2. 用户触发“发现对等点”功能(例如 HTTP/WebSockets 请求)
  3. 设备用途nmapssl-cert剧本像这样扫描来识别同伴:
    nmap --script ssl-cert --script-args=tls.servername=www.example.com <local network>
    
  4. 收集、解析和过滤输出,然后向用户显示生成的 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

如果我启用-oGgreppable 输出,证书信息似乎会被忽略。(如果有办法改变这种情况,我很想知道。)因此,我尝试使用“行前”选项通过管道传输到 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 进行发现,然后尝试连接以检查证书是否存在并验证

相关内容