Вывод трафика через разные интерфейсы в зависимости от порта назначения


23

Мой вопрос в основном такой же, как Разрешить только определенный исходящий трафик на определенных интерфейсах .

У меня есть два интерфейса eth1(10.0.0.2) и wlan0(192.168.0.2). Мой маршрут по умолчанию для eth1. Допустим, я хочу, чтобы весь https-трафик проходил wlan0. Теперь, если я использую решение, предложенное в другом вопросе, трафик https будет проходить wlan0, но все равно будет иметь адрес источника eth1(10.0.0.2). Поскольку этот адрес не маршрутизируется для wlan0шлюза, ответы никогда не будут возвращаться. Самый простой способ - просто правильно установить bind-addr в приложении, но в этом случае это не применимо.

Я думаю, мне нужно переписать src-addr:

# first mark it so that iproute can route it through wlan0
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# now rewrite the src-addr
iptables -A POSTROUTING -t nat -o wlan0 -p tcp --dport 443 -j SNAT --to 192.168.0.2

Теперь tcpdump видит исходящие пакеты просто замечательно, и входящие пакеты прибывают для 192.168.0.2, однако они, вероятно, никогда не окажутся в приложении, потому что все, что я когда-либо получаю, это то, что приложение повторно отправляет SYN-пакет, хотя SYN- ACK уже был получен.

Вот я и подумал, может мне тоже нужно переписать входящий адрес:

iptables -A PREROUTING -t nat -i wlan0 -p tcp --sport 443 -j DNAT --to 10.0.0.2

но это тоже не сработало. Так что я застрял здесь. Какие-либо предложения?

Ответы:


24

Ты рядом.

Фактическая причина того, что приложение не видит ответный трафик, заключается в встроенной в ядре защите от IP-спуфинга. То есть обратный трафик не соответствует таблице маршрутизации и поэтому отбрасывается. Вы можете исправить это, отключив защиту от спуфинга следующим образом:

sudo sysctl net.ipv4.conf.wlan0.rp_filter=0

Но я бы не рекомендовал это. Более правильным способом является создание альтернативного экземпляра маршрутизации.

  1. Знак необходим. Оставь это.
  2. Источник NAT также необходим.
  3. Последний DNAT не нужен, поэтому вы можете удалить его.

Убедитесь, что у вас установлен iprouteпакет. Если у вас есть ipкоманда, значит, вы настроены (что похоже на то, что вы делаете, но если не получите это первым).

Отредактируйте /etc/iproute2/rt_tablesи добавьте новую таблицу, добавив следующую строку:

200 wlan-route

Затем вам необходимо настроить новую таблицу маршрутизации wlan-routeс именем по умолчанию на шлюз и создать правила для условной отправки трафика в эту таблицу. Я предполагаю, что ваш шлюз по умолчанию - 192.168.0.1. Естественно, это должно соответствовать вашей реальной сети, а не только моим предположениям.

ip route add default via 192.168.0.1 dev wlan0 table wlan-route
ip rule add fwmark 0x1 table wlan-route

Ваш последний аннотированный скрипт будет выглядеть так:

# Populate secondary routing table
ip route add default via 192.168.0.1 dev wlan0 table wlan-route
# Anything with this fwmark will use the secondary routing table
ip rule add fwmark 0x1 table wlan-route
# Mark these packets so that iproute can route it through wlan-route
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# now rewrite the src-addr
iptables -A POSTROUTING -t nat -o wlan0 -p tcp --dport 443 -j SNAT --to 192.168.0.2

Спасибо, что нашли время, чтобы разобраться в этом. Тем не менее, это уже то, что я использовал (как описано в другом вопросе), поэтому у меня настроен дополнительный маршрут, но он все тот же. SYN-ACK возвращаются к 192.168.0.2, но, очевидно, никогда не достигают приложения.
Румпель

Вернитесь и прочитайте мой ответ снова. Я обратился к этому.
Багамат

Часть о защите от спуфинга? Без изменений даже после попытки. Извините, прочитайте это назад и вперед пару раз, но еще не поняли, чего мне не хватает.
Rumpel

Вам нужно добавить srcопцию в ip routeкоманды, чтобы указать правильный адрес источника.
Дэвид Шварц

@DavidSchwartz: об POSTROUTING SNATэтом позаботятся.
Багамат

8

решение багамата правильное; однако, пожалуйста, обратите внимание, что единственный способ сделать это - отключить rp_filter для каждого интерфейса в системе, а не только для двух (в данном случае eth1 и wlan0), участвующих в NATing.

for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done
echo 1 > /proc/sys/net/ipv4/route/flush

(см. ВАЖНОЕ примечание в конце этой страницы: Advanced Routing Howto - размещенная там ссылка больше не существует, но я нашел ее через механизм обратного хода)


Спасибо за эти ответы, я тоже мог только заставить работать решение Багамских островов, учитывая ваш ответ.
Диналон

для меня на довольно стандартном Ubuntu 12.04 LTS box, в дополнение к отключению rp_filter и очистке кэша маршрутов, мне также пришлось исключить имя интерфейса из аргументов iptables. не было достаточно времени, чтобы выяснить, почему.
Костин Гуцэ

0

Одно предложение: вы должны всегда использовать --sportвместо --dportв цепочке вывода.

NAT изменяет dportи это сделает ваше правило невыполнимым.


2
Есть что-то, чего я не получаю? Dport, как и в порту назначения, не может измениться. Это порт службы, к которой пытается подключиться сеанс, например http, ssh, smtp. Либо ты перепутал спорт и dport, либо я упускаю что-то очевидное. : P
Кто-то

0

Я думаю, что ниже необходимо:

ip ru add from 192.168.0.2 table 3 prio 300
ip ro add table 3 default via 192.168.0.1 dev wlan0
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.