The other day I wanted to verify whether a service running on my Linux server was listening on IPv6 as well as IPv4. It turned out that it wasn’t that easy to answer – if at all.
Which ports are in the listening state? –> For this question I used netstat -tulpen for a couple of years now. It turned out, that netstat is kind of deprecated and that I should use ss for this. Same options: ss -tulpen:
- t: TCP
- u: UDP
- l: listening
- p: show the corresponding process
- e: extended (important, see below)
- n: numeric, that is: not resolving IP addresses (DNS PTR records) nor service names (“22” instead of “ssh”)
So, what’s the deal now?
In my case, I was trying to verify whether or not syslog-ng is listening on both IPs. I already knew that my SSH daemon was listening on both protocols. So this was the output (sorry, you have to scroll horizontally):
weberjoh@nb17-lx2:~$ sudo ss -tulpen Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1023,fd=3)) ino:22611 sk:3 <-> tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=1023,fd=4)) ino:22615 sk:4 v6only:1 <-> tcp LISTEN 0 128 *:514 *:* users:(("syslog-ng",pid=1877,fd=15)) ino:1753628 sk:4f v6only:0 <->
–> At a first glance, it looks like ssh is running for IPv4 and IPv6, while syslog-ng shows only one line here. In fact, it IS listening on both Internet Protocols as well. Note the “v6only:0” at the end which implies that this socket is also capable of IPv4. The IPv6 line from ssh reads “v6only:1” at the end. (This is what the -e option is all about.)
In case you’re using netstat, this is the output there. It shows “tcp6” for syslog-ng which is even more inaccurate as it implies “only v6” to my mind:
weberjoh@nb17-lx2:~$ sudo netstat -tulpen Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 22611 1023/sshd tcp6 0 0 :::22 :::* LISTEN 0 22615 1023/sshd tcp6 0 0 :::514 :::* LISTEN 0 1753628 1877/syslog-ng
It’s even getting weirder when listing IPv4 services only, because it does not show the “v6only:0” line at all, hence omitting the syslog-ng daemon completely, while it IS listening on IPv4:
weberjoh@nb17-lx2:~$ sudo ss -tulpen4 Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1023,fd=3)) ino:22611 sk:3 <->
Twitter user Flüpke gave the following explanation: “Sockets bound to in6addr_any on Linux will receive IPv4 mapped traffic if the sockopt IPV6_V6ONLY is not set”. Uh, okay.
Note that this is not a specific “problem” from syslog-ng, but a generic approach on how to open sockets. Some years ago I encountered the same behaviour with ntopng.
By the way: Since I was really unsure whether the ports are open or not, I used Nmap from a machine in the same layer 3 subnet to check for both Internet Protocols:
pi@pi05-random:~ $ sudo nmap -Pn -sS -p 514 194.247.5.6 Starting Nmap 7.40 ( https://nmap.org ) at 2021-05-20 14:40 CEST Nmap scan report for 194.247.5.6 Host is up (0.00066s latency). PORT STATE SERVICE 514/tcp open shell MAC Address: 00:21:70:B2:0E:6C (Dell) Nmap done: 1 IP address (1 host up) scanned in 3.76 seconds pi@pi05-random:~ $ pi@pi05-random:~ $ pi@pi05-random:~ $ sudo nmap -Pn -sS -p 514 -6 2001:470:1f0b:16b0::b17:22 Starting Nmap 7.40 ( https://nmap.org ) at 2021-05-20 14:41 CEST Nmap scan report for 2001:470:1f0b:16b0::b17:22 Host is up (0.00083s latency). PORT STATE SERVICE 514/tcp open shell MAC Address: 00:21:70:B2:0E:6C (Dell) Nmap done: 1 IP address (1 host up) scanned in 1.23 seconds
To top it off
I wanted syslog-ng to listen on UDP and TCP on both Internet Protocols. Using this source statement:
source s_network { network ( ip-protocol(6) transport("udp") ); network ( ip-protocol(6) transport("tcp") ); };
I was able to get this:
weberjoh@nb17-lx2:~$ sudo ss -tulpen | grep syslog udp UNCONN 0 0 *:514 *:* users:(("syslog-ng",pid=20820,fd=15)) ino:2121626 sk:56 v6only:0 <-> tcp LISTEN 0 128 *:514 *:* users:(("syslog-ng",pid=20820,fd=83)) ino:2121627 sk:57 v6only:0 <->
But in the meantime, I recognized that my IPv4 machines (that send syslog message) were listed as “::ffff:192.168.3.53” and so on in my syslog folders. Twitter user Armin brought me to this RFC section “Compatibility with IPv4 Nodes”.
Then I tried to open the IPv4/IPv6 ports independently, which succeeded for UDP but not for TCP:
weberjoh@nb17-lx2:~$ sudo ss -tulpen | grep syslog udp UNCONN 0 0 0.0.0.0:514 0.0.0.0:* users:(("syslog-ng",pid=20887,fd=83)) ino:2123432 sk:58 <-> udp UNCONN 0 0 *:514 *:* users:(("syslog-ng",pid=20887,fd=15)) ino:2123431 sk:59 v6only:0 <-> tcp LISTEN 0 128 *:514 *:* users:(("syslog-ng",pid=20887,fd=84)) ino:2123433 sk:5a v6only:0 <->
Ouch. To my mind, this was incorrect anyway, since the second line shows “v6only:0” hence there were two different UDP sockets opened, both capable of IPv4.
Thanks to Twitter Users!
Thanks to my Twitter followers, who helped me out with this question. In the end, “I know that I know nothing”. Even after figuring it out for a couple of hours, I am not quite sure whether I understood it correctly… Any concerns from your site? Please leave a comment!
Photo by Franco Antonio Giovanella on Unsplash.