1

Я хотел бы направить трафик на некоторые конкретные адреса через VPN. Достаточно просто, можно просто добавить маршрут:

ip route add <destination ip> dev tun0 scope link

Здесь возникает загвоздка: я не хочу маршрутизировать весь трафик через VPN, только некоторые. В идеале я хотел бы "сопоставить" IP-адрес (например, адрес 10.xxx), который "указывает" на реальный IP-адрес назначения, но маршрутизируется через VPN. Насколько я понимаю, это означает добавление маршрута (как выше), а затем выполнение эквивалента DNAT в цепочке POSTROUTING.

По сути, я хотел бы сделать трюк Dirty NAT в обратном порядке (т.е. на клиенте, а не на сервере).

(Я хотел бы создать простой HTTP-прокси, который направляет трафик через VPN только в том случае, если URL соответствует заданному шаблону. Конечным решением было бы повлиять на маршрутизацию данного соединения непосредственно из программы пользовательского пространства, но я думаю, что это невозможно.)


Допустим, я хотел бы направить некоторый трафик, скажем, с 8.8.8.8 через tun0 , но я все еще хочу, чтобы некоторый трафик на 8.8.8.8 проходил через eth0 . Например, изображение 8.8.8.8 несколько сайтов, и я хочу туннелировать трафик, идущий только на некоторые сайты.

Я хотел бы установить "поддельный" адрес, скажем, 10.1.2.3 . Любой трафик, направленный с моего компьютера на 10.1.2.3 , пойдет на 8.8.8.8 , но будет маршрутизироваться через tun0 вместо основной таблицы маршрутизации.

Мне частично удалось настроить: сначала я выбрал диапазон IP, скажем, 10.1.0.0/16 . Чем я помечаю пакеты в цепочке OUTPUT goind в этот диапазон, скажем, 0x40:

sudo iptables -A OUTPUT -t mangle --dst 10.1.0.0/16 -j MARK --set-mark 64

Затем я добавляю правила DNAT для сопоставления "поддельных" IP-адресов из этого диапазона с реальным назначением. Это может быть возможно автоматизировано:

sudo iptables -A OUTPUT -t nat --dst 10.1.2.3 -j DNAT --to 8.8.8.8

Основываясь на отметке, я маршрутизирую пакеты по другой таблице маршрутизации:

sudo ip rule add fwmark 64 lookup vpn
sudo ip route add default dev tun0 scope global proto static table vpn

К сожалению, я все еще не могу пинговать 10.1.2.3 . Если я удаляю правило MARK, я получаю ответ, поэтому часть DNAT работает как положено.

2 ответа2

1

Были две проблемы с моей первоначальной настройкой маршрутизации:

  1. Как указано в ответе Гейба, MARK в OUTPUT не может влиять на решение о маршрутизации, а только на решение о перенаправлении после NAT.

    Это привело к неправильному адресу источника в исходящих пакетах, поскольку адрес источника назначается решением о маршрутизации и остается одним при перенаправлении. Я наконец-то решил, что лучшее решение - справиться с этим с помощью действия MASQUERADE на основе знака:

    iptables -A POSTROUTING -t nat -m mark --mark 64 -j MASQUERADE

  2. В Linux есть обратный фильтр пакетов.

    См., Например, комментарий на https://superuser.com/a/355408/184915 о влиянии фильтра на сценарии маршрутизации, связанные с VPN.

    Если пакет с адреса источника A получен на интерфейсе I , он будет отброшен, если пакет с адресом назначения A не был бы направлен на интерфейс I Конечно, ответы от, например, 8.8.8.8 поступающего на tun0 будут отброшены, так как нормальная маршрутизация будет маршрутизировать пакеты с 8.8.8.8 по eth0 при отсутствии метки.

    Можно отключить фильтр пакетов с помощью

    echo 2 > /proc/sys/net/ipv4/conf/tun0/rp_filter

    но это считается вредным, поскольку теперь поддельные пакеты, притворяющиеся, например, из 127.0.0.1 могут попасть на машину через tun0 . Мы можем установить соответствующие правила брандмауэра, чтобы предотвратить это нарушение безопасности. Обратите внимание, что использование вышеупомянутой уязвимости потребует компрометации самого VPN-сервера (только мы отключаем rp-фильтр только для tun0 ), так что, на мой взгляд, это не очень большой риск в любом случае.

Неплохой побочный эффект этой настройки заключается в том, что tun0 никогда явно не упоминается в правилах iptables. Теперь я могу добавить любую информацию о маршрутизации в таблицу маршрутизации vpn и создать "поддельные" IP-адреса, которые ей подчиняются (хотя нужно помнить о rp-фильтре). Например, настройка одинаково полезна для VPN на основе PPTP путем изменения одной записи таблицы маршрутизации.

1

Я не уверен, что понимаю, как вы представляете себе решение на основе IP-маршрутизации, но у меня есть предложение по вашей реальной проблеме:

Я хотел бы создать простой HTTP-прокси, который маршрутизирует трафик через VPN, только если URL соответствует заданному шаблону.

Самый простой способ добиться этого - (условная) цепочка прокси. В простейшем случае, например, для squid вы должны установить родительский cache_peer и установить для cache_peer_domain значение .netflix.com или что-то еще - http://wiki.squid-cache.org/Features/CacheHierarchy - хорошая отправная точка для настройки этого; с помощью apache mod_proxy вы бы использовали директиву ProxyRemote (и, возможно, NoProxy , в зависимости от деталей вашей настройки).


Отвечая на ваш пример на основе IP: я считаю, что единственная проблема с правилом MARK заключается в том, что оно находится в неправильной цепочке; должен быть PREROUTING, а не OUTPUT. Цитата из справочной страницы iptables(1) :

MARK
   This target is used to set the Netfilter mark value associated with
   the packet.  It can, for example, be used in conjunction with rout‐
   ing based on fwmark (needs iproute2). If you plan on doing so, note
   that the mark needs to be set in the PREROUTING chain of the mangle
   table to affect routing.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .