OpenVPN - как запретить устанавливать маршрут через WAN? [РЕШЕНО]
Имеются три офиса. В каждом настроен роутер на Gentoo: a-router, b-router и c-router. A-router - OpenVPN-сервер. B-router и c-router - его клиенты. Связь установлена, маршрутизация настроена, пинги идут, компьютеры друг друга видят.
На виндовых машинах в каждой из сетей запускаем пинги соседних сетей. Точнее, Windows-машин из соседних сетей. Опускаем внешний интерфейс у VPN-сервера, имитируя сбой связи у провайдера. Ждём таймаут клиентов (2 минуты). Переподключение, неудача, tun0-интерфейсы VPN-клиентов исчезают и не создаются, пока VPN-сервер не станет доступен.
Из всех сетей проброшен маскарадинг в интернет. Поднимается VPN-канал, роутеры друг друга снова видят. У виндовых машин связь не восстанавливается лишь по тем адресам, которые пинговались. Смотрим tcpdunm-ом tun0 и видим, что в момент, пока tun0 пропадал, установились сеансы связи для этих машин через внешний шлюз, который естественно ничего не видит. Помогает только сброс соединений.
Пробовал запретить доступ ко внешнему интерфейсу при адресации внутренних адресов подсетей. Без толку...
Конфигурация не боевая. Она тестируется на виртуальных машинах.
Скрипт конфигурации роутера на VPN-сервере:
#!/bin/sh WAN="eth0" LAN="eth1" VPN="tun0" LO="lo" DNS_S="192.168.0.1" IPTABLES="iptables" $IPTABLES -F $IPTABLES -t nat -F $IPTABLES -P INPUT ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -P FORWARD DROP $IPTABLES -I INPUT 1 -i ${LAN} -j ACCEPT $IPTABLES -I INPUT 1 -i ${LO} -j ACCEPT $IPTABLES -A INPUT -p UDP --dport bootps -i !${LAN} -j REJECT $IPTABLES -A INPUT -p UDP --dport domain -i !${LAN} -j REJECT $IPTABLES -A INPUT -p TCP --dport ssh -i ${WAN} -j ACCEPT $IPTABLES -A INPUT -p TCP --dport 1194 -i ${WAN} -j ACCEPT $IPTABLES -A INPUT -p TCP -i !${LAN} -d 0/0 --dport 0:1023 -j DROP $IPTABLES -A INPUT -p UDP -i !${LAN} -d 0/0 --dport 0:1023 -j DROP $IPTABLES -I FORWARD -i ${LAN} -d 192.168.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${LAN} -s 192.168.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${WAN} -d 192.168.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A INPUT -i ${WAN} -m state --state NEW -d 192.168.2.0/255.255.255.0 -j DROP $IPTABLES -A INPUT -i ${WAN} -m state --state NEW -d 192.168.3.0/255.255.255.0 -j DROP $IPTABLES -A INPUT -i ${WAN} -m state --state NEW -d 192.168.4.0/255.255.255.0 -j DROP $IPTABLES -A FORWARD -i ${WAN} -d 192.168.2.0/255.255.0.0 -j DROP $IPTABLES -A FORWARD -i ${WAN} -d 192.168.3.0/255.255.0.0 -j DROP $IPTABLES -A FORWARD -i ${WAN} -d 192.168.4.0/255.255.0.0 -j DROP $IPTABLES -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE $IPTABLES -t nat -A PREROUTING -i ${LAN} -p udp --dport 53 -j DNAT --to-destination ${DNS_S} $IPTABLES -A FORWARD -i ${LAN} -d 10.10.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${LAN} -d 192.168.3.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${LAN} -s 192.168.3.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -d 10.10.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -s 192.168.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -s 10.10.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -d 192.168.3.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -s 192.168.3.0/255.255.0.0 -j ACCEPT $IPTABLES -t nat -A POSTROUTING -o ${VPN} -j MASQUERADE $IPTABLES -t nat -A POSTROUTING -o ${LAN} -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done /etc/init.d/iptables save
Вывод ROUTE:
Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 10.10.0.2 * 255.255.255.255 UH 0 0 0 tun0 192.168.4.0 10.10.0.2 255.255.255.0 UG 0 0 0 tun0 192.168.3.0 10.10.0.2 255.255.255.0 UG 0 0 0 tun0 192.168.2.0 * 255.255.255.0 U 0 0 0 eth1 10.10.0.0 10.10.0.2 255.255.255.0 UG 0 0 0 tun0 192.168.0.0 * 255.255.255.0 U 0 0 0 eth0 loopback a-router 255.0.0.0 UG 0 0 0 lo default primary.mshome. 0.0.0.0 UG 2 0 0 eth0
Настройки одного из клиентов (b-router) - они идентичны, только адреса немного разные:
#!/bin/sh WAN="eth0" LAN="eth1" VPN="tun0" LO="lo" DNS_S="192.168.0.1" IPTABLES="iptables" $IPTABLES -F $IPTABLES -t nat -F $IPTABLES -P INPUT ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -P FORWARD DROP $IPTABLES -I INPUT 1 -i ${LAN} -j ACCEPT $IPTABLES -I INPUT 1 -i ${LO} -j ACCEPT $IPTABLES -A INPUT -p UDP --dport bootps -i !${LAN} -j REJECT $IPTABLES -A INPUT -p UDP --dport domain -i !${LAN} -j REJECT $IPTABLES -A INPUT -p TCP --dport ssh -i ${WAN} -j ACCEPT $IPTABLES -A INPUT -p TCP -i !${LAN} -d 0/0 --dport 0:1023 -j DROP $IPTABLES -A INPUT -p UDP -i !${LAN} -d 0/0 --dport 0:1023 -j DROP $IPTABLES -I FORWARD -i ${LAN} -d 192.168.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${LAN} -s 192.168.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${WAN} -d 192.168.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A INPUT -i ${WAN} -m state --state NEW -d 192.168.2.0/255.255.255.0 -j DROP $IPTABLES -A INPUT -i ${WAN} -m state --state NEW -d 192.168.3.0/255.255.255.0 -j DROP $IPTABLES -A INPUT -i ${WAN} -m state --state NEW -d 192.168.4.0/255.255.255.0 -j DROP $IPTABLES -A FORWARD -i ${LAN} -d 192.168.2.0/255.255.255.0 -j DROP $IPTABLES -A FORWARD -i ${LAN} -d 192.168.3.0/255.255.255.0 -j DROP $IPTABLES -A FORWARD -i ${LAN} -d 192.168.4.0/255.255.255.0 -j DROP $IPTABLES -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE $IPTABLES -t nat -A PREROUTING -i ${LAN} -p udp --dport 53 -j DNAT --to-destination ${DNS_S} $IPTABLES -A FORWARD -i ${LAN} -d 10.10.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${LAN} -d 192.168.2.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${LAN} -s 192.168.2.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -d 10.10.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -s 192.168.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -s 10.10.0.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -d 192.168.2.0/255.255.0.0 -j ACCEPT $IPTABLES -A FORWARD -i ${VPN} -s 192.168.2.0/255.255.0.0 -j ACCEPT $IPTABLES -t nat -A POSTROUTING -o ${VPN} -j MASQUERADE $IPTABLES -t nat -A POSTROUTING -o ${LAN} -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done /etc/init.d/iptables save
Вывод ROUTE:
Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 10.10.0.102 * 255.255.255.255 UH 0 0 0 tun0 192.168.4.0 10.10.0.102 255.255.255.0 UG 0 0 0 tun0 192.168.3.0 * 255.255.255.0 U 0 0 0 eth1 192.168.2.0 10.10.0.102 255.255.255.0 UG 0 0 0 tun0 10.10.0.0 10.10.0.102 255.255.255.0 UG 0 0 0 tun0 192.168.0.0 * 255.255.255.0 U 0 0 0 eth0 loopback b-router 255.0.0.0 UG 0 0 0 lo default primary.mshome. 0.0.0.0 UG 2 0 0 eth0
Пингуем с Win-машины за b-router Win-машну за a-router. Всё отлично. До сброса VPN-соединения tcpdump говорит это:
b-router ~ # tcpdump -i tun0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on tun0, link-type RAW (Raw IP), capture size 96 bytes 14:48:57.895594 IP 10.10.0.101 > 192.168.2.20: ICMP echo request, id 512, seq 8720, length 40 14:48:57.898325 IP 192.168.2.20 > 10.10.0.101: ICMP echo reply, id 512, seq 8720, length 40 14:48:58.891731 IP 10.10.0.101 > 192.168.2.20: ICMP echo request, id 512, seq 8976, length 40 14:48:58.892915 IP 192.168.2.20 > 10.10.0.101: ICMP echo reply, id 512, seq 8976, length 40 14:48:59.891758 IP 10.10.0.101 > 192.168.2.20: ICMP echo request, id 512, seq 9232, length 40 14:48:59.893630 IP 192.168.2.20 > 10.10.0.101: ICMP echo reply, id 512, seq 9232, length 40 14:49:00.890872 IP 10.10.0.101 > 192.168.2.20: ICMP echo request, id 512, seq 9488, length 40 14:49:00.892168 IP 192.168.2.20 > 10.10.0.101: ICMP echo reply, id 512, seq 9488, length 40 ^C 8 packets captured 8 packets received by filter 0 packets dropped by kernel
Сбрасываем VPN. Пинг не прерываем. На Win-машине - "Превышен интервал ожидания запроса". Tcpdump говорит это:
b-router ~ # tcpdump -i tun0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on tun0, link-type RAW (Raw IP), capture size 96 bytes 14:51:06.674133 IP 192.168.0.3 > 192.168.2.20: ICMP echo request, id 512, seq 10512, length 40 14:51:12.173307 IP 192.168.0.3 > 192.168.2.20: ICMP echo request, id 512, seq 10768, length 40 14:51:17.674637 IP 192.168.0.3 > 192.168.2.20: ICMP echo request, id 512, seq 11024, length 40 14:51:23.173849 IP 192.168.0.3 > 192.168.2.20: ICMP echo request, id 512, seq 11280, length 40 ^C 4 packets captured 4 packets received by filter 0 packets dropped by kernel
Собственно вопрос: как такое своеволие грамотно пресечь?
- Для комментирования войдите или зарегистрируйтесь
Можете пояснить следующее? :
Можете пояснить следующее? :
Т.е. прописывается какой-то другой маршрут для Win машин?
Какие сеансы вы имеете ввиду?
Да, и еще, насчет правил, может это у вас опечатка:
Дело в том, что в этом случае правила вида 192.168.3.0/255.255.0.0 будут аналогичны правилам вида 192.168.0.0/255.255.0.0 т.е. всю сеть (16 бит) охватит, а не 24 бита. Но к вашей проблеме это отношения не имеет.
Справедливость восторжествует.
Сбрасываем VPN. Пинг не
это не баг, это фича. Может я чего не понял ?
Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)
mr Fog написал(а): Можете
Если на вин-машине в сети B пинговалась вин-машина из сети A, то в течение долгого времени все запросы по этому IP будут проходить через внешний интерфейс, а не через VPN-интерфейс.
Сеанс связи TCP. Т.е. сессия, когда при отправке первых пакетов устанавливается канал связи для отправки всех последующих.
В любом случае благодарю) Вы помогли навести порядок со скриптами роутинга. Сам этой ошибки не заметил, а копи-паст сделал грязное дело.
Однако, названная проблема никуда не делась. Она свойственна всем трём компам. Точнее, трём случаям. Если в момент разрыва VPN-канала работа PING не прерывалась, то после возобновления связи машины пытаются достучаться друг к другу через WAN-интерфейс, что запрещено.
Это - как следствие того, что маршрут устанавливается через другой шлюз. Это действие мне и надо как-то пресечь.
Выложу изменённые скрипты:
a-router:
b-router:
c-router:
сверху многа буков - не
сверху многа буков - не осилил
По теме - для изменения таблицы роутинга - man RIPv2, man ospf, i.e man quagga
Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)
?
Ну а если рутер "А" соделать мостом+
net-firewall/ebtables
?Об этом решении тоже думал. В
Об этом решении тоже думал. В случае использования моста, с помощью bridge-utils поднять какой-нибудь br0, который не будет никуда исчезать, а уже на него понавешать прав ebtables. Про последнего до сего момента не знал.
Всё происходит по той причине, что когда убивается tun0, вместе с ним пропадают соответствующие записи в таблице роутинга. Это делает OpenVPN-сервер. В общем, и правильно делает.
В целом, проблема не настолько страшна. Любое обращение по другому порту после восстановления VPN-связи сразу начинает транслироваться через VPN-шлюз. А в случае с тем же PING можно его остановить, подождать минут пять, да снова запустить - всё будет нормально, т.к. TCP-сессия уже иссякнет. Но сотрудники - люди нервные. Им не объяснишь, что от многократных попыток связаться заново, они только оттягивают восстановление связи. Поэтому и хочу как-то избежать такой картины.
Кстати, пробовал при помощи tcpkill убивать сессию, но не выло - ноль реакции. Сама сессия устанавливается на сервере, т.к. tcpdump -i eth1 (LAN) говорит, что адресат не 192.168.0.2, а сразу конечный 192.168.3.20. Т.е. винда использует только локальный шлюз и никакой другой.
В общем, попробую создать мост. И ещё: похоже, я уже стал забывать логику работы ipfilter.
Решение проблемы
Грамотная настройка NetFilter с помощью IPTABLES проблему не решила.
Поступил другим не самым красивым, но действенным способом:
Сетевой интерфейс у OpenVPN-сервера при падении сети
не исчезает, т.к. сервер на это не обращает внимания.
Для клиентов же всё иначе. Как только пропадает сеть,
клиент отсчитывает таймаут по параметру keepalive до
перезапуска соединения. Если сервер всё ещё не доступен,
то повторная попытка завершается неудачей, и VPN-интерфейс
не создаётся.
На время, пока у клиента не поднимается VPN-канал, я
переназначаю маршруты к удалённым подсетям на интерфейс
lo (loopback). Делаю это через исполняемые VPN-сервисом
скрипты up.sh и down.sh. В случае Gentoo эти скрипты уже
существуют, а пользователю предлагается создавать скрипт
в каталоге /etc/openvpn формата [имя сервиса]-up.sh и
[имя сервиса]-down.sh . В скрипте down явным образом
замыкаю маршруты подсетей на lo, а в скрипте up удаляю
эти правила из таблицы роутинга, т.к. OpenVPN вместо них
добавляет свои правила, замкнутые на VPN-интерфейс.
Может это и покажется кривым решением, но всё же оно работает.
Благодарю всех отписавшихся за упоминания иных интересных
и полезных, но, к сожалению, не в этом случае, средств.