30

Here's the output of netsat -tupn on my Debian Jessie server:

Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 10.0.0.12:445           10.0.0.20:49729         ESTABLISHED 26277/smbd      
tcp        0      0 10.0.0.12:443           10.0.0.21:44162         ESTABLISHED 1400/nginx: worker 
tcp        0      0 10.0.0.12:445           10.0.0.21:46650         ESTABLISHED 23039/smbd      
tcp        0      0 10.0.0.12:443           10.0.0.20:54584         ESTABLISHED 1400/nginx: worker 
tcp        0      0 10.0.0.12:139           10.0.0.225:10425        ESTABLISHED 23701/smbd      
tcp        0      0 10.0.0.12:445           10.0.0.217:49179        ESTABLISHED 21535/smbd      
tcp        0      0 10.0.0.12:445           10.0.0.217:49178        ESTABLISHED 21534/smbd      
tcp        0      0 10.0.0.12:445           10.0.0.20:64636         ESTABLISHED 21470/smbd      
tcp        0      0 10.0.0.12:443           10.0.0.21:44198         ESTABLISHED 1400/nginx: worker 
tcp        0      0 10.0.0.12:2049          10.0.0.16:752           ESTABLISHED -               
tcp        0      0 10.0.0.12:222           10.0.0.21:55514         ESTABLISHED 23111/sshd: redacted
tcp6       0      0 10.0.0.12:4243          10.0.0.20:64702         ESTABLISHED 31307/java      
tcp6       0      0 10.0.0.12:48932         162.222.40.93:443       ESTABLISHED 31307/java      
tcp6       0      0 10.0.0.12:49093         216.17.8.47:443         ESTABLISHED 31307/java 

PID 31307 is the CrashPlan backup engine, Java version 1.7.0_45. The two non-RFC1918 IPv4 addresses are CrashPlan's servers and 10.0.0.20:64702 is my computer running the client.

Why do the last three connections show as tcp6 even though they're IPv4 addresses?

33

This is happening because by default, AF_INET6 sockets will actually work for both IPv4 and IPv6. See section 3.7 - Compatibility with IPv4 Nodes of RFC 3493 - Basic Socket Interface Extensions for IPv6

Here is a short example of code that can produce this sort of situation:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define TEST_PORT 5555

#define xstr(s) str(s)
#define str(x) #x

int main (int argc, char **argv)
{
    int v6server;
    int v4client;
    int rc;

    struct sockaddr_in6 s6addr = {
        .sin6_family = AF_INET6,
        .sin6_flowinfo = 0,
        .sin6_port = htons(TEST_PORT),
        .sin6_addr = in6addr_any
    };

    struct sockaddr_in c4addr = {
        .sin_family = AF_INET,
        .sin_port = htons(TEST_PORT),
        .sin_addr = inet_addr("127.0.0.1")
    };

    // Open an IPv6 listener
    v6server = socket(AF_INET6, SOCK_STREAM, 0);
    if (v6server < 0) perror("socket()");

    rc = bind(v6server, (struct sockaddr *)&s6addr, sizeof(s6addr));
    if (rc != 0) perror("bind()");

    rc = listen(v6server, 0);
    if (rc != 0) perror("listen()");

    // Connect to the listener with an IPv4 socket
    v4client = socket(AF_INET, SOCK_STREAM, 0);
    if (v4client < 0) perror("socket()");

    rc = connect(v4client, (struct sockaddr *)&c4addr, sizeof(c4addr));
    if (rc != 0) perror("connect()");

    // inspect open sockets
    system("netstat -tan | grep " xstr(TEST_PORT));

    close(v4client);
    close(v6server);
}

The output on my Ubuntu machine is:

$ make v4v6
cc     v4v6.c   -o v4v6
$ ./v4v6 
tcp        0      0 127.0.0.1:46518         127.0.0.1:5555          ESTABLISHED
tcp6       0      0 :::5555                 :::*                    LISTEN     
tcp6       0      0 127.0.0.1:5555          127.0.0.1:46518         ESTABLISHED
$ 
  • The tcp6 LISTEN entry is for the socket listening on port 5555. Note that it is an AF_INET6 socket, so it will accept both IPv4 and IPv6 incoming connections.
  • The tcp ESTABLISHED entry is the result of connecting an AF_INET4 socket to the listener (active connection).
  • The tcp6 ESTABLISHED entry is for the passive connection spawned from the listener socket. It shows up as tcp6, since it is spawned from a tcp6 listener; however it represents a connection from an IPv4.

Its worth noting the following:

  • This behavior is special to AF_INET6 sockets. AF_INET (IPv4) sockets simply cannot and will not deal with anything IPv6.
  • This behavior may be overridden with the IPV6_V6ONLY socket option. Setting this option will cause the socket to only handle IPv6 and not allow anything IPv4.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.