Ответ VPN между площадками не идёт через туннель
Ответ, обходящий туннель, — это решение о маршрутизации на дальней стороне. Проверьте таблицу хостов, селекторы и rp_filter, затем выберите маршрут или NAT.
Я потратил утро на туннель, который поднялся чисто и гнал трафик ровно в одну сторону: филиал доставал файловый сервер в головном офисе, а каждое соединение, открытое из офиса в филиал, умирало на первом SYN. SA были подняты, счётчики туннеля росли, и рукопожатие никогда не было проблемой. Ответ маршрутизировался туда, куда туннель не достаёт, и этот выбор принадлежит дальней стороне. VPN между площадками переносит только пакеты, которые хост передаёт шлюзу, и каждый хост делает этот выбор отдельно, в каждом направлении, из собственной таблицы маршрутизации.
Оба направления маршрутизируются отдельно
IP не помнит направление разговора. Каждый хост, отправляющий пакет, выполняет свой поиск самого длинного префикса, выбирает один следующий переход и забывает решение. Запрос и ответ — два несвязанных пакета, случайно принадлежащих одному соединению, а туннель — один переход, которым любой из них может воспользоваться или нет. Ничто в обмене IKE не учит удалённый сервер, как добраться до вашей подсети; переговоры лишь договариваются, какие префиксы можно шифровать.
Это соглашение — вторые ворота. В strongSwan селекторы трафика — это leftsubnet и rightsubnet, и пакет, чей источник или назначение выходит за пределы согласованной пары, не шифруется, что бы ни говорила таблица маршрутизации. Префикс, маршрутизированный в туннель, но отсутствующий в селекторах, — тихий односторонний отказ: маршрут выглядит правильным, пакет всё равно уходит открытым или отбрасывается, и только журнал charon жалуется.
Удалённый хост ничего не знает о вашем туннеле
Внутри удалённой локальной сети ответ — обычный пакет, адресованный вашему клиенту. Хост назначения не видит заголовка IPsec и не имеет причин предпочитать VPN-шлюз; он ищет ваш префикс, не находит ничего конкретнее своего маршрута по умолчанию и следует ему. Если маршрут по умолчанию указывает на основной межсетевой экран, у него либо есть маршрут обратно в туннель, либо нет. Когда нет, вы получаете тихий сброс, ICMP unreachable или ответ, который уходит через интерфейс в сторону интернета и умирает.
Второго интерфейса достаточно, чтобы это сломать, даже когда маршрут существует. NAS с каналом управления в другом VLAN, сервер с резервным uplink, правило политики, отправляющее один диапазон источников во вторую таблицу: любое из этого может перехватить ответ. В Linux ip rule show и ip route show table all показывают правила и таблицы, которые скрывает обычный список.
Прочитайте решение на машине, которая отправляет ответ
Спросите ядро, прежде чем что-то менять, и дайте ему адрес источника, потому что правила, зависящие от источника, меняют ответ.
ip route get 10.10.5.10 from 10.20.30.15
ip rule show
ip route show table all
ss -tn state established "( sport = :445 )"
Вывод называет исходящий интерфейс и следующий переход. Если интерфейс не тот, что смотрит на VPN-шлюз, вы нашли дефект, и остаётся выбрать, где должен быть маршрут. Ping со шлюза здесь доказывает мало: он отвечает адресом, который удалённый хост может разместить, а не адресом вашего ноутбука.
В Windows эквиваленты — Find-NetRoute -RemoteIPAddress 10.10.5.10 для решения и Get-NetRoute для таблицы. Маршрут, добавленный через New-NetRoute с метрикой выше стандартной, тихо проигрывает, поэтому читайте столбец метрики, а не запись. Затем подтвердите пакетами: tcpdump -ni any "host 10.10.5.10 and tcp port 445" на удалённом интерфейсе LAN показывает запрос, а тот же фильтр на стороне туннеля показывает, вернулся ли ответ. Запрос виден, ответа нет — значит ответ был маршрутизирован в другое место или отброшен; ответ на неверном интерфейсе выдаёт виновника до того, как вы тронете маршрут.
Когда шлюз сервера не является конечной точкой VPN
Многие площадки ставят межсетевой экран между серверами и концентратором. Этот экран пересылает ответ, поэтому ему нужен маршрут для префикса вашего клиента в сторону VPN-шлюза и политика пересылки в обоих направлениях. Устройства с состоянием усугубляют: запрос прошёл через экран от хоста LAN, которому он разрешил, ответ теперь приходит с другого направления, а запись отслеживания соединений больше не совпадает, поэтому пакет отбрасывается как недействительный, а не как запрещённый. Вот почему журнал политики выглядит пустым, пока трафик исчезает.
У шлюза есть собственный второй фильтр. Обратная проверка пути в Linux отбрасывает пакеты, источник которых недостижим через интерфейс, на который они пришли, и это в точности форма законного асимметричного обратного пути. руководство strongSwan по пересылке требует net.ipv4.ip_forward и ослабленный net.ipv4.conf.all.rp_filter именно поэтому. Строгое значение 1 на любом из шлюзов тихо ломает правильный маршрут, и nstat -az показывает отбрасывания, если знать, куда смотреть.
| Symptom | Where the reply is most likely lost |
|---|---|
| Gateway ping works, LAN host silent | Source address the far host cannot place in its table |
| SYN arrives, no SYN-ACK, tunnel counters flat | No route to the client prefix on the far host or its gateway |
| Reply counted on the internet-facing interface | Default route or policy rule on the far host |
| Firewall reports invalid state | Asymmetric path through a stateful device |
| Worked until a link failed over | New path is asymmetric, or rp_filter now rejects it |
Маршрутизируйте или транслируйте, затем проверьте в обоих направлениях
Два исправления не эквивалентны. Добавление маршрута сохраняет адрес клиента нетронутым, поэтому правила на основе источника, журналы аудита и приложения, записывающие вызывающего, продолжают работать; цена — каждый переход, принимающий решение, нуждается в маршруте, то есть больше мест, где можно ошибиться. Маскарадинг на удалённом шлюзе сжимает обратный путь до одного перехода, потому что ответ теперь адресован самому шлюзу, и скрывает, какой клиент что сделал.
iptables -t nat -A POSTROUTING -o eth1 -s 10.20.30.0/24 -j MASQUERADE
Выбирайте это осознанно: как только клиенты начинают выглядеть как адрес шлюза, ACL на основе источника перестают их различать, и conntrack должен удерживать соответствие, чтобы ответ записывался обратно в туннель. Если селекторы по-прежнему исключают префикс клиента, NAT ничего не меняет, потому что запрос так и не вошёл в туннель.
Прежде чем объявить это исправленным, подтвердите четыре вещи по порядку: маршрут на хосте, который отправляет ответ, маршрут на каждом переходе, который его пересылает, селекторы, покрывающие оба префикса, и запись, показывающую, что ответ входит в туннель с ожидаемым источником. Затем повторите тест с другой площадки. Прохождение одного направления — это полуоткрытый дизайн, и второе направление обычно падает по причине, отличной от той, которую вы только что исправили.