Please enable JavaScript to view the comments powered by Disqus.

AF_INET6 Sockets Can Accept Connections From IPv4 Addresses

In Problems When Setting Up WriteFreely Part 2: Firewall, I posed an unanswered question:

Why did netstat not show me processes listening to port 80 & 443, yet I was able to make an HTTP request to port 80?

In that post, I showed a netstat output as follows:

[email protected]:~$ netstat -t4lpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:33060         0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -       

I wanted to confirm that my WriteFreely instance was listening to port 80 & 443. But, the above output didn't give me the answer I sought. I didn't see anything listening on port 80, yet I was able to connect to that port successfully!

I only focused on IPv4 at the time because I thought I was connecting to the IPv4 interface of my server. After all, my server wasn't assigned a public IPv6 address. teddyh.dev only has an A record containing the IPv4 address of my server.

Later, I did more research on this seemingly odd phenomenon. I stumbled upon this SO post. Apparently, AF_INET6 sockets can receive connections from IPv4 addresses!

Had I used sudo netstat -tlpn instead, I would have seen the following output:

[email protected]:~$ sudo netstat -tlpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      459/systemd-resolve 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      707/sshd: /usr/sbin 
tcp        0      0 127.0.0.1:33060         0.0.0.0:*               LISTEN      644/mysqld          
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      644/mysqld          
tcp6       0      0 :::22                   :::*                    LISTEN      707/sshd: /usr/sbin 
tcp6       0      0 :::443                  :::*                    LISTEN      140750/writefreely  
tcp6       0      0 :::80                   :::*                    LISTEN      140750/writefreely

This output gave way more insights than the netstat -t4lpn. The last 2 lines showed that WriteFreely was listening to :::80 & :::443. That would have given me some clue about this probable relationship between IPv6 sockets and IPv4 client addresses.

To further demonstrate this compatibility, I used telnet to open a TCP connection to my server.

My home PC:

╭─teddy@teddy-ubuntu ~ 
╰─$ telnet teddyh.dev 443                                                                                                                                                                                    130 ↵
Trying 54.151.219.0...
Connected to teddyh.dev.
Escape character is '^]'.

My blog server:

[email protected]:~$ sudo netstat -t6apn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp6       0      0 :::22                   :::*                    LISTEN      707/sshd: /usr/sbin 
tcp6       0      0 :::443                  :::*                    LISTEN      140750/writefreely  
tcp6       0      0 :::80                   :::*                    LISTEN      140750/writefreely            
tcp6       0      0 172.31.29.106:443       A.B.C.D:36134     ESTABLISHED 140750/writefreely  

I have redacted my home IP address above to A.B.C.D. Notice that both the local & foreign addresses are IPv4. 172.31.29.106 is the private IPv4 address of my server, NAT'ed from the public IPv4 address 54.151.219.0 shown in the output of the telnet command.

The above experiment proves that AF_INET6 sockets are compatible with IPv4 addresses. That said, that compatibility can be overridden by setting the IPV6_V6ONLY option, as pointed out in the linked SO post.