IPTables et questions DHCP?

8

Sur mon autre fil, je parlais de choses intéressantes sur la politique et les états d'iptables , maintenant j'aimerais mieux comprendre comment fonctionne DHCP et comment iptables le comprend.

ETH0 est connecté à mon commutateur principal qui reçoit l'IP dynamique de mon routeur pour accéder non seulement à Internet mais aussi à mon réseau externe.

ETH1 est la carte interne qui est connectée à un commutateur interne où les clients X reçoivent leur IPS de ce serveur

Le réseau ETH1 est 192.168.1.0/255.255.255.0 où l'adresse IP du serveur est 192.168.1.254.

D'après ce que j'ai compris, dhcp est un protocole bootp, donc même si vous avez vos politiques de pare-feu pour tout supprimer, votre réseau recevrait toujours le DHCP, ce qui, dans les tests que j'ai faits, semblait être vrai.

Depuis tcpdump:

root@test:~# tcpdump -i eth1 port 67 or 68
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
11:34:03.943928 IP 192.168.1.2.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:0c:29:29:52:8b (oui Unknown), length 303
11:34:03.957647 IP 192.168.1.254.bootps > 192.168.1.2.bootpc: BOOTP/DHCP, Reply, length 300
11:34:06.492153 IP 192.168.1.2.bootpc > 192.168.1.254.bootps: BOOTP/DHCP, Request from 00:0c:29:29:52:8b (oui Unknown), length 303
11:34:06.506593 IP 192.168.1.254.bootps > 192.168.1.2.bootpc: BOOTP/DHCP, Reply, length 300

J'ai créé une règle de journal simple pour voir ce que fait iptables:

root@test:~# tail -f /var/log/syslog
Oct 15 11:30:58 test kernel: IN=eth1 OUT= MAC=ff:ff:ff:ff:ff:ff:00:0c:29:29:52:8b:08:00 SRC=192.168.1.2 DST=255.255.255.255 LEN=331 TOS=0x00 PREC=0x00 TTL=128 ID=9527 PROTO=UDP SPT=68 DPT=67 LEN=311
Oct 15 11:31:43 test kernel: IN=eth1 OUT= MAC=ff:ff:ff:ff:ff:ff:00:0c:29:29:52:8b:08:00 SRC=192.168.1.2 DST=255.255.255.255 LEN=331 TOS=0x00 PREC=0x00 TTL=128 ID=9529 PROTO=UDP SPT=68 DPT=67 LEN=311
Oct 15 11:33:32 test kernel: IN=eth1 OUT= MAC=ff:ff:ff:ff:ff:ff:00:0c:29:29:52:8b:08:00 SRC=192.168.1.2 DST=255.255.255.255 LEN=331 TOS=0x00 PREC=0x00 TTL=128 ID=9531 PROTO=UDP SPT=68 DPT=67 LEN=311
Oct 15 11:34:03 test kernel: IN=eth1 OUT= MAC=ff:ff:ff:ff:ff:ff:00:0c:29:29:52:8b:08:00 SRC=192.168.1.2 DST=255.255.255.255 LEN=331 TOS=0x00 PREC=0x00 TTL=128 ID=9533 PROTO=UDP SPT=68 DPT=67 LEN=311

Voici mes règles iptables au momment:

# deny all traffic
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT DROP

# Use stateful inspection feature to only allow incoming connections
# related to connections I have already established myself
$IPT -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# allow all traffic on lo interface
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

Donc, même avec la POLITIQUE par défaut pour supprimer tout, j'obtiens toujours le DHCP sur mon réseau alors qu'il faut beaucoup plus de temps pour renouveler une IP et autres.

Si j'ajoute la règle de suivi à mon pare-feu:

$IPT -I OUTPUT -o $INTIF -p udp --dport 67:68 --sport 67:68 -j ACCEPT

Il faudra beaucoup moins de temps pour mettre à jour n'importe quel DHCP client.

Compte tenu de ce qui précède:

  1. pourquoi faut-il en effet plus de temps pour le mettre à jour alors qu'il n'était pas bloqué?
  2. est-il possible de supprimer le serveur DHCP du tout sans l'éteindre?
  3. est-il possible d'accepter le serveur dhcp dans iptables avec le BOOTP? comment cela se fait-il?

