Score:-2

How to discover HTTPS servers on local network with certificate for particular hostname

fr flag

I am making a network-connected device (using Raspberry Pi 4 inside), and I would like a way for these devices to discover each other (when on the same local subnet). I am vaguely aware of protocols like SSDP / UPnP which can help with things like this, but the complexity and security concerns lead me to believe that that is not the best option.


Update: The feedback I have gotten so far suggests that mDNS & DNS-SD, implemented in existing software like avahi, are far preferable tools for this job. In the process of learning about these, I am finding the following links helpful (if you have more please add them in an answer or comment!):


All of the devices that I am making are running an HTTPS server (nginx) listening on tcp/443 and configured with a (legitimate) certificate valid for hostnames like www.example.com and *.example.com (where example.com is replaced with my own domain name).

The way I am currently trying to support this peer discovery feature is like this:

  1. User connects to web interface of one device (e.g. by knowing the IP a priori)
  2. User triggers "discover peers" feature (e.g. HTTP/WebSockets request)
  3. Device uses nmap's ssl-cert script to scan to identify peers like this:
    nmap --script ssl-cert --script-args=tls.servername=www.example.com <local network>
    
  4. Output is collected, parsed, and filtered then resulting IP address list is displayed to the user.

First off, are there alternative ways of doing this that might be "better" (less "invasive" / noisy, more reliable, etc.)?

Secondly, the output from the nmap command listed in step 3 is hard to parse. It looks something like this (targeting known test server here):

# 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

If I enable -oG for greppable output it seems that the certificate information gets omitted. (If there is a way to change that I would like to know about it.) So instead I tried piping to grep with the "lines before" option like nmap ...|grep -B 5 "ssl-cert: Subject: commonName=\*.example.com"| and then grepping again and using awk to select only the hostname/IP address. The result is like this:

#!/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']

Since I was just trying to get this to work I suspect there is a better / more elegant approach to this out there. Would anyone be willing to provide feedback, suggestions, etc.?

jacobq avatar
fr flag
Please help me understand how to improve this question. I put a significant amount of time and effort into it and thought it was clear. Too wordy? Too ignorant of service discovery technologies?
cn flag
It's perfectly acceptable to answer your own question (there is even a badge for it), in this case it probably would be better than editing it in such a way to dramatically change it's nature.
jacobq avatar
fr flag
I do not think that my edit changed the nature of the question. I am trying to solve exactly the same problem and so far have two candidate solutions but am not thrilled with either of them. However, I will consider your suggestion of writing up an answer if a more helpful one doesn't get posted soon.
Score:0
cn flag

Just use ssdp/mdns to discover, then try and connect to check the certificate exists and verifies

jacobq avatar
fr flag
If I understand correctly, this requires setting up another service (SSDP/MDNS) on each device and adding a firewall rule to allow it in, correct? And the advantage is that it is more efficient (multi-cast vs. brute-force unicast scan) and might able to span multiple subnets. Is that right?
cn flag
1) why reinvent the wheel 2) anything brute force scanning the network is likely to get flagged as hostile on anything other than a home lan
jacobq avatar
fr flag
1) to use existing firewall configuration and available utilities (already have nmap available on the image) and not need to learn something new (have never used these other discovery tools though am open to trying), 2) yes, though showing the user a warning first will be sufficient in this case, especially since this "scanning" is equivalent to opening a bunch of web browser tabs.
jacobq avatar
fr flag
Can you share more information about how to do what you describe? I am exploring using `avahi` for the first time, which seems like it might do this, but I've never used it before. There seem to be many related technologies (e.g. zeroconf, Bonjour, mDNS, DNS-SD, and RFC 3927/IPv4LL), but it's a lot to take in at once, and I'm not sure where to begin.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.