Question

Je travaille sur un système serveur basé sur Linux dans lequel il existe deux interfaces réseau, toutes deux situées sur le même sous-réseau (pour l'instant, disons simplement qu'elles sont 172.17.32.10 & amp; 172.17.32.11 ). Lorsque j'envoie des données à un hôte du réseau, je souhaite spécifier l'interface sur laquelle les données sont transmises sur mon serveur. Je dois pouvoir passer d’une interface à l’autre (voire même transmettre sur les deux) dans le logiciel (les règles de routage statiques ne fonctionneront pas pour cette application).

J'ai trouvé une question connexe dans StackOverflow qui suggérait d'utiliser la bibliothèque netlink pour modifier les itinéraires à la volée. Cela semble intuitivement fonctionner, mais je me demandais s’il existait un autre moyen d’atteindre le même résultat.

Était-ce utile?

La solution

Aucune infraction prévue, mais la réponse concernant l'utilisation de bind () est tout à fait fausse. bind () contrôlera l'adresse IP source placée dans l'en-tête IP du paquet. Il ne contrôle pas quelle interface sera utilisée pour envoyer le paquet: la table de routage du noyau sera consultée pour déterminer quelle interface a le coût le plus bas pour atteindre une destination particulière. (* voir note)

Au lieu de cela, vous devez utiliser un sockopt SO_BINDTODEVICE . Cela fait deux choses:

  • Les paquets sortiront toujours de l'interface que vous avez spécifiée, peu importe ce que disent les tables de routage du noyau.
  • Seuls les paquets arrivant sur l'interface spécifiée seront remis au socket. Les paquets arrivant sur d'autres interfaces ne le seront pas.

Si vous souhaitez basculer entre plusieurs interfaces, nous vous suggérons de créer un socket par interface. De plus, comme vous ne recevrez que des paquets sur l'interface à laquelle vous êtes lié, vous devrez ajouter tous ces sockets à votre select () / poll () . / tout ce que vous utilisez.

#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");
}

(* note) Bind () à une adresse IP d'interface peut entraîner un comportement déroutant mais néanmoins correct. Par exemple, si vous bind () à l'adresse IP de eth1, mais que la table de routage envoie le paquet eth0, un paquet apparaîtra sur le fil eth0 mais transportera l'adresse IP source de l'interface eth1. . C'est bizarre mais autorisé, bien que les paquets renvoyés à l'adresse IP de eth1 soient renvoyés vers eth1. Vous pouvez tester cela en utilisant un système Linux avec deux interfaces iP. J'en ai un et je l'ai testé, et bind () ne permet pas de sortir le paquet d'une interface physique.

Bien que techniquement autorisé, cela peut ne pas fonctionner, selon la topologie. Pour atténuer les attaques par déni de service distribué lorsque les attaquants utilisent des adresses source IP falsifiées, de nombreux routeurs effectuent désormais des vérifications de renversement de chemin (Reverse Path Forwarding, RPF). Paquets avec une adresse IP source sur le "mauvais" le chemin peut être supprimé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top