Reliable (cryptographic) way to verify a devices public IP address behind a NAT

85 Views Asked by At

I am writing a relatively small bash script that is supposed to update DNS records for a server behind a NAT which might change its external IP address. Essentially a free DynDNS using my DNS provider's API.

I am retrieving the server's IP address using a simple query to an external service. But for the sake of security, before pointing my DNS A record to a new arbitrary IP address given to my by an external service I first need to verify that this indeed is the server's IP address. And this check would need to involve a cryptography step since an active MITM attack could be taking place and just forwarding traffic to the server's real IP address.

So what would be the simplest way (if possible through bash) to verify that this is indeed the server's IP address?

2

There are 2 best solutions below

5
symcbean On

I presume you mean that the bash script is running somewhere other than the server whose IP you need to determine?

The obvious solution would be to connect using ssh with strict host checking (and a remembered server key) or via SSL with certificate versification (you could use a self-signed certificate). The former is a bit easier to do out of the box.

0
Itay Grudev On

Assuming that $IP is the server's new external IP address, this works by first acquiring the servers SSH keys by running ssh-keyscan on localhost and generating a temporary known hosts file. It then substitutes 127.0.0.1 with the given $IP and initiates an ssh session with the temporary known hosts file to the remote IP address. If the session is established and the key verification is successful the command will exit cleanly. Otherwise it will output the Host key verification failed. message. This will work even if authentication with the server fails as host key verification is done before authentication. The script finally checks whether the ssh output includes the given error message and returns valid or invalid correspondingly.

TMP_KNOWN_HOSTS=$(mktemp)
ssh-keyscan 127.0.0.1 > $TMP_KNOWN_HOSTS
sed -i "s/127\.0\.0\.1/$IP/" $TMP_KNOWN_HOSTS
RESPONSE=$(ssh -n -o "UserKnownHostsFile $TMP_KNOWN_HOSTS" -o "StrictHostKeyChecking yes" $IP true 2>&1)

if ! [[ $RESPONSE = *"Host key verification failed."* ]]; then
  echo "valid"
else
  echo "invalid"
fi