Si vous connaissez de bons liens, cela ne me dérangerait pas d'en prendre beaucoup :)

Guapo
la source
Je suis un peu confus par votre sortie de journal tcpdump et iptables. Surveillez-vous l'interface réseau en mode promiscuous? Votre serveur pare-feu utilise-t-il réellement DHCP pour configurer sa carte réseau?
Steven lundi
@Steven le serveur qui a le pare-feu qui est celui mentionné ci-dessus a eth0 et eth1, eth0 reçoit dhcp en tant que client de l'extérieur et eth1 est mon serveur dhcp pour mon réseau interne qui est celui dont je parle. Que voulez-vous dire par Are you monitoring the network interface in promiscuous modej'apprends encore ...
Guapo
Ah d'accord. Vous avez vraiment besoin de mieux décrire votre réseau et vos serveurs si vous voulez que quelqu'un comprenne votre question!
Steven lundi
À propos du mode promiscous: en.wikipedia.org/wiki/Promiscuous_mode
Steven lundi
@Steven le fera maintenant, merci de le signaler, pensez-vous que je dois spécifier autre chose que la disposition du réseau?
Guapo

Réponses:

13

Je répondrai # 2: Non.

Lors de l'obtention d'une adresse IP, le démon dhcp crée un socket brut pour l'interface réseau et gère le protocole UDP lui-même. Ainsi, les paquets UDP ne passent jamais par iptables.

La raison pour laquelle le démon dhcp doit implémenter UDP est que le noyau ne peut gérer UDP (en fait la totalité de la suite TCP / IP) que lorsque l'interface a une adresse IP. Auparavant, les démons dhcp donnaient d'abord à une interface l'adresse IP de 0.0.0.0 mais cela ne fonctionnait plus.

Mark Wagner
la source
socket de paquet . prises premières ne passent par iptables. afaict. unix.stackexchange.com/a/447524/29483
sourcejedi
5

Ajouter

$IPT -I INPUT -i $INTIF -p udp --dport 67:68 --sport 67:68 -j ACCEPT

doit rendre la mise à jour DHCPD plus rapide :) Il doit fonctionner à la fois côté entrée et sortie. Vous pouvez DROP dhcpd avec ebtables, pas avec iptables. DHCPD écoute à 0.0.0.0, pas dans IP

Ta Coen
la source
+1 Je l'avais sur INPUT et cela prenait le même temps que si je ne l'avais pas sur mes règles. Quand je l'ai fait OUTPUT, cela a fait une énorme différence. Je vais lire sur ebtables merci.
Guapo
$ IPT -I INPUT -i $ INTIF -s 0/0 -p udp --dport 67:68 --sport 67:68 -j ACCEPT
Ta Coen
vient d'essayer ce qui précède et prend encore trop de temps par rapport à l'utilisation de la règle OUTPUT.
Guapo
Étant donné que la stratégie est DROP, vous devez utiliser à la fois INPUT et OUTPUT.
Ta Coen du
3

Ma récente observation, sur OpenWRT Kamikaze 7.09 = 2.4.34 et udhcpc de busybox 1.4.2:

J'ai une politique "ACCEPT" dans la chaîne OUTPUT, et dans le sens INPUT, à l'origine je me suis appuyé sur cette règle fourre-tout classique:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

pour autoriser les réponses DHCP dans (à mon udhcpc) ​​sur l'interface WAN. C'est-à-dire que c'est là que le serveur DHCP en amont de mon FAI m'attribue une adresse IP.

Faites attention à la différence entre un échange DHCP initial (découverte, offre, demande, accusé de réception) et un renouvellement de bail DHCP (demande, accusé de réception).

Après le démarrage, udhcpc démarre par l'échange initial complet. Cet échange allait réussir. Et un autre renouvellement ou deux réussirait aussi - juste une demande et un accusé de réception. Le serveur DHCP de mon FAI demande généralement un temps de renouvellement d'environ une heure à 1,5 heure, donc mon client DHCP demande un renouvellement toutes les 30 à 45 minutes (ce comportement est basé sur le RFC).

Mais, vers le troisième ou le quatrième renouvellement, cela commencerait à devenir intéressant. TCPdump afficherait environ trois tentatives de renouvellement, suivies d'un échange initial complet - dans un laps de temps de quelques minutes, voire quelques secondes. Comme si udhcpc n'aimait pas ce qu'il a récupéré :-( et serait finalement satisfait de l'échange complet. Après cela, un autre renouvellement dans une demi-heure réussirait ... et l'histoire se répéterait à nouveau.

