Назад | Перейти на главную страницу

Вопросы по IPTables и DHCP?

В другой ветке я рассказывал о некоторых интересных вещах о политике и состояниях iptables, теперь я хотел бы больше узнать о том, как работает DHCP и как его понимает iptables.

ETH0 подключен к моему главному коммутатору, который получает динамический IP-адрес от моего маршрутизатора, чтобы получить не только доступ в Интернет, но и доступ к моей внешней сети.

ETH1 - это внутренняя карта, которая подключена к внутреннему коммутатору, где клиенты X получают свои IPS с этого сервера.

Сеть ETH1 - 192.168.1.0/255.255.255.0, IP-адрес сервера - 192.168.1.254.

Насколько я понял, dhcp - это протокол bootp, поэтому, даже если у вас есть политики брандмауэра, позволяющие отбрасывать все, ваша сеть все равно будет получать DHCP, что в проведенных мною тестах казалось правдой.

Из 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

Я сделал простое правило журнала, чтобы увидеть, что делает 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

Вот мои правила iptables на момент создания:

# 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

Таким образом, даже с ПОЛИТИКОЙ по умолчанию - отказаться от всего, я все равно получаю DHCP в моей сети, хотя для обновления IP-адреса требуется намного больше времени.

Если я добавлю в свой брандмауэр следующее правило:

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

Для обновления любого клиентского dhcp потребуется МЕНЬШЕ ВРЕМЕНИ.

Учитывая вышеизложенное:

  1. почему обновление действительно занимает больше времени, даже если оно не заблокировано?
  2. возможно ли вообще DROP-сервер dhcp, не выключая его?
  3. возможно ли ПРИНЯТЬ dhcp-сервер в iptables с помощью BOOTP? как это делается?

Если вы знаете хорошие ссылки, я бы не прочь взять много :)

Я отвечу №2: Нет.

При получении IP-адреса демон dhcp создает необработанный сокет для сетевого интерфейса и обрабатывает сам протокол UDP. Таким образом, пакеты UDP никогда не проходят через iptables.

Причина, по которой демон dhcp должен реализовывать UDP, заключается в том, что ядро ​​может обрабатывать UDP (фактически, весь пакет TCP / IP), только когда интерфейс имеет IP-адрес. Раньше демоны dhcp сначала давали интерфейсу IP-адрес 0.0.0.0, но это больше не работает.

Добавление

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

должен ускорить обновление DHCPD :) Он должен работать как на ВХОД, так и на ВЫВОД. Вы можете УДАЛИТЬ dhcpd с помощью ebtables, но не с помощью iptables. DHCPD прослушивает 0.0.0.0, а не IP

Мое недавнее наблюдение на OpenWRT Kamikaze 7.09 = 2.4.34 и udhcpc из busybox 1.4.2:

У меня есть политика «ПРИНЯТЬ» в цепочке OUTPUT, а в направлении INPUT изначально я полагался на это классическое универсальное правило:

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

чтобы разрешить ответы DHCP в (на мой udhcpc) ​​на интерфейсе WAN. То есть здесь восходящий DHCP-сервер моего интернет-провайдера назначает мне IP-адрес.

Обратите внимание на разницу между начальным обменом DHCP (обнаружение, предложение, запрос, подтверждение) и продлением аренды DHCP (запрос, подтверждение).

После загрузки udhcpc запускает полный первоначальный обмен. Этот обмен будет успешным. И еще одно или два обновления тоже будут успешными - просто просьба и подтверждение. DHCP-сервер моего интернет-провайдера обычно запрашивает время обновления от примерно часа до 1,5 часов, поэтому мой DHCP-клиент запрашивает обновление каждые 30-45 минут (это поведение основано на RFC).

Но примерно при третьем или четвертом обновлении стало бы интересно. TCPdump покажет около трех попыток обновления, за которыми последует полный первоначальный обмен - всего за несколько минут или даже секунд. Как будто udhcpc не понравилось то, что он получил обратно :-( и в конечном итоге будет удовлетворен полным обменом. После этого будет выполнено еще одно обновление через полчаса ... и история повторится снова.

Я понял, что, возможно, что-то не так с отслеживанием соединения в ядре. Как будто запись conntrack истекает через два часа или около того, а последующие обновления DHCP завершаются неудачно, потому что ACK от сервера фактически не передает udhcpc, прослушивающий сокет. Обратите внимание, что tcpdump (libpcap) прослушивает необработанный интерфейс и может видеть все входящие пакеты до того, как они попадут в iptables. Как только udhcpc отказывается от обновлений и в отчаянии пытается начать с нуля, используя полный обмен (начиная с DISCOVER), ядро ​​создает новую запись conntrack и может еще некоторое время понимать связанные пакеты ...

Конечно, однажды я добавил что-то вроде:

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

обновления, кажется, работают вечно.

Вы можете найти следующие аргументы командной строки tcpdump:

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

Обратите внимание -vv запрашивает подробный вывод диссектора. eth0.1 это мой порт WAN (также интерфейс "NAT за пределами").

Интересным атрибутом в пакетах ACK является LT: field = предлагаемое / максимальное предоставленное время аренды в секундах. Запросы DHCP отправляются с порта 68 на порт 67. Ответы приходят с порта 67 на порт 68.