Pregunta

Estoy trabajando en un sistema de servidor basado en Linux en el que hay dos interfaces de red, ambas en la misma subred (por ahora, digamos que son 172.17.32.10 & amp; 172.17.32.11 ). Cuando envío datos a un host en la red, me gustaría especificar en qué interfaz de mi servidor se transmiten los datos. Necesito poder cambiar de una interfaz a otra (o tal vez incluso transmitir en ambos) en el software (las reglas de enrutamiento estático no funcionarán para esta aplicación).

Encontré una pregunta relacionada en StackOverflow que sugería usar la biblioteca netlink para modificar rutas sobre la marcha. Esto intuitivamente parece que debería funcionar, pero me preguntaba si había otras opciones para lograr este mismo resultado.

¿Fue útil?

Solución

No se pretende ofender, pero la respuesta sobre el uso de bind () es bastante incorrecta. bind () controlará la dirección IP de origen colocada dentro del encabezado IP del paquete. No controla qué interfaz se utilizará para enviar el paquete: se consultará la tabla de enrutamiento del kernel para determinar qué interfaz tiene el costo más bajo para llegar a un destino en particular. (* ver nota)

En su lugar, debe utilizar un sockopt SO_BINDTODEVICE . Esto hace dos cosas:

  • Los paquetes siempre saldrán de la interfaz que usted especificó, independientemente de lo que digan las tablas de enrutamiento del kernel.
  • Solo los paquetes que lleguen a la interfaz especificada se entregarán al socket. Los paquetes que llegan a otras interfaces no lo harán.

Si tiene varias interfaces entre las que desea cambiar, sugeriría crear un socket por interfaz. Debido a que también solo recibirá paquetes a la interfaz a la que está vinculado, deberá agregar todos estos sockets a su select () / poll () / Lo que sea que uses.

#include <net/if.h>

struct ifreq ifr;

memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name));
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
            (void *)&ifr, sizeof(ifr)) < 0) {
    perror("SO_BINDTODEVICE failed");
}

(* nota) Bind () a una dirección IP de interfaz puede llevar a un comportamiento confuso pero, sin embargo, correcto. Por ejemplo, si bind () a la dirección IP para eth1, pero la tabla de enrutamiento envía el paquete eth0, entonces aparecerá un paquete en el cable eth0 pero con la dirección IP de origen de la interfaz eth1 . Esto es raro pero permitido, aunque los paquetes enviados de nuevo a la dirección IP de eth1 se enrutarán de nuevo a eth1. Puede probar esto utilizando un sistema Linux con dos interfaces iP. Tengo uno, y lo probé, y bind () no es eficaz para dirigir el paquete fuera de una interfaz física.

Aunque técnicamente se permite, dependiendo de la topología esto puede no funcionar. Para frenar los ataques de denegación de servicio distribuidos en los que los atacantes utilizan direcciones de origen IP falsificadas, muchos enrutadores ahora realizan comprobaciones de Reenvío de ruta inversa (RPF). Los paquetes con una dirección IP de origen en el " incorrecto " la ruta puede ser eliminada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top