4 votes

Comment puis-je faire un IP Passthrough sur une boîte Linux ?

J'ai un Raspberry Pi, fonctionnant sous Raspbian (basé sur Debian), avec 2 interfaces réseau.

L'une des interfaces est le WAN, provenant d'un modem satellite. L'autre est le routeur du client, pour lequel le Pi fournit l'Internet.

Le problème est que je n'ai affaire qu'à un /30, et que le modem satellite possède déjà l'une des deux IP sur ce /30, il ne me reste donc qu'une IP (1.1.1.2/30), et deux appareils qui la veulent (mon Raspberry Pi, et le routeur du client).

Je sais que je peux facilement faire du NAT, et donner au client une IP de réseau local. Ce n'est pas ce que je veux. J'ai besoin que le client ait une IP publique. Je sais également que je peux configurer le Pi pour qu'il ne soit qu'un commutateur, sans IP propre, mais le Pi n'aura alors pas d'accès à Internet. Ce n'est pas ce que je veux non plus. J'ai besoin que le Pi et le routeur du client aient tous deux accès à Internet.

Diagram

Je sais que c'est possible, car j'ai utilisé des modems cellulaires MicroHard dans le passé qui font exactement la même chose. Le modem cellulaire obtient une IP publique lorsqu'il se connecte à la tour cellulaire, et lorsque vous activez le mode IP passthrough, un routeur branché sur ce modem cellulaire obtiendra également la même IP publique.

Si vous accédez à cette IP publique depuis Internet sur le port 80, 443 ou 22, vous parlerez au modem cellulaire, mais si vous accédez à un autre port, vous parlerez au routeur derrière le modem cellulaire. C'est exactement ce que je veux faire. Je ne suis juste pas sûr de savoir exactement comment ils font, et comment je le reproduis sous Linux. Les modems cellulaires MicroHard sont basés sur Linux, donc c'est possible sous Linux.

Pour l'instant, c'est mon plan :

  • IP statique de 1.1.1.2/30 sur eth0 du Raspberry Pi (Interface Sat Modem)
  • IP statique de 1.1.1.254/24 sur eth1 du Raspberry Pi (Interface du routeur client)
  • Serveur DHCP sur eth1 donnant le routeur du client :
    • 1.1.1.2/24
    • DG : 1.1.1.254
  • Activé net.ipv4.ip_forward
  • Puisque les 2 sous-réseaux sur les 2 interfaces se chevauchent évidemment, utilisez des règles de routage basées sur des politiques pour indiquer au Pi quand et où il doit envoyer le trafic.

Cela ressemble maintenant à ceci :

enter image description here

J'ai essayé de le faire fonctionner, mais le dernier point est évidemment la partie la plus difficile. Tout le reste (routeur DHCP, IP statiques, transfert d'IP) est terminé et fonctionne.

Je l'ai fait :

# Rules to prevent ARP from going out the wrong interface
$ sudo arptables -A INPUT -i eth0 --destination-ip ! 1.1.1.2 -j DROP
$ sudo arptables -A INPUT -i eth1 --destination-ip ! 1.1.1.254 -j DROP

# Create custom routing tables
$ sudo vim /etc/iproute2/rt_tables
    190 to_sat_modem
    200 to_customer_router

# Add rules to tables
$ sudo ip route add default dev eth0 table to_sat_modem
$ sudo ip route add default dev eth1 table to_customer_router

# Add policy based routing rules
$ sudo ip rule add fwmark 0x1 lookup to_sat_modem
$ sudo ip rule add fwmark 0x2 lookup to_customer_router

# Add masq rule
$ sudo iptables -t nat -A POSTROUTING -o eth0 ! -s 1.1.1.2 -j SNAT --to 1.1.1.2

# Add rules for when to use these routing tables

$ sudo iptables -t mangle -N TO_CUSTOMER_ROUTER
$ sudo iptables -t mangle -N TO_SAT_MODEM

$ sudo iptables -t mangle -A OUTPUT -d 1.1.1.2 -j TO_CUSTOMER_ROUTER        # From localhost
$ sudo iptables -t mangle -A PREROUTING -i eth0 -d 1.1.1.2 -p udp -j TO_CUSTOMER_ROUTER                                         # All UDP ports
$ sudo iptables -t mangle -A PREROUTING -i eth0 -d 1.1.1.2 -p tcp --match multiport ! --dports 22,80 -j TO_CUSTOMER_ROUTER  # Most TCP ports
$ sudo iptables -t mangle -A TO_CUSTOMER_ROUTER -j MARK --set-xmark 0x2
$ sudo iptables -t mangle -A TO_CUSTOMER_ROUTER -j ACCEPT

