Accès au serveur Web DNAT depuis l'intérieur du LAN

12

J'ai un petit réseau avec un routeur, qui maintient une connexion Internet, un serveur et certaines stations de travail dans un réseau local.

Carte du réseau

Le serveur est censé être accessible à partir d'Internet, et il y a plusieurs entrées DNAT définies dans les iptables du routeur, comme ceci:

-A PREROUTING -i ppp0 -p tcp -m multiport --dports 22,25,80,443 -j DNAT --to-destination 192.168.2.10

Les paquets externes arrivent au routeur via l' ppp0interface, et les paquets internes en proviennent br-lan, ce qui inclut en fait le commutateur et l'adaptateur WLAN. Le problème est que, bien que l'accès externe fonctionne correctement, la tentative d'accès au serveur depuis l'intérieur du LAN par une adresse IP externe résolue par DNS (attribuée à ppp0) échoue.

La seule solution que j'ai pu inventer est d'ajouter des entrées statiques au routeur /etc/hostspointant vers l'IP interne, mais comme il n'y a pas de caractères génériques (et j'ai au moins trois domaines de premier niveau affectés à ce système, sans compter des dizaines de sous-domaines), c'est plutôt croquant et sujet aux pannes. Pouvez-vous suggérer quelque chose de mieux?

Je n'ai trouvé que cette question , qui n'était pas très utile.

Si cela est pertinent, le routeur exécute OpenWRT 10.03 Kamikaze avec dnsmasq.

whitequark
la source
Quelle version d'OpenWRT?
Corey S.
@Corey 10.03 Stable, mais cela n'a rien à voir avec openwrt lui-même, n'est-ce pas?
whitequark

Réponses:

3

Je suis surpris qu'après presque 8 ans, personne n'ait expliqué comment procéder correctement en utilisant le système de configuration UCI utilisé par défaut dans OpenWRT.

La réponse de Steven Monday est correcte, mais il utilise iptablesdirectement des commandes, qui est une couche inférieure à celle du système de configuration UCI, et il est préférable que la plupart des utilisateurs d'OpenWRT ne le touchent pas.

La manière correcte d'accéder aux serveurs internes via leurs combinaisons IP / ports publiques à partir d'un autre hôte interne dans UCI consiste à activer l'option de configuration reflectionsous chaque cible DNAT spécifique dans le fichier /etc/config/firewall. Ce comportement est documenté ici .

Par exemple:

config redirect option target 'DNAT' option src 'wan' option dest 'lan' option proto 'tcp' option src_dport '44322' option dest_ip '192.168.5.22' option dest_port '443' option name 'apache HTTPS server' option reflection '1'

Remarque: selon la documentation OpenWRT indiquée, reflectionest activé par défaut. Lors de mes tests, ce n'était pas le cas.

vittorio88
la source
15

J'ai supprimé ma réponse d'origine, car je n'étais pas entièrement convaincue qu'elle était correcte. J'ai depuis eu le temps de mettre en place un petit réseau virtuel de VMs pour simuler le réseau en question. Voici l'ensemble des règles de pare-feu qui ont fonctionné pour moi (au iptables-saveformat, pour le nattableau uniquement):

-A PREROUTING -d 89.179.245.232/32 -p tcp -m multiport --dports 22,25,80,443 -j DNAT --to-destination 192.168.2.10
-A POSTROUTING -s 192.168.2.0/24 -o ppp0 -j MASQUERADE
-A POSTROUTING -s 192.168.2.0/24 -d 192.168.2.10/32 -p tcp -m multiport --dports 22,25,80,443 -j MASQUERADE

La première POSTROUTINGrègle est un moyen simple de partager la connexion Internet avec le LAN. Je l'ai laissé là pour être complet.

La PREROUTINGrègle et la deuxième POSTROUTINGrègle établissent ensemble les NAT appropriés, de sorte que les connexions au serveur via l'adresse IP externe puissent se produire, que les connexions proviennent de l'extérieur ou de l'intérieur du LAN. Lorsque les clients sur le LAN se connectent au serveur via l'adresse IP externe, le serveur considère que les connexions proviennent de l'adresse IP interne du routeur (192.168.2.1).

Fait intéressant, il s'avère qu'il existe quelques variantes de la deuxième règle POSTROUTING qui fonctionnent également. Si la cible est remplacée par -j SNAT --to-source 192.168.2.1, l'effet est (sans surprise) le même que MASQUERADE: le serveur voit les connexions des clients LAN locaux comme provenant de l' adresse IP interne du routeur . D'un autre côté, si la cible est modifiée en -j SNAT --to-source 89.179.245.232, alors les NAT fonctionnent toujours, mais cette fois, le serveur voit les connexions des clients LAN locaux comme provenant de l' adresse IP externe du routeur (89.179.245.232).

Enfin, notez que votre PREROUTING/ DNATrègle d'origine -i ppp0ne fonctionne pas, car la règle ne correspond jamais aux paquets provenant des clients LAN (car ceux-ci n'entrent pas dans le routeur via l' ppp0interface). Il serait possible de le faire fonctionner en ajoutant une deuxième PREROUTINGrègle uniquement pour les clients LAN internes, mais elle serait inélégante (IMO) et aurait encore besoin de se référer explicitement à l'adresse IP externe.

Maintenant, même après avoir présenté en détail une solution "en épingle à cheveux NAT" (ou "NAT loopback", ou "NAT réflexion", ou comme on préfère l'appeler), je pense toujours qu'une solution DNS à horizon partagé ... -avec des clients externes se résolvant à l'IP externe et des clients internes se résolvant à l'IP interne --- serait la voie la plus recommandée à prendre. Pourquoi? Parce que plus de gens comprennent le fonctionnement du DNS que le fonctionnement du NAT, et une grande partie de la construction de bons systèmes choisit d'utiliser des pièces qui sont maintenables. Une configuration DNS est plus susceptible d'être comprise, et donc correctement entretenue, qu'une configuration NAT obscure (IMO, bien sûr).

Steven Monday
la source
Cela fonctionne parfaitement, merci beaucoup! Je suis d'accord que la configuration DNS est meilleure, mais vous ne pouvez pas transférer différents ports sur la même IP externe vers différentes machines sur LAN avec elle. Quoi qu'il en soit, je suis le seul à maintenir cette configuration, donc ça va.
whitequark
Je suis content d'apprendre que cela a fonctionné pour vous!
Steven lundi
Qu'est-ce que "IMO"? Organisation Internationale des Météores www.imo.net?
Jonathan Komar
@ macmadness86 IMO == À mon avis
Steven lundi
3

Une solution courante consiste à pointer vos hôtes internes vers un serveur DNS local qui renvoie l'adresse "interne" correcte pour ces noms d'hôtes.

Une autre solution - et nous l'utilisons là où je travaille sur nos pare-feu Cisco - consiste à réécrire les réponses DNS sur le pare-feu qui correspondent à ces adresses. Je ne pense pas qu'il existe actuellement des outils pour Linux qui le fassent.

Vous devriez pouvoir configurer le routage sur votre passerelle pour faire la bonne chose. Vous devrez peut-être configurer les serveurs pour qu'ils soient conscients de leur adresse IP mappée en externe (par exemple, en l'affectant à une interface factice). Avec cette configuration, la communication d'un système interne à un autre système interne - en utilisant son adresse «externe» - passerait par le routeur.

larsks
la source
Hmm. Suggérez-vous donc d'ajouter l'IP externe aux interfaces des serveurs, puis de configurer le routeur pour qu'il transfère tous les paquets à l'IP externe provenant de l'intérieur du LAN vers ce serveur? Intéressant, je vais le tester bientôt.
whitequark
Pouvez-vous suggérer la configuration? J'ai essayé ceci:, ip rule add to 89.179.245.232 dev br-lan table 10; ip route add 89.179.245.232 via 192.168.2.10 dev br-lan table 10et ça ne marche pas.
whitequark
Que contient la table de routage 10? Sur les serveurs internes, vous souhaitez probablement qu'ils aient à la fois une adresse locale 192.168.xx (pour communiquer localement) et l'adresse publique (en tant qu'alias) sur leur interface principale.
larsks
2

Ce que vous demandez à faire est appelé NAT Loopbacket cela nécessite que vous ajoutiez une règle SNAT pour que les paquets provenant de votre réseau local vers votre serveur reviennent via le routeur:

-A POSTROUTING -p tcp -s 192.168.2.0/24 -d 192.168.2.10 -m multiport --dports 22,25,80,443 -j SNAT --to-source 89.179.245.232
SiegeX
la source
Malheureusement, cela ne fonctionne pas. J'ai à l'origine manqué l' -i ppp0option dans ma règle en question, car elle était gérée par une autre chaîne; cette règle empêcherait le routage des paquets provenant du LAN (et si je l'activais, les paquets iraient d'une mauvaise source et seront rejetés).
whitequark
L'as tu essayé? Cela n'affectera que les paquets de votre réseau local allant vers l'IP de votre serveur sur ces ports très spécifiques.
SiegeX
Oui je l'ai fait. (Et j'ai aussi essayé de changer la première règle). Par exemple, dig envoie un paquet au 192.168.2.1 # 53, puis obtient une réponse inattendue de 192.168.2.10 # 53, avec ou sans votre règle.
whitequark
0

larsks commente l'hébergement d'une version interne du namespace \ domain est généralement la façon dont j'ai géré ce problème dans le passé. Bien sûr, vous avez besoin d'un serveur DNS en interne pour ce faire.

CurtM
la source
Oui, j'ai écrit que j'utilisais dnsmasq. Des idées sur la mise en place d'une substitution automatique?
whitequark
Je ne sais rien d'OpenWRT et de Kamikaze, mais d'après ce que je lis - et si vous ajoutiez ce qui suit à votre /etc/dnsmasq.conf "cname = ext-hostname.domain.com, int-hostname.domain.com"
CurtM
Eh bien, pour autant que j'ai pu le déterminer, dnsmasq cnamene prend pas en charge les masques, et n'est donc pas applicable pour moi en raison du nombre de sous-domaines.
whitequark
0

J'ai proposé la solution suivante pour permettre à mon réseau invité de se connecter aux ports qui ont été transférés de mon réseau étendu vers le réseau local. Ce script est placé dans ma section "Réseau -> Pare-feu -> Règles personnalisées":

# lookup the public IP (DDNS resolves to this)
wanip=$(ip route get 8.8.8.8 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}')

# Guest network to LAN
# srcname is the guest network name, this needs to match for iptables
srcname=guest
# CIDR notation of guest and lan networks
srcnet=192.168.15.0/24
tgtnet=192.168.10.0/24
# router (openwrt) IP on lan network
tgtrouter=192.168.10.1
# host on lan network where ports are normally forwarded
tgthost=192.168.10.5
# ports to forward as a list or range
tcpports=8080,9090
udpports=12345

prechain=prerouting_${srcname}_rule
postchain=postrouting_${srcname}_rule

# reset the tables to prevent duplicate rules
iptables -t nat -F ${prechain}
iptables -t nat -F ${postchain}

iptables -t nat -A ${prechain} -s ${srcnet} -d ${wanip}/32 -p tcp -m tcp -m multiport --dports ${tcpports} -m comment --comment "${srcname} NAT reflection TCP DNAT" -j DNAT --to-destination ${tgthost}
iptables -t nat -A ${postchain} -s ${srcnet} -d ${tgthost}/32 -p tcp -m tcp -m multiport --dports ${tcpports} -m comment --comment "${srcname} NAT reflection TCP SNAT" -j SNAT --to-source ${tgtrouter}
iptables -t nat -A ${prechain} -s ${srcnet} -d ${wanip}/32 -p udp -m udp -m multiport --dports ${udpports} -m comment --comment "${srcname} NAT reflection UDP DNAT" -j DNAT --to-destination ${tgthost}
iptables -t nat -A ${postchain} -s ${srcnet} -d ${tgthost}/32 -p udp -m udp -m multiport --dports ${udpports} -m comment --comment "${srcname} NAT reflection UDP SNAT" -j SNAT --to-source ${tgtrouter}

Pour prendre en charge les redémarrages, je devais exécuter ce qui suit à partir de la ligne de commande ssh sur openwrt (sinon, je crois qu'il existe une condition de concurrence critique où certaines règles ont été ajoutées puis vidées lors du redémarrage):

uci set firewall.@include[0].reload="1"
uci commit firewall

La réflexion NAT est configurée pour les connexions au sein du réseau LAN à lui-même, mais pas à d'autres réseaux si vous avez créé plusieurs interfaces pour isoler le trafic. J'ai essayé de configurer une règle de transfert à partir de l'interface Web, mais cela envoie tout le trafic vers un port du réseau invité vers cet hôte LAN. Ce qui précède intercepte uniquement les demandes adressées à l'adresse IP WAN au lieu de tout le trafic réseau.

Un DNS interne pourrait être utilisé à la place de cela, mais uniquement si tous les ports redirigés ne vont qu'à un seul hôte. Si vous avez plusieurs hôtes sur lesquels vous transférez différents ports, vous pouvez répéter les règles pour différents ports vers des tgthostIP et des ports différents.

BMitch
la source
Dans les noyaux actuels, il existe un conntrackmodule de correspondance. Et tout ce dont vous avez besoin pour résoudre le problème est d'utiliser la règle unique comme celle-ci:iptables -t nat -A POSTROUTING --dst <lan-net> ! --src <lan-gw-ip> -m conntrack --ctstate DNAT --ctorigdst <wan-gw-ip> -j MASQUERADE
Anton Danilov
@AntonDanilov sympa, j'aime ça. Les règles que j'ai utilisées étaient basées sur des règles NAT de réflexion déjà dans OpenWRT pour les connexions à partir du même sous-réseau. Je ne sais pas s'ils avaient d'autres raisons à cela que d'être écrites avant que conntrack ne soit disponible.
BMitch