Sockets 使用辅助IP地址连接套接字

Sockets 使用辅助IP地址连接套接字,sockets,tcp,routing,linux-kernel,ip,Sockets,Tcp,Routing,Linux Kernel,Ip,不久前,我能够通过以下步骤从给定接口上的主IP地址或辅助IP地址连接到给定的目标地址 使用IP addr add…向给定接口添加辅助IP地址 根据需要将套接字绑定到主地址或辅助地址 使用#2中绑定的主地址或辅助地址连接到目标ip地址 我最近将一台机器升级到了Linux3.3.6,但这台机器已经不能工作了,但我不记得我上一次尝试的版本是什么了。有人知道如何在更新的内核中做同样的事情吗?我刚刚在另一台机器上验证了2.6.23上的相同代码 更新2这似乎与NIC驱动程序有关。有了3.3.6和8139,一

不久前,我能够通过以下步骤从给定接口上的主IP地址或辅助IP地址连接到给定的目标地址

  • 使用
    IP addr add…
    向给定接口添加辅助IP地址
  • 根据需要将套接字绑定到主地址或辅助地址
  • 使用#2中绑定的主地址或辅助地址连接到目标ip地址
  • 我最近将一台机器升级到了Linux3.3.6,但这台机器已经不能工作了,但我不记得我上一次尝试的版本是什么了。有人知道如何在更新的内核中做同样的事情吗?我刚刚在另一台机器上验证了2.6.23上的相同代码

    更新2这似乎与NIC驱动程序有关。有了3.3.6和8139,一切都很好。同一台机器,但使用不同的NIC,并通过莱茵河,问题就出现了

    下面是我在3.3.6(从
    tshark
    后台运行的数据包捕获输出)上运行代码(末尾的源代码)时发生的情况:

    然后在第2.6.23节中进行同样的操作:

    $ ./bind_connect 10.0.0.123 10.0.0.226                                                                                                                                           >
    Bound socket: 10.0.0.226 [10.0.0.226->10.0.0.123]
    $ 231.566278   10.0.0.226 -> 10.0.0.123   TCP 54109 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=99922052 TSER=0 WS=5
    231.566448   10.0.0.123 -> 10.0.0.226   TCP http > 54109 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=7060755 TSER=99922052 WS=1
    231.566463   10.0.0.226 -> 10.0.0.123   TCP 54109 > http [ACK] Seq=1 Ack=1 Win=5856 Len=0 TSV=99922052 TSER=7060755
    231.566510   10.0.0.226 -> 10.0.0.123   TCP 54109 > http [FIN, ACK] Seq=1 Ack=1 Win=5856 Len=0 TSV=99922052 TSER=7060755
    231.566593   10.0.0.123 -> 10.0.0.226   TCP http > 54109 [ACK] Seq=1 Ack=2 Win=5792 Len=0 TSV=7060755 TSER=99922052
    231.566704   10.0.0.123 -> 10.0.0.226   TCP http > 54109 [FIN, ACK] Seq=1 Ack=2 Win=5792 Len=0 TSV=7060755 TSER=99922052
    231.566737   10.0.0.226 -> 10.0.0.123   TCP 54109 > http [ACK] Seq=2 Ack=2 Win=5856 Len=0 TSV=99922052 TSER=7060755
    
    $ ./bind_connect 10.0.0.123 10.0.0.126                                                                                                                                           >
    Bound socket: 10.0.0.126 [10.0.0.126->10.0.0.123]
    $ 235.824867   10.0.0.126 -> 10.0.0.123   TCP 34228 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=99926310 TSER=0 WS=5
    235.825185   10.0.0.123 -> 10.0.0.126   TCP http > 34228 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=7061180 TSER=99926310 WS=1
    235.825236   10.0.0.126 -> 10.0.0.123   TCP 34228 > http [ACK] Seq=1 Ack=1 Win=5856 Len=0 TSV=99926311 TSER=7061180
    235.825273   10.0.0.126 -> 10.0.0.123   TCP 34228 > http [FIN, ACK] Seq=1 Ack=1 Win=5856 Len=0 TSV=99926311 TSER=7061180
    235.825721   10.0.0.123 -> 10.0.0.126   TCP http > 34228 [ACK] Seq=1 Ack=2 Win=5792 Len=0 TSV=7061180 TSER=99926311
    235.825722   10.0.0.123 -> 10.0.0.126   TCP http > 34228 [FIN, ACK] Seq=1 Ack=2 Win=5792 Len=0 TSV=7061180 TSER=99926311
    235.825756   10.0.0.126 -> 10.0.0.123   TCP 34228 > http [ACK] Seq=2 Ack=2 Win=5856 Len=0 TSV=99926311 TSER=7061180
    
    $ uname -a
    Linux gaia.mn.ca 2.6.23.17-88.fc7 #1 SMP Thu May 15 00:35:10 EDT 2008 i686 i686 i386 GNU/Linux
    $ ip route get 10.0.0.123
    10.0.0.123 dev eth0  src 10.0.0.126
        cache  mtu 1500 advmss 1460 hoplimit 64
    
    绑定连接的代码:

    #include <arpa/inet.h>
    #include <errno.h>
    #include <netinet/in.h>
    #include <netinet/tcp.h>
    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    int main(int argc, char **argv)
    {
        struct sockaddr_in sn;
        socklen_t sn_len;
        struct sockaddr_in src;
        struct sockaddr_in dst;
        int sock;
        char b1[INET_ADDRSTRLEN];
        char b2[INET_ADDRSTRLEN];
        char b3[INET_ADDRSTRLEN];
    
        src.sin_family = dst.sin_family = AF_INET;
        src.sin_port = 0;
        dst.sin_port = htons(80);
    
        if (argc < 3) {
            printf("missing argument\n");
            return 1;
        }
    
        if (inet_pton(AF_INET, argv[1], &dst.sin_addr) != 1) {
            perror("pton");
            return -errno;
        }
    
        if (inet_pton(AF_INET, argv[2], &src.sin_addr) != 1) {
            perror("pton");
            return -errno;
        }
    
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            perror("socket");
            return -errno;
        }
    
        if (bind(sock, (struct sockaddr*)&src, sizeof src) != 0) {
            perror("bind");
            return -errno;
        }
    
        sn_len = sizeof sn;
        if (getsockname(sock, (struct sockaddr*)&sn, &sn_len) != 0) {
            perror("getsockname");
            return -errno;
        }
    
        printf("Bound socket: %s [%s->%s]\n",
               inet_ntop(AF_INET, &sn.sin_addr, b1, sizeof b1),
               inet_ntop(AF_INET, &src.sin_addr, b2, sizeof b2),
               inet_ntop(AF_INET, &dst.sin_addr, b3, sizeof b3));
    
        if (connect(sock, (struct sockaddr*)&dst, sizeof dst) != 0) {
            perror("connect");
            return -errno;
        }
    
        close(sock);
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    int main(int argc,字符**argv)
    {
    序列号中的结构sockaddr_;
    socklen_t snu len;
    src中的结构sockaddr_;
    dst中的结构sockaddr_;
    int袜子;
    字符b1[INET_ADDRSTRLEN];
    字符b2[INET_ADDRSTRLEN];
    字符b3[INET_ADDRSTRLEN];
    src.sin_family=dst.sin_family=AF_INET;
    src.sin_端口=0;
    dst.sin_端口=htons(80);
    如果(argc<3){
    printf(“缺少参数\n”);
    返回1;
    }
    if(inet\u pton(AF\u inet,argv[1],&dst.sin\u addr)!=1){
    佩罗尔(“普顿”);
    返回-错误号;
    }
    if(inet\u pton(AF\u inet,argv[2],&src.sin\u addr)!=1){
    佩罗尔(“普顿”);
    返回-错误号;
    }
    sock=socket(AF\u INET,sock\u STREAM,0);
    if(sock<0){
    佩罗(“插座”);
    返回-错误号;
    }
    if(绑定(sock,(struct sockaddr*)&src,sizeof src)!=0){
    佩罗(“绑定”);
    返回-错误号;
    }
    sn_len=sn的尺寸;
    if(getsockname(sock,(struct sockaddr*)和序号及序号)!=0){
    perror(“getsockname”);
    返回-错误号;
    }
    printf(“绑定套接字:%s[%s->%s]\n”,
    inet\u ntop(AF\u inet和sn.sin\u addr,b1,b1尺寸),
    inet_ntop(AF_inet和src.sin_addr、b2、b2尺寸),
    inet_ntop(AF_inet和dst.sin_addr,b3,sizeof b3));
    if(connect(sock,(struct sockaddr*)和dst,sizeof dst)!=0){
    perror(“连接”);
    返回-错误号;
    }
    关闭(袜子);
    返回0;
    }
    
    问题是我用iptables设置了一个nat后路由规则,即

    Chain POSTROUTING (policy ACCEPT 11 packets, 637 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 MASQUERADE  all  --  any    eth0.894  anywhere             anywhere            
    
    一旦我删除了这条规则:

    $ sudo iptables -t nat -F
    

    事情又开始起作用了。不久前,我在测试另一个问题时设置了nat规则,但后来忘了删除它。

    您能解释一下“不再工作”是什么意思吗?在上面代码的每个不同运行中,您的程序都不会打印任何错误,这意味着它实际上已连接并关闭。“绑定套接字”打印行似乎与相应的命令行匹配。数据包跟踪似乎是一个3路握手,然后是一个正常的闭合序列。换句话说,我看不出有什么不对。但我可能遗漏了一些微妙的东西。对不起,我应该使用比.120/.220更不同的源IP。“不工作”情况是从错误的源IP发送,例如绑定到.120,从.220发送流量。您是否从VM运行?如果是这样,您的数据包跟踪是在虚拟机内运行还是在主机上运行?@selbie-谢谢您的关注。原来我用iptables nat规则做了错事。
    $ sudo iptables -t nat -F