2012-07-04 39 views
6

Cách đây không lâu, tôi có thể kết nối với địa chỉ đích đã cho từ địa chỉ IP chính hoặc thứ cấp trên giao diện đã cho theo các bước sau.Kết nối ổ cắm bằng địa chỉ IP phụ

  1. thêm một địa chỉ IP thứ phát sau một giao diện được sử dụng ip addr add ...,
  2. gắn một ổ cắm đến địa chỉ chính hay phụ, như mong muốn,
  3. kết nối với địa chỉ đích IP sử dụng địa chỉ chính hay phụ, như ràng buộc trong 2.

Gần đây tôi đã nâng cấp một máy lên Linux 3.3.6 và điều này không còn hoạt động nữa, nhưng tôi không nhớ phiên bản cuối cùng tôi đã thử trên đó thực sự hoạt động. Có ai biết làm thế nào để làm cùng một loại điều trong hạt nhân mới hơn? Tôi vừa xác minh cùng mã trên 2.6.23 trên một máy khác.

CẬP NHẬT 2 Điều này dường như liên quan đến trình điều khiển NIC. Với 3.3.6 và 8139too, mọi thứ đều ổn. Cùng một máy, nhưng sử dụng một NIC khác và qua-rhine, khi đó sự cố sẽ hiển thị.

Đây là những gì xảy ra khi tôi chạy mã (nguồn ở cuối) trên 3.3.6 (đầu ra chụp gói từ tshark chạy ở chế độ nền):

$ ./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 from 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 get 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 

Và rồi giống nhau trên 2.6.23 trở lên :

$ ./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 

Mã cho 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; 
} 
+2

Bạn có thể giải thích ý nghĩa của từ "không còn hoạt động" không? Trong mỗi lần chạy mã khác nhau của bạn ở trên, chương trình của bạn không in bất kỳ lỗi nào - ngụ ý rằng nó thực sự được kết nối và đóng. Dòng in "bound socket" xuất hiện để khớp với dòng lệnh tương ứng. Các dấu vết gói xuất hiện là một bắt tay 3 chiều theo sau là một chuỗi đóng bình thường. Nói cách khác, tôi không thấy gì sai. Nhưng tôi có thể thiếu một cái gì đó tinh tế. – selbie

+0

Rất tiếc, tôi đã sử dụng IP nguồn khác nhiều hơn .120/.220. Trường hợp "không hoạt động" đang gửi từ IP nguồn sai, ví dụ: liên kết với .120, lưu lượng truy cập được gửi từ .220. – Wade

+0

Bạn có đang chạy từ máy ảo không? Nếu vậy, có phải dấu vết gói của bạn đang chạy trong máy ảo hoặc trên máy chủ không? – selbie

Trả lời

3

Vấn đề hóa ra là rằng tôi đã thiết lập một quy tắc POSTROUTING nat với iptables, ví dụ:

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    

Khi tôi loại bỏ quy tắc này:

$ sudo iptables -t nat -F 

Mọi thứ bắt đầu hoạt động trở lại. Tôi đã thiết lập quy tắc nat một thời gian trước trong khi thử nghiệm một vấn đề khác, và sau đó quên để loại bỏ nó sau đó.

Các vấn đề liên quan