J'ai compris que c'est peut-être le suivi des connexions dans le noyau qui a quelque chose de mal. Comme si l'entrée conntrack expirait au bout de deux heures environ, et que les renouvellements DHCP ultérieurs échouaient parce que l'ACK du serveur ne parvient pas réellement à écouter udhcpc sur le socket. Notez que tcpdump (libpcap) écoute sur l'interface brute et peut voir tous les paquets entrant, avant d'être soumis à iptables. Une fois que udhcpc abandonne les renouvellements et, désespéré, essaie de recommencer à zéro en utilisant un échange complet (en commençant par DISCOVER), le noyau établit une nouvelle entrée conntrack et peut comprendre les paquets associés pendant un certain temps ...

Effectivement, une fois que j'ai ajouté quelque chose comme:

iptables -A INPUT -i $OUT_IF -p udp --sport 67 --dport 68 -j ACCEPT

les renouvellements semblent fonctionner pour toujours.

Les arguments de la cmdline tcpdump peuvent être utiles:

tcpdump -vv -s 1500 -i eth0.1 port 67 or port 68

Remarque: le -vvdemande la sortie du dissecteur détaillé. eth0.1est mon port WAN (également une interface "NAT en dehors").

Un attribut intéressant dans les paquets ACK est le champ LT: = durée de bail suggérée / maximale accordée en secondes. Les demandes DHCP sont envoyées du port 68 au port 67. Les réponses proviennent du port 67 au port 68.

frr
la source
Votre histoire n'a aucun sens. Peu importe qu'il soit initial ou renouvelé, l'échange DHCP est toujours démarré par le client envoyant du port 68 au port 67, soit vers une adresse IP spécifique, soit sous forme de diffusion. Et avec ACCEPT sortant, cela fonctionnera toujours. Une réponse de la destination sortante doit toujours transiter par la règle ESTABLISHED entrante, donc le renouvellement doit fonctionner pour toujours avec uniquement la règle ESTABLISHED car chaque renouvellement renouvelle ou recrée également l'état conntrack.
Mecki
Un renouvellement envoie une demande openwrt:68 -> dhcpserver:67et l'ACK sera dhcpserver:67 -> openwrt:68. Cela compte comme ÉTABLI et passera. Si l'ancien état conntrack a expiré, cela en établit un nouveau. S'il y a un problème, il ne peut s'agir que de l'échange initial tel que le DISCOVER est 0.0.0.0:68 -> 255.255.255.255:67et l'OFFRE sera dhcpserver:67 -> new-openwrt:68, ce qui ne compte pas comme ÉTABLI. Cela ne fonctionne que comme DHCP contourne généralement iptables avec un socket de paquet sous Linux, sinon une règle entrante est requise qui autorise les paquets du port UDP 67 ou vers le port UDP 68.
Mecki
1
Vous dites également que plusieurs renouvellements ont réussi, mais chaque renouvellement qui réussit renouvellera également l'état conntrack, donc si vos états conntrack expirent après 2 heures, un renouvellement le prolongerait encore de 2 heures et ainsi de suite et donc il n'expirera jamais . Cependant, le délai d'expiration conntrack par défaut pour UDP n'est que de 30 secondes et non de 2 heures et je doute qu'OpenWRT ait changé cela en 2 heures car ce serait fou. Votre histoire me semble donc totalement imparfaite.
Mecki
@Mecki, merci pour les précieux commentaires :-) À ce jour, ma réponse a 4 ans. Il y a environ un an, mon ASUS WL500G Deluxe commençait à devenir floconneux en phase terminale (après environ 12 ans d'exécution, en raison du remplacement des condensateurs) et j'ai jeté ce vieux Kamikaze avec le matériel. En ce moment, je lance un OpenWRT plus récent sur un AP TP-Link moderne, et après réflexion, je n'ai pas réutilisé mes anciens scripts de pare-feu. OpenWRT semble maintenant avoir un bon pare-feu prêt à l'emploi ... Je veux dire que je ne peux pas vérifier mes revendications passées. Tout ce que je sais, c'est que la règle des iptables supplémentaires a aidé.
TRF