tcp - Connect socket using secondary IP address -
not long ago, able connect given destination address either primary or secondary ip address on given interface following steps.
- add secondary ip address given interface using
ip addr add ..., - bind socket primary or secondary address, desired,
- connect destination ip address using primary or secondary address, bound in #2.
i upgraded machine linux 3.3.6 , no longer works, don't remember last version tried on working. know how same kind of thing in newer kernels? verified same code on 2.6.23 on different machine.
update 2 seems related nic driver. 3.3.6 , 8139too, fine. same machine, using different nic , via-rhine, problem shows up.
here's happens when run code (source @ end) on 3.3.6 (packet capture output tshark running in background):
$ ./bind_connect 10.0.1.124 10.0.1.120 bound socket: 10.0.1.120 [10.0.1.120->10.0.1.124] # wrong source ip (should use 10.0.1.120 bind) # | # v $ 121.051052 10.0.1.220 -> 10.0.1.124 50418 80 tcp 74 50418 > 80 [syn] seq=3358582895 win=14600 len=0 mss=1460 sack_perm=1 tsval=30589624 tsecr=0 ws=128 121.051428 10.0.1.124 -> 10.0.1.220 80 50418 tcp 74 80 > 50418 [syn, ack] seq=1815118993 ack=3358582896 win=5792 len=0 mss=1460 sack_perm=1 tsval=8157158 tsecr=30589624 ws=2 121.051475 10.0.1.220 -> 10.0.1.124 50418 80 tcp 66 50418 > 80 [ack] seq=3358582896 ack=1815118994 win=14720 len=0 tsval=30589624 tsecr=8157158 121.051504 10.0.1.220 -> 10.0.1.124 50418 80 tcp 66 50418 > 80 [fin, ack] seq=3358582896 ack=1815118994 win=14720 len=0 tsval=30589624 tsecr=8157158 121.051768 10.0.1.124 -> 10.0.1.220 80 50418 tcp 66 80 > 50418 [ack] seq=1815118994 ack=3358582897 win=5792 len=0 tsval=8157158 tsecr=30589624 121.051913 10.0.1.124 -> 10.0.1.220 80 50418 tcp 66 80 > 50418 [fin, ack] seq=1815118994 ack=3358582897 win=5792 len=0 tsval=8157158 tsecr=30589624 121.051941 10.0.1.220 -> 10.0.1.124 50418 80 tcp 66 50418 > 80 [ack] seq=3358582897 ack=1815118995 win=14720 len=0 tsval=30589625 tsecr=8157158 $ ./bind_connect 10.0.1.124 10.0.1.220 bound socket: 10.0.1.220 [10.0.1.220->10.0.1.124] $ 124.139966 10.0.1.220 -> 10.0.1.124 41470 80 tcp 74 41470 > 80 [syn] seq=1404133303 win=14600 len=0 mss=1460 sack_perm=1 tsval=30590551 tsecr=0 ws=128 124.140421 10.0.1.124 -> 10.0.1.220 80 41470 tcp 74 80 > 41470 [syn, ack] seq=1918490481 ack=1404133304 win=5792 len=0 mss=1460 sack_perm=1 tsval=8157467 tsecr=30590551 ws=2 124.140478 10.0.1.220 -> 10.0.1.124 41470 80 tcp 66 41470 > 80 [ack] seq=1404133304 ack=1918490482 win=14720 len=0 tsval=30590551 tsecr=8157467 124.140553 10.0.1.220 -> 10.0.1.124 41470 80 tcp 66 41470 > 80 [fin, ack] seq=1404133304 ack=1918490482 win=14720 len=0 tsval=30590551 tsecr=8157467 124.140934 10.0.1.124 -> 10.0.1.220 80 41470 tcp 66 80 > 41470 [ack] seq=1918490482 ack=1404133305 win=5792 len=0 tsval=8157467 tsecr=30590551 124.140976 10.0.1.124 -> 10.0.1.220 80 41470 tcp 66 80 > 41470 [fin, ack] seq=1918490482 ack=1404133305 win=5792 len=0 tsval=8157467 tsecr=30590551 124.140995 10.0.1.220 -> 10.0.1.124 41470 80 tcp 66 41470 > 80 [ack] seq=1404133305 ack=1918490483 win=14720 len=0 tsval=30590551 tsecr=8157467 $ uname -a linux erebus.mn.ca 3.3.6-1-arch #1 smp preempt sun may 13 09:59:18 utc 2012 i686 gnu/linux $ ip route 10.0.1.124 10.0.1.124 dev eth0.894 src 10.0.1.220 cache ipid 0x61ca rtt 3ms rttvar 3ms cwnd 10 and same on 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 10.0.0.123 10.0.0.123 dev eth0 src 10.0.0.126 cache mtu 1500 advmss 1460 hoplimit 64 code bind_connect:
#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; }
the problem turns out had set nat postrouting rule iptables, i.e.
chain postrouting (policy accept 11 packets, 637 bytes) pkts bytes target prot opt in out source destination 0 0 masquerade -- eth0.894 anywhere anywhere once removed rule:
$ sudo iptables -t nat -f things started work again. had set nat rule while ago while testing problem, , forgotten remove afterward.
Comments
Post a Comment