Linux: Comment forcer l'utilisation d'une interface réseau spécifique?
Cela pourrait être considéré comme une continuation de cette plus tôt DONC, la question.
Idéalement, j'aimerais prison d'un processus en utilisant uniquement une certaine interface, n'importe quoi. Il fera des connexions TCP, l'envoi de datagrammes UDP, et à l'écoute pour les diffusions UDP. Actuellement, ce que je fais:
- Déterminer l'adresse IP de l'interface à utiliser.
- Créer une politique de propriété intellectuelle de la règle de la route tous les paquets provenant de l'interface pour que la propriété intellectuelle
- Créer une autre politique de propriété intellectuelle de la règle de la route tous les paquets en provenance de l'IP de cette interface
- Configurer une valeur par défaut de la table de routage pour chaque règle
Maintenant, cela fonctionne, pour la plupart, mais le processus client doit également être prêts à jouer le jeu. C'est, il doit se lier à une adresse IP spécifique de l'interface qu'il veut utiliser, et je pense que j'ai besoin de SO_BINDTODEVICE
. (Cependant, je continue la lecture des informations contradictoires quant à savoir si SO_BINDTODEVICE
fonctionne réellement lors de l'utilisation de TCP ou UDP.) Heureusement, l'application cliente est Python, et je peux prolonger la classe socket pour faire tout cela de manière transparente. Mais je ne suis pas sûr que c'est une solution complète, surtout à l'égard de la réception d'émissions.
Mes questions sont:
- Ne
SO_BINDTODEVICE
faire ce que je veux ici? Ou est-ce seulement efficace pour les sockets raw? Quelqu'un fait remarquer que, "SO_BINDTODEVICE
sur un socket ne garantit pas la prise ne recevoir des paquets qui sont arrivés sur cette interface physique du fil d'antenne." Si cela est vrai en effet, alors que tSO_BINDTODEVICE
faire? - Est-il un moyen de le faire, tels que l'adresse IP locale n'a pas à être unique? Ce ne serait pas un problème autre que le fait que le serveur DHCP sur une interface attribuer une IP qui est utilisé par une autre interface, confondant ainsi la table de routage.
- Comment puis-je recevoir les émissions uniquement à partir d'une interface spécifique? La liaison à une IP spécifique semble faire ignorer les émissions, ce qui est logique, mais ce n'est pas tout à fait ce que je cherche.
Je suis en cours d'exécution sur Ubuntu 8.04 w/noyau Linux 2.6.26. Être en mesure d'accéder à la même sous-réseau sur deux réseaux différents à travers deux interfaces différentes simultanément est une exigence non négociable, rendant ainsi (pour la plupart) immunitaire à "ne pas le faire." 🙂
source d'informationauteur |
Vous devez vous connecter pour publier un commentaire.
Comme pour ma question d'ordre général, il semble y avoir quelques façons de le faire:
La manière compliquée qui implique la table de routage des changements et de la coopération de chaque processus. C'est la façon dont je l'ai décrit ci-dessus. Un avantage qu'il a c'qu'il fonctionne à partir de l'espace utilisateur. J'ai mis quelques notes supplémentaires sur et a répondu à mes questions spécifiques ci-dessous.
Écrire un noyau personnalisé modèle qui ignore la table de routage complètement, si
SO_BINDTODEVICE
est réglé. Le processus client est toujours nécessaire d'appelersetsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev)
cependant. Cette option n'est certainement pas pour les faibles de cœur.Virtualiser le processus. Ce n'est probablement pas approprié pour beaucoup de gens, et il apporte propre ensemble de maux de tête, surtout avec la configuration. Mais il vaut la peine d'être mentionné.
Les Options 1 et 2 nécessitent des processus d'opt-in pour le travail que nous l'aurions souhaité. Cela peut être partiellement atténué par la création d'une bibliothèque dynamique qui détourne le socket() pour créer le socket, puis lie immédiatement à l'appareil avant de retourner le descripteur. Ceci est décrit plus en détail ici.
Après avoir fait quelques recherches et beaucoup de Googler, je peux en tirer quelques conclusions sur la façon dont le noyau Linux 2.6.26 se comporte. Notez que ce sont probablement tous de la mise en œuvre des comportements spécifiques, et peut-être même noyau spécifique. Test de votre propre plate-forme avant de décider de mettre en œuvre les fonctionnalités de base de mon point de données unique.
SO_BINDTODEVICE
en effet de faire ce qu'il dit, au moins pour UDP.Unique IPs pour chaque interface semble être nécessaire, puisque nous utilisons les tables de routage. Un noyau personnalisé module pourrait contourner cette restriction.
Pour recevoir les émissions sur une interface spécifique, se lient à l'appareil en utilisant d'abord des
SO_BINDTODEVICE
et alors se lier à l'adresse de diffusion avec l'habituel appel de bind (). Le dispositif de liaison doit être fait avant toute autre chose. Ensuite, la prise recevra uniquement les émissions qui arrivent sur cette interface.Je l'ai testé en créant d'abord une prise de courant. Ensuite, j'ai lié à une interface spécifique à l'aide de
setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev)
. Enfin, j'ai lié à l'adresse de diffusion. À partir d'un autre ordinateur, j'ai envoyé une émission qui serait reçu par l'intermédiaire d'un nonbound interface. Le dispositif lié socket n'a pas reçu cette émission, qui a du sens. Supprimer lasetsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev)
appel et la diffusion sera reçu.Il convient également de mentionner que vous pouvez utiliser
setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
ici. Notez que la sémantique deSO_REUSEADDR
changement avec des adresses de diffusion. Plus précisément, il est légal d'avoir deux sockets lié à l'adresse de diffusion et le même port sur la même machine si elles ont toutes les deuxSO_REUSEADDR
ensemble.Mise à JOUR:
SO_BINDTODEVICE
avec une diffusion semble être périlleuse, plus précisément, de la réception de trames de diffusion. J'ai été l'observation des trames de diffusion reçu sur une interface, mais la disparition de l'autre en même temps. Il semble que ceux-ci sont effectués par la table de routage locale, mais sont insensibles à la propriété intellectuelle, les règles de politique. Cependant, je ne suis pas certain à 100% sur ce et je suis le seul fait de mentionner à titre d'enquête si vous souhaitez continuer. Tout ça pour dire: utilisez à vos propres risques. Dans l'intérêt de temps, j'ai ouvert une socket raw sur l'interface et analysé les IP et Ethernet, des en-têtes de moi-même.Après une bataille acharnée week-end, je suis heureux de vous présenter une solution qui résout la plupart de ce que j'ai déjà discuté avec presque zéro tracas.
Il y a un sysctl appelé net.ipv4.conf.tous les.rp_filter qui peut être mis à 0 pour désactiver la validation de la source:
Cela peut également être défini par l'interface de base à l'aide de /proc/sys/net/ipv4/conf/
<interface>
/rp_filter.Comme une affiche a expliqué, il fait le routage IP "moins déterministe", dans le sens que les paquets provenant d'un sous-réseau ne sont pas garantis pour aller toujours de la même interface. Dans ce cas, c'est exactement ce qu'il est nécessaire. Merci de faire des recherches supplémentaires pour déterminer si c'est vraiment ce que vous voulez.
Les émissions sont toujours problématique pour des raisons que je ne comprends pas, mais je suis enfin satisfait de ce problème, et j'espère que cela aide les autres.
Pas une réponse directe à votre question, mais juste un avis. Comme vous l'avez mentionné ci-dessus, cette solution peut être trop de travail pour ce que vous avez besoin/envie de le faire.
Personnellement, j'aime bien l'idée de la création d'un réseau de pile crochet module du noyau qui va me permettre de faire cela. De cette façon, j'ai le plein contrôle de la multidiffusion et unitcast images allant et venant de l'espace utilisateur. Vous devez utiliser quelque chose comme sockets netlink pour envoyer/recevoir des données vers et à partir du pilote de l'espace utilisateur et l'application, mais il fonctionne très bien et est très rapide.
Vous bénéficiez également de se raccorder à n'importe quel niveau de la pile de cette façon... Ethernet ou IP. Donc avoir le plein contrôle sur ce que vous envoyez/recevez.
Voici un exemple article qui parle d'accrochage dans le netfilter pile.
Remarque: cet article crochets dans la pile IP, et c'est aussi vieille. Je sais que les Api ont changé, mais beaucoup de cet article s'applique toujours pratiquement et théoriquement.
Si vous voulais crochet dans la transition de la couche, vous pouvez utiliser l'un mécanisme similaire, mais de spécifier
Note: Ceci est très similaire à l'ouverture d'une socket raw sur l'interface. Vous devrez construire vos images vous-même.
vous pourriez essayer de limiter le processus' espace de noms réseau à une seule interface. Vous avez besoin d'un noyau compilé avec CONFIG_NETNS (la plupart des noyaux des distributions modernes) et un script pour faire les devoirs pour vous. Exemple de configuration