воскресенье, 17 ноября 2013 г.

Как написать правило SNAT в iptables для интерфейса с динамическим IP

Прихожу на работу утром, а бухгалтера жалуются, что не работает "Система Город".
Для подключения используется "централизованный" OpenVPN на роутере предприятия.
Проверяю состояние интерфейса:


и маршрутизацию:
# route -n | grep 10.221.128
10.221.128.0    0.0.0.0         255.255.128.0   U     0      0        0 tap0


 - все в порядке.
Проверяю телнетом со своего компа - не проваливается.
Хм.
Рестартанул скрипт rc.firewall - не помогает.
Смотрю tcpdump-ом на интерфейсе роутера:

# tcpdump -qnn -i tap0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap0, link-type EN10MB (Ethernet), capture size 65535 bytes
09:03:20.927793 IP 10.221.130.209.60475 > 10.221.128.1.3389: tcp 0
09:03:22.166023 ARP, Request who-has 10.221.130.209 tell 10.221.128.1, length 28
09:03:23.926820 IP 10.221.130.209.60475 > 10.221.128.1.3389: tcp 0
09:03:24.674988 ARP, Request who-has 10.221.130.209 tell 10.221.128.1, length 28

Отсюда понимаю, что система не знает ничего об адресе 10.221.130.209 - а это по идее адрес нашего интерфейса tap0.
Проверяю состояние tap0:
# ifconfig tap0
tap0      Link encap:Ethernet  HWaddr B2:2F:7F:0B:A3:3B
          inet addr:10.221.141.98  Bcast:10.221.255.255  Mask:255.255.128.0
          inet6 addr: fe80::b02f:7fff:fe0b:a33b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1532  Metric:1
          RX packets:1804 errors:0 dropped:0 overruns:0 frame:0
          TX packets:40 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:75768 (73.9 KiB)  TX bytes:2560 (2.5 KiB)

Ага, поменялся адрес интерфейса tap0, и правила в скрипте rc.firewall стали недействительными.
Уточняю у админов системы город - поменялось оборудование у них, а ip-шники присваиваются динамически.
Что же делать, думаю? Нужно в скрипте rc.firewall вместо константы использовать выражение, которое бы возвращало ip-адрес интерфейса tap0

Чуть чуть поразмыслив, нахожу вот такое решение:

/sbin/ifconfig tap0 | grep 'inet addr:' | cut -d: -f2 | awk '{print $1}'

и добавляю соответствующую переменную в скрипт rc.firewall:

GOROD_IP=`/sbin/ifconfig tap0 | grep 'inet addr:' | cut -d: -f2 | awk '{print $1}'`

Перезапускаю скрипт:
# /etc/rc.d/rc.firewall

Проверяю правила:
# iptables-save | grep 10.221
-A POSTROUTING -s 192.168.0.0/24 -d 10.221.128.0/24 -o tap0 -j SNAT --to-source 10.221.141.98
-A INPUT -s 10.221.0.0/16 -d 10.221.141.98/32 -p tcp -m tcp --sport 3389 --dport 1024:65535 -j ACCEPT
-A FORWARD -s 192.168.0.0/24 -d 10.221.0.0/16 -p tcp -m tcp --sport 1024:65535 --dport 3389 -j ACCEPT
-A FORWARD -s 10.221.0.0/16 -d 192.168.0.0/24 -p tcp -m tcp --sport 3389 --dport 1024:65535 -j ACCEPT
-A OUTPUT -s 10.221.141.98/32 -d 10.221.0.0/16 -p tcp -m tcp --sport 1024:65535 --dport 3389 -j ACCEPT

Вижу правильный IP в последнем правиле - все в порядке, теперь можно спать спокойно...

Комментариев нет:

Отправить комментарий