Testing for Remote Listener
Anyone know a good method for testing whether a remote UDP service is reachable - preferably without the use of netcat or similar tools? TCP-based listeners are easy enough to do a cursory test: TCP gives you a basic pass/fail on a socket open attempt. Thus, a test like:
for HOST in ${SERVERLIST}
do
printf "Attempting service-connect to ${HOST}...\n"
SOCKTEST=$(timeout 5 bash -c 'cat < /dev/null > \
/dev/tcp/${HOST}/53')$?
if [[ ${SOCKTEST} -eq 0 ]]
then
printf "Socket-test passed.\n"
else
printf "Socket-test failed.\n"
fi
done
Is a fairly quick way to ensure that (in this case) the guys who provisioned a system pointed it to reachable DNS servers (didn't fat-finger any entries in the DHCP zone).
Using the above method-type for UDP doesn't really work - you get false successes. The specific case I'm trying to verify is NTPD accessibility. Using ntpdate <SERVER> would be fine, but I'd need to do my tests like service ntpd stop ; <TESTS> ; service ntpd start. Could also use ntpq -c peers, but would really rather test servers individually rather than all at once. And, really, would overall prefer a generalizable method for UDP testing rather than having to do per-service test-definitions.
Any ideas?
Responses
UDP is a connectionless protocol, there is no reliable way of testing whether there is anything listening unless the listener replies to you.
You will sometimes get systems which reply with an "ICMP Destination Unreachable", but you'll also get firewalls which just drop with no ICMP reply.
As a UDP sender, you have no way of telling whether your data was read by an application or dropped by a firewall. That reliability of transmission is not a feature which UDP offers.
You might want to look into nmap, it's a network tool which contains a port scanner which can do this for large network ranges with a variety of protocols. It's available in the RHEL Server channel.
Well, you can do the same thing in bash:
$ echo "a" > /dev/udp/127.0.0.1/12345
$ echo $?
0
However what you're testing for with $? is that the message was delivered to the transmitting socket, which of course it was.
To intercept a possible "ICMP Destinaton Unreachable" you'd need to write something which listens back on the socket - essentially writing your own netcat/nmap.
If your aim is to test DNS servers, how about performing a lookup using dig @serverip example.com instead?
Writing a "listen back" isn't that hard.
Run this past your security team. Whilst I don't mean to speak poorly of your programming ability, I bet the collective authors of netcat have written a safer listener (which is more protected from buffer overflows and arbitrary code execution) than you or I could knock up for a quick service test :)
I got looking into this more, you can use bash to open an FD like so:
$ exec 3<> /dev/udp/127.0.0.1/12345
Now writing into the FD twice throws an error:
$ echo 1>&3
$ echo 1>&3
bash: echo: write error: Connection refused
Or you can read back from the socket and check for error:
$ echo 1>&3
$ while read 0<&3; do echo $REPLY; done
bash: read: read error: 0: Connection refused
Close the opened FD with:
$ exec 3>&-
Reference:
Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.
