Локальные клиенты Wi-Fi и Ethernet подключаются к точке доступа Pi, получают адрес из её диапазона DHCP и загружают интернет-страницы без жалоб. Затем те же клиенты упираются в тайм-аут, когда открывают общий файл или веб-интерфейс в домашней LAN, хотя сам Pi достигает эту LAN через туннель. В беспроводном уровне ничего не сломано. Не хватает маршрутизируемого договора: префикс точки доступа нужно перенести в интерфейс TUN, и что-то на домашней стороне должно знать, как отправлять ответы обратно. Обе половины должны существовать, прежде чем один пакет сможет завершить путь туда и обратно.

Три подключения с тремя разными задачами

Мост Ethernet в Linux пересылает кадры по MAC-адресу назначения. OpenVPN в режиме TUN несёт IP-пакеты и вообще не имеет уровня MAC, поэтому добавление локального моста никогда не регистрирует туннель как порт. документация ядра по TUN/TAP объясняет это разделение: устройство TAP выглядит как интерфейс Ethernet, устройство TUN — нет. Проект, который соединяет два локальных порта, а затем маршрутизирует, является маршрутизатором, что бы ни говорили имена интерфейсов.

Это различие решает вопрос владения. Подсеть клиентов, их шлюз по умолчанию и полномочия DHCP для этого диапазона принадлежат локальному плану Pi. Домашние широковещательные рассылки DHCP не пересекают маршрутизируемый туннель, и никакая настройка моста этого не меняет; направлять клиентов на домашний DHCP-сервер — это отдельный, намеренный проект ретрансляции со своими режимами отказа.

Держите модем тоже вне моста клиентов. Подключение PPP — не устройство Ethernet с другой этикеткой, а документированная логика маршрута по умолчанию в pppd работает после переговоров IPCP и отзывает свой маршрут, когда это соединение падает. Копирование шаблона DHCP и переименование каждого usb0 в ppp0 ничего не доказывает о шлюзе, метрике или жизненном цикле.

Выберите префиксы, прежде чем редактировать любую конфигурацию

Перекрывающиеся префиксы тратят больше вечеров, чем правила брандмауэра, потому что перекрытие отправляет поиск маршрута на неверный интерфейс даже при здоровом туннеле. Начните с перечня того, что уже есть на Pi, а затем читайте результат как четыре отдельных пула.

ip -4 addr show scope global
ip -4 route show table main
ip -4 route get 192.168.77.10

Первый пул — адрес underlay, который оператор выдал модему; он должен оставаться вне любого плана, обращённого к клиентам. Второй — подсеть туннеля, выбранная сервером, часто его собственная частная /24-сеть. Третий — мост точки доступа, а четвёртый — домашний префикс, которого вы хотите достичь. В этом проходе точка доступа получает 172.28.90.0/24 с мостом на 172.28.90.1, а домашняя сервисная LAN сохраняет 192.168.77.0/24, что обходит стандартные 192.168.1.0/24 и 10.0.0.0/24, поставляемые потребительскими роутерами, и диапазон оператора 100.64.0.0/10.

В диапазоне DHCP точки доступа объявляйте шлюзом только адрес моста и ничего больше. Никогда не выдавайте клиентам точки доступа домашний адрес в качестве шлюза; у них нет пути на канальном уровне к этому сегменту.

Маршрутизируйте каждое направление на той стороне, которая им владеет

Pi нужен маршрут к домашнему префиксу через туннель. Серверы в серверном режиме обычно проталкивают этот маршрут, поэтому сначала убедитесь, что пересылка включена и ядро разрешает домашний адрес из tun0.

sysctl net.ipv4.ip_forward
ip route add 192.168.77.0/24 dev tun0
ip -4 route get 192.168.77.10

Если ip route get всё ещё сообщает интерфейс underlay, остановитесь там; ничто дальше по пути не исправит неверный поиск.

