2012-07-04 17 views
6

No hace mucho tiempo, pude conectarme a una dirección de destino determinada desde una dirección IP primaria o secundaria en una interfaz determinada, siguiendo los siguientes pasos.Conecta el socket utilizando la dirección IP secundaria

  1. agregar una dirección IP secundaria a una interfaz dada usando ip addr add ...,
  2. enlazar un socket a la dirección primaria o secundaria, según se desee,
  3. conectar a la dirección IP de destino usando la dirección primaria o secundaria, como límite en 2.

Recientemente actualicé una máquina a Linux 3.3.6 y esto ya no funciona, pero no recuerdo la última versión que probé que realmente funcionaba. ¿Alguien sabe cómo hacer el mismo tipo de cosas en kernels más nuevos? Acabo de verificar el mismo código en 2.6.23 en una máquina diferente.

ACTUALIZACIÓN 2 Esto parece estar relacionado con el controlador de la NIC. Con 3.3.6 y 8139too, todo está bien. Misma máquina, pero con una NIC diferente y via-rhine, aparece el problema.

Esto es lo que sucede cuando corro el código (fuente al final) en 3.3.6 (salida de captura de paquetes de tshark ejecuta en segundo plano):

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

y luego el mismo en 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 

Código de 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

¿Puedes explicar a qué te refieres con "ya no funciona"? En cada una de las diferentes ejecuciones de su código anterior, su programa no imprime ningún error, lo que implica que realmente se conectó y cerró. La línea impresa de "socket enlazado" parece coincidir con la línea de comando correspondiente. La traza del paquete parece ser un enlace de 3 vías seguido de una secuencia de cierre normal. En otras palabras, no veo nada mal. Pero podría estar perdiendo algo sutil. – selbie

+0

Lo siento, debería haber usado una fuente IP más diferente que .120/.220. El caso "no funciona" es enviar desde una dirección IP incorrecta, p. obligado a .120, tráfico enviado desde .220. – Wade

+0

¿Está ejecutando desde una máquina virtual? Si es así, ¿se está ejecutando su rastreo de paquete dentro de la VM o en la máquina host? – selbie

Respuesta

3

El problema resulta ser que había establecido una regla POSTROUTING NAT con iptables, es decir

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    

Una vez me quita esta regla:

$ sudo iptables -t nat -F 

cosas empezaron a funcionar de nuevo. Había establecido la regla nat hace un tiempo mientras probaba otro problema, y ​​luego olvidé eliminarlo después.

Cuestiones relacionadas