Tại sao các kết nối TCP IPv4 hiển thị dưới dạng tcp6?


30

Đây là đầu ra của netsat -tupnmáy chủ Debian Jessie của tôi:

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 là công cụ sao lưu CrashPlan , phiên bản Java 1.7.0_45. Hai địa chỉ IPv4 không phải RFC1918 là máy chủ của CrashPlan và 10.0.0.20:64702là máy tính của tôi chạy máy khách.

Tại sao ba kết nối cuối cùng hiển thị là tcp6 mặc dù chúng là địa chỉ IPv4?

Câu trả lời:


33

Điều này đang xảy ra bởi vì theo mặc định, các ổ cắm AF_INET6 sẽ thực sự hoạt động cho cả IPv4 và IPv6. Xem phần 3.7 - Khả năng tương thích với các nút IPv4 của RFC 3493 - Tiện ích mở rộng giao diện ổ cắm cơ bản cho IPv6

Dưới đây là một ví dụ ngắn về mã có thể tạo ra loại tình huống này:

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

Đầu ra trên máy Ubuntu của tôi là:

$ 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
$ 
  • Các tcp6 LISTENentry là cho nghe ổ cắm trên cổng 5555. Lưu ý rằng nó là một ổ cắm AF_INET6, vì vậy nó sẽ chấp nhận cả IPv4 và IPv6 kết nối đến.
  • Các tcp ESTABLISHEDentry là kết quả của việc kết nối một ổ cắm AF_INET4 cho người nghe (kết nối đang hoạt động).
  • Các tcp6 ESTABLISHEDentry là cho kết nối thụ động sinh ra từ các ổ cắm nghe. Nó hiện lên như tcp6, vì nó được sinh ra từ một tcp6người nghe; tuy nhiên, nó đại diện cho một kết nối từ một IPv4.

Đáng chú ý của nó như sau:

  • Hành vi này là đặc biệt đối với ổ cắm AF_INET6. Ổ cắm AF_INET (IPv4) đơn giản là không thể và sẽ không đối phó với bất kỳ điều gì IPv6.
  • Hành vi này có thể được ghi đè bằng tùy chọn ổ cắm IPV6_V6ONLY . Đặt tùy chọn này sẽ khiến ổ cắm chỉ xử lý IPv6 và không cho phép bất cứ thứ gì IPv4.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.