$ sudo iptables -t mangle -A OUTPUT -d 1.1.1.1 -j TO_SAT_MODEM      # From localhost
$ sudo iptables -t mangle -A PREROUTING -i eth1 -d 1.1.1.1 -j TO_SAT_MODEM
$ sudo iptables -t mangle -A TO_SAT_MODEM -j MARK --set-xmark 0x1
$ sudo iptables -t mangle -A TO_SAT_MODEM -j ACCEPT

J'ai l'impression d'être sur la bonne voie, mais je ne parviens pas à le faire fonctionner. Avez-vous des idées ?

PS. Oui, je sais que la plupart de mes règles ne survivront pas à un redémarrage. Je corrigerai cela une fois que j'aurai une solution qui fonctionne.

PPS. Cela revient à essayer d'obtenir une transparence à sens unique. Le modem satellite ne verra qu'un seul appareil derrière lui (1.1.1.2), tandis que le routeur client pourra parler au Pi (1.1.1.254) et au modem satellite (1.1.1.1). Cela devrait fonctionner, mais pose le problème du masquage d'un /24 entier d'adresses IP publiques réelles. Je peux remplacer le /24 par un /29 pour réduire l'effet, mais cela se produira quand même. À terme, je voudrais une transparence bidirectionnelle pour pouvoir réutiliser les IP /30 aux deux extrémités du Pi, mais je me suis dit que ce serait plus simple pour commencer

PPPS. Je suis conscient que la réponse évidente à cette question est la suivante

Ne faites pas ça. Faites autre chose. Donnez au client une IP de réseau local, ou mettez votre Pi derrière le routeur du client et donnez-lui une IP de réseau local, ou mettez le pi en mode pont, ou ...

Je ne veux pas écrire une explication de 10 pages sur les raisons pour lesquelles cela doit être fait de cette façon, mais croyez-moi, cela doit être fait de cette façon, si c'est possible, ce qui, comme je l'ai dit, est possible parce que je l'ai vu faire

1voto

John Points 151

Sur la base de ma solution 2 Pi, j'ai pu utiliser les espaces de noms du réseau Linux pour configurer la même chose sur un seul Pi :

Single Pi Solution

Étapes initiales :

  • Activer le transfert d'IP
  • Configurez votre eth0 à 1.1.1.2/30 IP statique comme vous le feriez normalement.
    • Vous pourriez utiliser un client DHCP, mais vous auriez besoin d'une sorte de crochet qui reconfigurerait le réseau pour les nouvelles IP.

script pour configurer le réseau :

#!/bin/bash

###############
# Global Vars #
###############

# Sat modem IP with subnet
# Ex: 1.1.1.1
SAT_MODEM_IP="1.1.1.1"

# Router IP
# Ex: 1.1.1.2
ROUTER_IP="1.1.1.2"

# Subnet in cidr notation
# Ex: 30
SUBNET_MASK="30"

# Space separated list of ports for the Pi to intercept
PORTS="8081 8082"

#####################
# Calculated Values #
#####################

# Removes the slash, in case the user wrote "/30" instead of "30" above
SUBNET_MASK=$(echo $SUBNET_MASK | tr -d '/')

# Make sure port list is property formatted for iptables
PORTS=$(echo $PORTS | sed 's/ /,/g' | tr -s ',')

##########
# Checks #
##########

# Make sure we are running as root
if ! [ $(id -u) = 0 ]
then
    echo "Error: This script must be run as root" >&2
    exit 1
fi

# Make sure ns2 doesn't already exist
if /sbin/ip netns | grep -q '^ns2'
then
    echo "Error: ns2 already exists"
    exit 1
fi

###################
# Start of Config #
###################

# Create ns2 namespace
ip netns add ns2 

# Move eth1 to ns2 namespace
ip link set eth1 netns ns2

# Configure eth1 in ns2 namespace
ip netns exec ns2 ip address add $SAT_MODEM_IP/$SUBNET_MASK dev eth1
ip netns exec ns2 ip link set eth1 up

# Enable loopback interface in ns2 namespace
ip netns exec ns2 ip link set lo up

# Create virtual interface pair, and move one of the interfaces into
# the ns2 namespace
ip link add veth type veth peer name vpeer
ip link set vpeer netns ns2

# Set ip on virtual interfaces
ip address add 192.168.90.5/24 dev veth
ip netns exec ns2 ip address add 192.168.90.6/24 dev vpeer

# Bring up both virtual interfaces
ip link set veth up
ip netns exec ns2 ip link set vpeer up

# Add DG to ns2 namespace
ip netns exec ns2 ip route add default via 192.168.90.5

