web-dev-qa-db-fra.com

iptables - Cible pour acheminer le paquet vers une interface spécifique?

Mon serveur domestique possède deux interfaces principales, eth1 (une connexion Internet standard) et tun0 (un tunnel OpenVPN). Je voudrais utiliser iptables pour forcer tous les paquets générés par un processus local appartenant à l'UID 1002 à quitter via tun0, et tous les autres paquets à quitter via eth1.

Je peux facilement marquer les paquets correspondants:

iptables -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11

Maintenant, je voudrais mettre une règle dans la chaîne POSTROUTING (probablement de la table mangle) pour faire correspondre les paquets marqués de 11 et les envoyer à tun0, suivi d'une règle qui correspond à tous les paquets et les envoie à eth1.

J'ai trouvé la cible ROUTE, mais cela ne semble que réécrire l'interface source (sauf si je ne la lis pas correctement).

Iptables en est-il capable? Dois-je jouer avec la table de routage (via ip route ou simplement les anciennes commandes route) à la place?

Edit: je pensais que je devrais peut-être fournir plus d'informations. Je n'ai pas d'autres règles iptables à l'heure actuelle (bien que je puisse créer des règles pour effectuer des tâches non liées à l'avenir). De plus, la sortie de ip route est:

default via 192.168.1.254 dev eth1  metric 203
10.32.0.49 dev tun0  proto kernel  scope link  src 10.32.0.50
85.17.27.71 via 192.168.1.254 dev eth1
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.73  metric 203

Je n'ai pas touché à la table de routage - c'est comme ça à l'heure actuelle (même si elle semble assez sale). Je suis désolé, mais je n'ai pas la commande legacy route installée sur cette machine.

Et la sortie de ip addr (bien sûr, eth0 et eth2 peuvent être ignorés - ce sont des cartes réseau qui ne sont pas utilisées actuellement):

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope Host lo
    inet6 ::1/128 scope Host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 1c:6f:65:2a:73:3f brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast     state UP qlen 1000
    link/ether 00:1b:21:9d:4e:bb brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.73/24 brd 192.168.1.255 scope global eth1
    inet6 fe80::21b:21ff:fe9d:4ebb/64 scope link
       valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:1b:21:6a:c0:4b brd ff:ff:ff:ff:ff:ff
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc     pfifo_fast state UNKNOWN qlen 100
    link/none
    inet 10.32.0.50 peer 10.32.0.49/32 scope global tun0

Edit: J'ai obtenu quelque chose qui fonctionne, mais il ne transfère pas les paquets marqués vers tun0. Fondamentalement, j'ai ajouté un tableau (11) et utilisé:

ip route add table 11 via 10.32.0.49 dev tun0
ip rule add priority 10000 fwmark 11 table 11

Quand je viens de Sudo -u user1000 wget -qO- whatismyip.org, J'obtiens l'adresse IP externe de mon domicile, mais si je le fais Sudo -u user1002 wget -qO- whatismyip.org, J'obtiens également l'adresse IP de mon domicile (mais je devrais obtenir l'adresse IP à l'autre bout du tunnel OpenVPN).

Fonctionnement iptables -vL confirme que les paquets sont mis en correspondance par la règle de marquage, mais ils ne semblent pas suivre la règle de routage.

EDIT: J'ai passé beaucoup de temps là-dessus, et bien que cela ne fonctionne toujours pas, je pense que je suis un peu plus proche.

La règle iptables doit être dans la chaîne OUTPUT de la table mangle. Je pense que j'ai également besoin d'une règle MASQUERADE dans la chaîne POSTROUTING de la table nat, pour définir l'adresse source. Cependant, le réacheminement qui se produit après le mangle de OUTPUT ne fonctionne pas correctement.

J'ai passé 5 heures là-dessus maintenant, donc je fais une pause et j'y reviendrai probablement plus tard ce soir ou demain.

26
Ethan

J'ai résolu ça. Le problème venait des règles de routage du tableau 11. Le tableau 11 était touché, mais les règles de routage le rendent inutilisable. Ce script est ce que j'utilise maintenant, et il semble bien fonctionner (bien qu'il soit évidemment spécifique à ma configuration). J'ai également créé un nouveau tableau 21 consacré à la liaison montante principale (eth1).

# Add relevant iptables entries.
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

# Flush ALL THE THINGS.
ip route flush table main
ip route flush table 11
ip route flush table 21
ip rule flush

# Restore the basic rules and add our own.
ip rule add lookup default priority 32767
ip rule add lookup main priority 32766
ip rule add fwmark 11 priority 1000 table 11
# This next rule basically sends all other traffic down eth1.
ip rule add priority 2000 table 21

# Restore the main table.  I flushed it because OpenVPN does weird things to it.
ip route add 127.0.0.0/8 via 127.0.0.1 dev lo
ip route add 192.168.1.0/24 dev eth1 src 192.168.1.73
ip route add default via 192.168.1.254

# Set up table 21.  This sends all traffic to eth1.
ip route add 192.168.1.0/24 dev eth1 table 21
ip route add default via 192.168.1.254 dev eth1 table 21

# Set up table 11.  I honestly don't know why 'default' won't work, or
# why the second line here is needed.  But it works this way.
ip route add 10.32.0.49/32 dev tun0 table 11
ip route add 10.32.0.1 via 10.32.0.50 dev tun0 table 11
ip route add 0.0.0.0/1 via 10.32.0.50 dev tun0 table 11

ip route flush cache

## MeanderingCode edit (parce que je ne peux pas encore commenter)

Merci pour cette réponse! Il semble que cela puisse devenir compliqué, car vous devrez conserver les informations sur l'itinéraire ici (peut-être en double ou en cassant d'autres choses qui pourraient vouloir définir des itinéraires).

Vous rencontrez peut-être des "choses étranges" dans votre table de routage depuis OpenVPN car le serveur est configuré pour des itinéraires "Push", permettant à tout le trafic de passer via l'interface réseau VPN, plutôt que sur Internet "nu". Ou votre configuration OpenVPN ou tout script/application qui la configure définit des itinéraires.

Dans le premier cas, vous pouvez éditer votre configuration OpenVPN et mettre une ligne contenant "route-nopull"
Dans ce dernier, vérifiez la configuration d'OpenVPN ou de tout wrapper (network-manager-openvpn, par exemple sur de nombreuses distributions de bureau Linux actuelles)
.

À votre santé!

7
Ethan

J'ai récemment rencontré un problème similaire, quoique légèrement différent. Je voulais router uniquement TCP port 25 (SMTP) sur une interface OpenVPN tap0, tout en acheminant tout le reste du trafic ( même pour le même hôte) sur l'interface par défaut.

Pour ce faire, j'ai dû marquer des paquets et mettre en place des règles de traitement. Tout d'abord, ajoutez une règle qui rend les paquets de route du noyau marqués avec 2 à travers la table 3 (expliqué plus loin):

ip rule add fwmark 2 table 3

Vous auriez pu ajouter un nom symbolique à /etc/iproute2/rt_tables, mais je n'ai pas pris la peine de le faire. Le nombre 2 et 3 sont choisis au hasard. En fait, ceux-ci peuvent être les mêmes, mais pour plus de clarté, je ne l'ai pas fait dans cet exemple (bien que je le fasse dans ma propre configuration).

Ajoutez un itinéraire pour rediriger le trafic sur une autre interface, en supposant que la passerelle est 10.0.0.1:

ip route add default via 10.0.0.1 table 3

Très important! Videz votre cache de routage, sinon vous n'obtiendrez pas de réponse et restez assis les mains dans les cheveux pendant quelques heures:

ip route flush cache

Maintenant, définissez une règle de pare-feu pour marquer les paquets désignés:

iptables -t mangle -A OUTPUT -p tcp --dport 465 -j MARK --set-mark 2

La règle ci-dessus s'applique uniquement si les paquets proviennent de la machine locale. Voir http://inai.de/images/nf-packet-flow.png . Adaptez-le à vos besoins. Par exemple, si vous souhaitez uniquement acheminer le trafic HTTP sortant sur le tap0 interface, remplacez 465 par 80.

Pour empêcher les paquets envoyés sur tap0 obtenir votre adresse LAN comme IP source, utilisez la règle suivante pour la changer en votre adresse d'interface (en supposant que 10.0.0.2 comme adresse IP pour l'interface tap0):

iptables -t nat -A POSTROUTING -o tap0 -j SNAT --to-source 10.0.0.2

Enfin, relâchez la validation de la source du chemin inverse. Certains vous suggèrent de le régler sur 0, mais 2 semble un meilleur choix selon https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt . Si vous sautez ceci, vous recevrez des paquets (cela peut être confirmé en utilisant tcpdump -i tap0 -n), mais les paquets ne sont pas acceptés. La commande pour modifier le paramètre afin que les paquets soient acceptés:

sysctl -w net.ipv4.conf.tap0.rp_filter=2
28
Lekensteyn

Je pense que tu veux:

/sbin/ip route add default via 10.32.0.49 dev tun0 table 11
/sbin/ip rule add priority 10000 fwmark 11 table 11

http://lartc.org/howto/lartc.netfilter.html

Mais je n'ai pas testé ce qui précède.

2
mfarver

Cela peut être fait sans la commande iptables Exécuter une simple commande ip

Pour uid 1002:

ip rule add uidrange 1002-1002 table 502

Ajoutez la route par défaut pour la table 502 sur l'interface que vous voulez dire

eth0 ip rule add default via a.b.c.d dev eth0
0
jainendra