NAT 1: 1 avec plusieurs LAN identiques

13

Je souhaite connecter plusieurs réseaux locaux situés sur des bâtiments éloignés.
Le site "central" possède un ordinateur Linux exécutant OpenVPN. Chaque site distant exécute également OpenVPN.

  1. le site central a un LAN numéroté 192.168.0.0/24
  2. plusieurs sites distants sont également numérotés 192.168.0.0/24
  3. Je ne peux pas / ne veux pas / ne souhaite pas modifier la numérotation LAN
  4. Je n'ai aucun contrôle sur la plupart des OpenVPN distants

Je dois ensuite:
1. définir des LAN virtuels
2. configurer un NAT 1: 1 pour chaque site
3. le NAT 1: 1 doit être configuré sur le routeur central

Carte LAN .
Ainsi, chaque site est considéré comme ayant un LAN 10.10.x.0 / 24.
Quand un ordinateur veut atteindre, disons, 192.168.0.44 sur le site 12, il suffit d'envoyer un paquet au 10.10.12.44

L'exploitation d'un VPN n'est pas un problème pour moi. Je connecte actuellement plus de 60 sites. Mais je ne trouve pas un moyen simple de faire ce NAT 1: 1.

Voici un exemple d'un paquet envoyé depuis le site central vers un site distant et son paquet de réponse:

entrez la description de l'image ici

J'ai fait quelques tests avec iptables NETMAP mais je n'arrive pas à le faire fonctionner car je ne trouve pas un moyen de modifier la source + destination après la décision de routage.
Je préfère éviter la nouvelle fonctionnalité d' --client-natOpenVPN.
Peut-être que je dois forcer le routage avec ip route? Ou pour boucler deux fois dans la pile réseau avec veth?

Remarque: je ne veux pas utiliser la mascarade. Seulement 1/1 NAT.

EDIT:
Ce n'est pas possible avec une configuration openVPN régulière. Parce qu'un paquet provenant d'un site distant ne se distingue pas d'un paquet provenant d'un autre site: les deux ont des adresses source et de destination similaires, et tous deux proviennent de la même interface tun (ou tap). Il n'est donc pas possible de le NAT source.

Solution 1: faites le NAT sur les sites distants. Pas possible dans mon cas. Je dois le faire uniquement sur le site central.

Solution 2: configurez un VPN pour chaque site distant. Je vais donc avoir un tun pour chacun. Je pense que cela peut être ok. Pas très efficace en mémoire mais ok.

Solution 3: configurez un tunnel (non chiffré) à l'intérieur du VPN pour chaque site. Cela donnera une interface pour chacun. Les tunnels simples ne sont pas multi-plateformes (à mon sens). Par exemple, GRE ou ipip ou sit sont ok pour Linux, mais certains sites distants exécutent un seul ordinateur Windows, donc openVPN y est installé. Il est donc impossible de configurer un tunnel simple. Une autre option consiste à utiliser un tunnel plus compliqué (qui?), Mais la surcharge sur le système et sur l'administrateur système peut être plus importante que d'avoir plusieurs VPN

Solution 4: compilez le dernier openVPN, car il inclut une fonction NAT 1: 1. Je teste cette semaine.