# Add root namespace iptables rules
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o veth -s $SAT_MODEM_IP -j MASQUERADE
iptables -t nat -A PREROUTING -i eth0 -p udp -j DNAT --to-destination 192.168.90.6
iptables -t nat -A PREROUTING -i eth0 -p tcp -m multiport ! --dport $PORTS -j DNAT --to-destination 192.168.90.6
iptables -t nat -A PREROUTING -i eth0 -p ICMP -j DNAT --to-destination 192.168.90.6
iptables -t nat -A PREROUTING -i veth -p udp -d 192.168.90.5 -j DNAT --to-destination $SAT_MODEM_IP
iptables -t nat -A PREROUTING -i veth -p tcp -m multiport ! --dport $PORTS -d 192.168.90.5 -j DNAT --to-destination $SAT_MODEM_IP
iptables -t nat -A PREROUTING -i veth -p ICMP -d 192.168.90.5 -j DNAT --to-destination $SAT_MODEM_IP

# Add ns2 namespace iptables rules
ip netns exec ns2 iptables -t nat -A POSTROUTING -o vpeer -j MASQUERADE
ip netns exec ns2 iptables -t nat -A POSTROUTING -o eth1 -s 192.168.90.5 -j MASQUERADE
ip netns exec ns2 iptables -t nat -A PREROUTING -i vpeer -j DNAT --to-destination $ROUTER_IP
ip netns exec ns2 iptables -t nat -A PREROUTING -i eth1 -d $SAT_MODEM_IP -j DNAT --to-destination 192.168.90.5

# Add ICMP blocking
# Note: This just prevents customers from seeing LAN IPs in a
# traceroute from site, and duplicate WAN IPs in a traceroute to
# site
iptables -A OUTPUT -p ICMP -j DROP
ip netns exec ns2 iptables -A OUTPUT -p ICMP -j DROP

Remarque : je n'avais jamais utilisé d'espaces de noms de réseau auparavant, mais ils se sont avérés très faciles à comprendre et à utiliser. Voir : https://blogs.igalia.com/dpino/2016/04/10/network-namespaces/

Remarque : vous pouvez configurer un serveur DHCP sur eth1 pour donner au routeur du client une adresse IP sans qu'il ait à en définir une de manière statique, mais vous devrez exécuter votre serveur DHCP sur eth1 dans l'espace de noms ns2. Cela sort du cadre de cette question, mais recherchez l'option systemd NetworkNamespacePath, et assurez-vous de savoir comment éditer correctement un fichier d'unité systemd sans vous battre avec votre gestionnaire de paquets.

0voto

John Points 151

Dans la Question, j'ai commencé à essayer de faire de la transparence à sens unique, parce que je pensais que ce serait un point de départ plus facile, même si mon objectif final était la transparence à double sens.

Par transparence à sens unique, je veux dire que le modem ne peut voir qu'un seul appareil derrière lui (1.1.1.2), mais le routeur du client peut voir à la fois le Pi (à 1.1.1.254) et le modem à 1.1.1.1.

Le problème de la transparence à sens unique, du moins de la manière dont j'essayais de le faire, est que je masquerais les IP publiques légitimes. Ce n'est évidemment pas idéal.

La méthode suivante permet de faire fonctionner la transparence bidirectionnelle, mais elle utilise deux Raspberry Pis. Bien que cela fonctionne, et peut aider quelqu'un d'autre, j'ai besoin que cette chose exacte fonctionne sur un seul Pi, donc je vais chercher à utiliser les espaces de noms de réseau de Linux pour faire cela sur un seul Pi. Si quelqu'un a une solution qui fonctionne sur un seul Pi, faites-le moi savoir.

2 Pi Solution :

enter image description here

Étapes génériques :

  • Configurer des IPs statiques sur les deux Pis
  • Activer le routage sur les deux Pis (echo 1 > /proc/sys/net/ipv4/ip_forward)

Pi 1 :

ip route add default via 1.1.1.1

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth1 -s 1.1.1.1 -j MASQUERADE

# All UDP Ports
iptables -t nat -A PREROUTING -i eth0 -p udp -j DNAT --to-destination 192.168.90.6

# Some TCP Ports
iptables -t nat -A PREROUTING -i eth0 -p tcp -m multiport ! --dport 8081,8082 -j DNAT --to-destination 192.168.90.6

Pi 2 :

ip route add default via 192.168.90.5

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth1 -s 192.168.90.5 -j MASQUERADE

# Forwards EVERYTHING to Customer Router
iptables -t nat -A PREROUTING -i eth0 -j DNAT --to-destination 192.168.90.6

Note : J'ai abandonné cette solution 2-pi pour une solution single-pi assez rapidement, donc ce n'est pas aussi élaboré que la solution single-pi acceptée, et pourrait être amélioré si quelqu'un prévoit de l'utiliser. Elle n'est là qu'à titre de référence, car elle est plus facile à comprendre que la solution à un seul point, mais fait essentiellement la même chose.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X