У меня есть агент 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.