Bertrand SCHITS
la source
1
Pour la solution 4, vous n'avez pas besoin de compiler. La plupart des principales distributions Linux ont compilé des packages sur le site officiel openVPN. Mais cela ne fonctionnera pas pour vous car la fonction --client-nat est une option pouvant être poussée. Vos clients doivent donc également utiliser la dernière version RC (et vous dites que vous n'avez aucun contrôle sur les sites distants).
Gregory MOUSSAT
1
Eh bien, je me trompe: la fonctionnalité --client-nat est 100% à l'intérieur d'OpenVPN (je pensais qu'elle utilisait ipfilter). Je viens de tester: ça marche aussi sur Windows. Voir ma solution ci-dessous.
Gregory MOUSSAT
J'aimerais savoir si vous avez réussi à faire fonctionner ce travail et ce que vous avez fait.
Michael Grant

Réponses:

2

Une solution très basique est la suivante:
1. utiliser OpenVPN 2.3 ou plus (actuellement, la dernière est la version 2.3-alpha) pour le serveur + les clients
2. utiliser l'option de configuration OpenVPN ci-dessous
3. ne rien utiliser d'autre (pas de filtre ip, pas de trucs)

Côté serveur, vous devez distribuer manuellement les adresses VPN (donc pas d' serveroption, vous devez utiliser ifconfigou ifconfig-push):

# /etc/openvpn/server.conf
ifconfig 10.99.99.1 10.99.99.2
route 10.99.99.0 255.255.255.0
push "route 10.99.99.0 255.255.255.0"
push "client-nat dnat 10.99.99.11 255.255.255.255 10.10.111.11"
push "client-nat dnat 10.99.99.12 255.255.255.255 10.10.112.12"
push "client-nat dnat 10.99.99.13 255.255.255.255 10.10.113.13"

Les lignes routeet push routeet client-natsont nécessaires si vous souhaitez communiquer directement entre les routeurs (à ping 10.99.99.1partir d'un site distant via le VPN). Sinon, vous pouvez les jeter.

.

.

Vous devez maintenant choisir une adresse de réseau virtuel. J'ai gardé le même que vous avez utilisé dans votre exemple: 10.10.0.0/16
Vous autorisez le routage pour cela:

# /etc/openvpn/server.conf
route 10.10.0.0 255.255.0.0
push "route 10.10.0.0   255.255.0.0"

.

.

Vous devez maintenant demander au client d'utiliser le NAT 1: 1:

# /etc/openvpn/ccd/client_11
ifconfig-push 10.99.99.11 10.99.99.1
push "client-nat snat 10.99.99.11 255.255.255.255 10.10.111.11"
push "client-nat snat 192.168.0.0 255.255.255.0 10.10.11.0"
push "client-nat dnat 10.10.10.0 255.255.255.0 192.168.0.0"
iroute 10.10.11.0 255.255.255.0
iroute 10.10.111.0 255.255.255.0

La première ligne définit l'adresse du routeur distant. Méfiez-vous des pilotes Windows nécessitant des adresses spéciales.
Les deuxième et dernière lignes permettent au routeur distant de communiquer à partir de son interface 10.99.99.x.
Les troisième et quatrième lignes font la source et la destination 1: 1 NAT
La cinquième ligne indique à OpenVPN quoi faire avec les paquets correspondants.

Cette méthode permet de connecter des sites avec des adresses LAN identiques (ou non), sans hôte masqué.

Gregory MOUSSAT
la source
1
Simple, brillant.
Bertrand SCHITS
J'ai essayé mais je n'ai pas réussi à le faire fonctionner. J'utilise Linux des deux côtés. Quelque chose est étrange ou je ne comprends pas bien quelque chose. Votre ifconfig-push dans le fichier client_11 (première ligne), ne devrait-il pas s'agir d'un masque de réseau pour le deuxième argument au lieu de 10.99.99.1? Deuxièmement, pourquoi utilisez-vous ce troisième réseau 10.10.111.0/24? Il semble que vous essayez d'utiliser le réseau 111 pour la communication entre les sites, le réseau 10.10 ne peut-il pas être utilisé directement pour cela? Enfin, peu importe ce que j'essaye, je ne vois pas (dans tcpdump) le snat et le dnat affectant les paquets sur le client.
Michael Grant
Pas vraiment simple mais toujours génial.
Neurotransmetteur
4

J'ai fait quelque chose de similaire avec de vraies interfaces, mais je ne vois pas pourquoi cela ne fonctionnerait pas avec les interfaces VPN.

L'idée est que, comme vous avez le même sous-réseau disponible à différentes interfaces sur ce routeur, cela complique le routage. Fondamentalement, lorsqu'un paquet pour 10.10.13.123 entre dans le routeur, il est DNATé avant le routage vers 192.168.0.123, vous devez donc être en mesure de dire au routage qu'il était destiné au 192.168.0.123 sur l'interface VPN13 .

Cela peut être fait en utilisant des marques de pare-feu et des règles de routage qui utilisent ces marques. SNAT et DNAT doivent être effectués avec la cible de pare-feu NETMAP. Pour SNAT, c'est le même problème, en POSTROUTING, vous avez perdu l'information que le paquet provenait de telle ou telle interface et ils ont tous l'adresse source 192.168.0.x. Vous avez donc également besoin d'une marque pour transporter ces informations de mangle-PREROUTING à nat-POSTROUTING. Vous pouvez utiliser la même marque, mais cela signifierait que ces paquets utiliseraient cette table de routage alternative, vous devez donc dupliquer la table de routage globale sur tous.

Pour chaque réseau, vous feriez:

lnet=192.168.0.0/24
if10=eth0 if11=tun0 if12=tun1 if13=tun2

n=0
for site in 10 11 12 13; do
  table=$site
  net=10.10.$site.0/24
  n=$(($n + 1))
  eval "interface=\$if$site"
  inmark=$(($n * 2)) outmark=$(($n * 2 + 1))

  iptables -t nat -A PREROUTING -d "$net" -j NETMAP --to "$lnet"
  iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -m mark --mark "$inmark"/0xf -j NETMAP --to "$net"
  iptables -t mangle -A PREROUTING -i "$interface" -j MARK --set-mark "$inmark"/0xf
  iptables -t mangle -A PREROUTING -d "$net" -j MARK --set-mark "$outmark"/0xf
  ip rule add fwmark "$outmark"/0xf table "$table"
  ip route add "$lnet" dev "$interface" table "$table"
done

Ci-dessus, nous utilisons les 4 premiers bits de la marque , pour permettre à 7 réseaux d'être routés de cette façon.

Stéphane Chazelas
la source
1
Merci pour votre réponse. Je l'ai testé mais ça ne marche pas. J'ai testé avec un seul LAN, plus de résultat. J'utilise tcpdump pour surveiller les paquets, et quand j'envoie un paquet d'un site distant à un site central, je ne vois même rien (?! Comment est-ce possible?). Avec vos instructions, j'essaie de construire ma réponse étape par étape. Je ne suis pas sûr de réussir.
Bertrand SCHITS du
2
Ma réponse ne couvre que ce qu'il faut faire sur le site central. Je suppose que vous configurez correctement le routage sur les autres sites. Par exemple, vous devrez probablement ajouter une route vers 10.10.0.0/16 via le tunnel VPN sur les sites distants. Vous devrez peut-être également dire à openvpn de laisser passer ces paquets. Dans tous les cas, utiliser tcpdump pour voir quels paquets arrivent où et comment est la bonne approche. la cible iptables LOG est aussi votre amie.
Stéphane Chazelas
2
Si vous ne voyez aucun paquet, vous devez consulter votre journal openvpn. Vous trouverez probablement des paquets perdus. Si tel est le cas, utilisez un "iroute 192.168.0.0 255.255.255.0" pour chaque client dans votre
répertoire de