IPv4 TCP 연결이 tcp6으로 표시되는 이유는 무엇입니까?


30

netsat -tupn내 데비안 Jessie 서버 의 출력 결과는 다음과 같습니다 .

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은 CrashPlan 백업 엔진, Java 버전 1.7.0_45입니다. 두 개의 비 RFC1918 IPv4 주소는 CrashPlan의 서버이며 10.0.0.20:64702클라이언트를 실행하는 내 컴퓨터입니다.

마지막 세 개의 연결이 IPv4 주소인데도 왜 tcp6으로 표시됩니까?

답변:


33

기본적으로 AF_INET6 소켓은 실제로 IPv4 및 IPv6 모두에서 작동하기 때문에 발생합니다. 참조 3.7 절을 - IPv6에 대한 기본 소켓 인터페이스 확장 - RFC 3493의 IPv4의 노드와의 호환성

이러한 상황을 생성 할 수있는 간단한 코드 예제는 다음과 같습니다.

#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);
}

내 우분투 컴퓨터의 출력은 다음과 같습니다

$ 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
$ 
  • tcp6 LISTEN항목은 포트의 소켓 청취가 모두 IPv4 및 IPv6 들어오는 연결을 받아 들일 것입니다 그래서, AF_INET6 소켓 것을 5555 주입니다.
  • tcp ESTABLISHED항목은 AF_INET4 소켓을 리스너에 연결 한 결과입니다 (활성 연결).
  • tcp6 ESTABLISHED항목은 리스너 소켓에서 양산 수동 연결을위한 것입니다. 리스너 tcp6에서 스폰되기 때문에 로 표시됩니다 tcp6. 그러나 IPv4에서의 연결을 나타냅니다.

다음을 주목할 가치가 있습니다.

  • 이 동작은 AF_INET6 소켓에 특별합니다. AF_INET (IPv4) 소켓은 IPv6을 처리 할 수 ​​없으며 처리 할 수 ​​없습니다.
  • 이 동작은 IPV6_V6ONLY 소켓 옵션 으로 재정의 될 수 있습니다 . 이 옵션을 설정하면 소켓이 IPv6 처리하고 IPv4는 허용하지 않습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.