Конфигурация окружения: домашняя сеть, несколько компьютеров, подключённых через свитч к провайдерскому роутеру, плюс на компах есть несколько виртуальных машин с мостовым соединением, имеющих адреса из той же подсети. На одном ноутбуке (Rocky Linux 9.2) при помощи OpenConnect поднимается VPN-подключение в некую закрытую сеть, находящуюся снаружи. Задача: обеспечить другим машинам из моей домашней сети (виндовым и линуксовым) доступ в ту же VPN-сетку, используя этот ноутбук в качестве промежуточного узла. При этом весь трафик туда маршрутизировать не надо, выход в интернет должен оставаться обычным, провайдерским.
Что я сделал:
На VPN-ноутбуке (буду называть его так) настроил правила форвардинга (enp0s31f6 — ethernet-порт, через который ноут включён в сеть, tun0 — туннель, созданный openconnect'ом):
firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -o tun0 -j MASQUERADE
firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i enp0s31f6 -o tun0 -j ACCEPT
firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i tun0 -o enp0s31f6 -m state --state RELATED,ESTABLISHED -j ACCEPT
net.ipv4.ip_forward установлен в 1.
Далее на машине, с которой хочу получить доступ (далее "машина-клиент"), добавляю новый маршрут (соответственно, для линукса и винды):
ip r add 172.20.0.0/16 via 192.168.1.115
route add 172.20.0.0 mask 255.255.0.0 192.168.1.115
(192.168.1.115 — локальный адрес VPN-ноутбука, 172.20.0.0/16 — одна из подсетей внутри VPN).
Пытаюсь с машины-клиента пропинговать один из адресов в сети 172.20.x.x, и в ответ получаю отлуп от самого VPN-ноута с сообщением "Packet filtered". Разумеется, проверил, что пинг того же адреса, выполняемый непосредственно с VPN-ноутбука, проходит успешно.
Запустил на ноутбуке Wireshark, снова сделал пинг с машины-клиента. Увидел, что на ноутбук приходит пакет от клиента с адресом назначения равным 172.20.x.x, после чего ноутбук, даже не пытаясь отправить пакет дальше в сеть, сам тут же отвечает машине-клиенту сообщением type 3 (Destination unreachable), code 13 (Communication administratively filtered).
В качестве эксперимента я на этом же ноутбуке добавил глобальные правила форвардинга всего трафика (те же три команды файерволла, но с источником и назначением, равными enp0s31f6). На машине-клиенте добавил маршрут 8.8.8.8/32 via 192.168.1.115, попробовал пропинговать 8.8.8.8 — успешно пропинговалось, и в Wireshark, запущенном на VPN-ноуте, было видно, что пакеты летят через него. То есть сначала на ноут прилетает пакет от машины-клиента с назначением 8.8.8.8, потом ноут отправляет этот же пакет на 8.8.8.8 от своего имени, получает ответ и перепосылает этот ответ обратно клиенту. Получается, форвардинг как таковой работает отлично. Но только в глобальный интернет, а не в поднятый на этой же машине VPN-туннель.
Прошу помощи с решением этой проблемы. В сетевых технологиях я, к сожалению, довольно-таки чайник, и легко мог какую-то очевидную всем админам банальность не учесть.
На всех локальных машинах у меня полный админский/рутовый доступ. К VPN-серверу управленческого доступа нет.
Решить задачу другими средствами проблематично, так как стоит жёсткое требование: VPN-подключение должно быть поднято только на этом конкретном ноутбуке.
Здравствуйте, m2user, Вы писали:
M>Что показывают
M>iptables -L
M>iptables -L -t nat
M>?
Вот вывод (добавил -v, так как без него не показываются интерфейсы):
# iptables -L -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
30729 2309K ACCEPT all -- enp0s31f6 tun0 anywhere anywhere
0 0 ACCEPT all -- tun0 enp0s31f6 anywhere anywhere state RELATED,ESTABLISHED
12 1002 ACCEPT all -- enp0s31f6 enp0s31f6 anywhere anywhere state RELATED,ESTABLISHED
4 270 ACCEPT all -- enp0s31f6 enp0s31f6 anywhere anywhere
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
# iptables -L -t nat -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 0 packets, 0 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
1184 105K MASQUERADE all -- any tun0 anywhere anywhere
533 94862 MASQUERADE all -- any enp0s31f6 anywhere anywhere
Это, разумеется, уже после добавления глобального форвардинга. До него было два правила в форвардинге (tun0<->enp0s31f6) и одно правило маскарадинга в nat (для tun0).
Здравствуйте, m2user, Вы писали:
M>Посмотрите https://bugzilla.redhat.com/show_bug.cgi?id=2020974#c4
M>M>Not by default. Due to Netfilter (kernel) hook execution order it only works if the FirewallBackend=iptables. It's also unnecessary. Modern firewalld (v0.9.0+) has native support.
M>Use the native intra-zone forwarding (--add-forward) as indicated in comment 1.
M>https://firewalld.org/2020/04/intra-zone-forwarding
Спасибо, но, к сожалению, не помогло. Активная зона у меня public, как была по умолчанию. Выполнил команду:
firewall-cmd --zone=public --add-forward
но пинги и другие пакеты так и продолжают блокироваться. Проверил командой "nft list ruleset" из того багрепорта, вижу, что в таблице filter_FWD_public_allow присутствует запись «oifname "enp0s31f6" accept». То есть, вроде бы, команда отработала корректно, но чего-то всё равно не хватает.
Добавлено:
Нашёл! tun0 не был приписан к этой зоне. Добавил вручную через --add-interface — пинги сразу пошли.