У домашних устройств нет маршрута к 172.28.90.0/24, поэтому их ответы идут через шлюз по умолчанию и умирают на роутере. Есть два поддерживаемых исправления. Либо добавьте статический маршрут на домашнем роутере, который направляет префикс точки доступа на LAN-адрес VPN-сервера, либо, когда сервер сам является шлюзом, зарегистрируйте префикс клиента в собственной таблице маршрутизации сервера. В многоклиентском режиме OpenVPN каталог, специфичный для клиента, несёт эту связь: файл, названный по общему имени сертификата клиента, содержащий iroute 172.28.90.0 255.255.255.0 плюс соответствующую строку route, которая устанавливает его в ядре сервера. Угаданный маршрут ядра на сервере — не то же утверждение, что сообщить серверу, какой клиент владеет префиксом.

Не переносите службу DHCP домашней сети на VPN-сервер, чтобы это работало. Замена шлюза по умолчанию для целого дома — гораздо большее изменение, чем добавление одного частного обратного маршрута, и она втягивает DNS, резервирования адресов и каждое устройство, игнорирующее новую аренду, в отказ.

Откройте пересылку, не гадая о брандмауэре

Включённая пересылка не означает, что пакету разрешено пройти. Трафик от моста к туннелю всё ещё упирается в правила фильтрации, и политика пересылки по умолчанию drop отбрасывает трафик точки доступа, пока собственный трафик Pi продолжает работать, что даёт ровно тот расщеплённый симптом выше.

iptables -S FORWARD
iptables -t nat -S POSTROUTING
nft list ruleset

Ищите правило разрешения от br0 к tun0 и соответствующим направлением ответа, а также правило postrouting, которое может переписать источник. Если политика цепочки — drop и ни одно правило не подходит, добавьте узкие разрешения и повторите тест, вместо того чтобы переворачивать политику в accept.

Трансляция — это выбор политики, а не требование. Source NAT в сторону домашней LAN заставляет каждого клиента точки доступа выглядеть как туннельный адрес Pi, что теряет привязку по клиентам в домашних журналах и ломает службы, ожидающие исходный источник. Маршрутизация без NAT сохраняет адреса клиентов видимыми, но зависит от обратного маршрута выше. Выберите одно и обращайтесь с DNS и IPv6 так же, потому что работающий путь IPv4 рядом со сломанным путём IPv6 всё ещё читается в браузере как наполовину сломанный.

Проверьте путь туда и обратно, затем намеренно сломайте его

Тестируйте с клиента точки доступа, никогда с Pi, потому что собственный трафик Pi обходит и прямой, и обратный путь. Наблюдайте оба интерфейса, пока один клиент пытается достичь домашней службы.

tcpdump -ni br0 host 192.168.77.10
tcpdump -ni tun0 host 192.168.77.10
ping -c 3 192.168.77.10

Читайте оба захвата вместе. Запросы на br0, которые никогда не появляются на tun0, означают, что Pi не пересылает или маршрут указывает в другое место. Запросы на tun0 без ответов означают, что на домашней стороне нет обратного маршрута или сервер отфильтровал пакет. Ответы на tun0, которые никогда не появляются снова на br0, означают, что обратное правило фильтрации отсутствует, когда туннель выглядит идеально, а клиент всё равно ничего не видит.

Затем намеренно сломайте путь. Опустите модемное соединение и снова поднимите его и повторно выполните проверки маршрута и захвата; маршрут, который переживает туннель, но исчезает при переподключении, относится к профилю соединения, а не к разовой команде. Убедитесь, что транспорт туннеля по-прежнему выходит через underlay, а не через себя, классическая петля, когда протолкнутый маршрут по умолчанию принимается без маршрута к хосту-партнёру.

Принимайте проект только тогда, когда клиент точки доступа может разрешить домашнее имя, открыть службу TCP и удержать сеанс живым через одно переподключение модема. Если приложению действительно нужно обнаружение на уровне Ethernet в домашнем сегменте, выберите поддерживаемый проект Layer 2, вместо того чтобы описывать локальный мост как сведённый в мост и ждать появления широковещания.

Похожие статьи