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

iptables: перенаправление входящего UDP на другой порт и ответ, выходящий из «общедоступного» порта

У меня есть агент SNMP, который прослушивает порт высокого уровня (16161), и я хочу перенаправить трафик со стандартного порта агента SNMP 161. Простое правило iptables:

iptables -t nat -A PREROUTING -p udp --dport 161 -j REDIRECT --to-ports 16161

Однако ответы, похоже, приходят с порта 16161 и сбрасываются клиентами Linux.

Я хочу изменить исходный порт ответа на 161 (это также верно согласно спецификации SNMP). Я добавил:

-t nat -A POSTROUTING -p udp --sport 16161 -j SNAT --to-source :161

и это, кажется, вызывает ответы, которые никогда не покидают агента. Если я изменю to-source на любой другой порт, т.е. 162, работает. Или если я использую --dport 162 и клиент отправит запрос на порт 162, ответ может использовать порт 161. Только когда PREROUTING dport соответствует POSTROUTING to-source не отправляется ли ответ от агента.

Пример использования PREROUTING --dport 161 и РАЗМЕЩЕНИЕ --to-source 162:

snmpget -v2c -c public $DEVICE_IP iso.3.6.1.2.1.1.5.0

tcpdump от агента, исходный порт изменен на 162 в ответном пакете (ожидается :)

$ tcpdump -n udp and port 161 or port 162 or port 16161
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
19:47:30.755126 IP 192.168.66.3.55843 > 192.168.9.87.161:  GetRequest(28)  .1.3.6.1.2.1.1.5.0
19:47:30.787415 IP 192.168.9.87.162 > 192.168.66.3.55843:  GetResponse(41)  .1.3.6.1.2.1.1.5.0="foo"

Я могу даже иметь правило PREROUTING и POSTROUTING для одного и того же порта, но запрос не может поступать через тот же порт, который будет использовать ответ:

$ iptables -t nat -L -v
Chain PREROUTING (policy ACCEPT 3 packets, 313 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    2   142 REDIRECT   udp  --  any    any     anywhere             anywhere             udp dpt:snmp redir ports 16161
    0     0 REDIRECT   udp  --  any    any     anywhere             anywhere             udp dpt:snmp-trap redir ports 16161

Chain INPUT (policy ACCEPT 3 packets, 313 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    2   168 SNAT       udp  --  any    any     anywhere             anywhere             udp spt:16161 to::162

один сеанс tcpdump:

tcpdump -n udp and port 161 or port 162 or port 16161
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

>>>>>>> made request to port 161, response over 162, OK <<<<<<<<<

19:55:10.709670 IP 192.168.66.3.51621 > 192.168.9.87.161:  GetRequest(28)  .1.3.6.1.2.1.1.5.0
19:55:10.751607 IP 192.168.9.87.162 > 192.168.66.3.51621:  GetResponse(41)  .1.3.6.1.2.1.1.5.0="foo"

>>>>>>> made request to port 162, response not sent <<<<<<<<<

19:55:20.372213 IP 192.168.66.3.55108 > 192.168.9.87.162:  GetRequest(28)  .1.3.6.1.2.1.1.5.0
19:55:21.378445 IP 192.168.66.3.55108 > 192.168.9.87.162:  GetRequest(28)  .1.3.6.1.2.1.1.5.0
19:55:22.380925 IP 192.168.66.3.55108 > 192.168.9.87.162:  GetRequest(28)  .1.3.6.1.2.1.1.5.0
19:55:23.390915 IP 192.168.66.3.55108 > 192.168.9.87.162:  GetRequest(28)  .1.3.6.1.2.1.1.5.0
19:55:24.393482 IP 192.168.66.3.55108 > 192.168.9.87.162:  GetRequest(28)  .1.3.6.1.2.1.1.5.0
19:55:25.397306 IP 192.168.66.3.55108 > 192.168.9.87.162:  GetRequest(28)  .1.3.6.1.2.1.1.5.0

Как заставить мой агент принимать UDP-пакеты и отправлять ответы на один и тот же порт с помощью iptables?

Благодаря комментарию Теро на мой вопрос, используя -j DNAT вместо того REDIRECT был недостающий соус. Окончательное решение:

в правилах нац:

-A PREROUTING -p udp --dport 161 -j DNAT --to-destination :16161
-A POSTROUTING -p udp --sport 16161 -j SNAT --to-source :161

правила фильтрации:

-A INPUT -p udp --dport 16161 -m conntrack --ctstate DNAT -j ACCEPT

В --ctstate DNAT уловка пришел из этого ответа поэтому только порт 161 принимает соединения, а не 16161.