iproute2 и iptables. Маршрутизация по меткам.

Добрый день.

Как водится, появилась пара провайдеров, соответственно, следует раскидать трафик по интерфейсам.

Настроен iproute2:

# ip rule
0:      from all lookup local 
32756:  from 1.1.1.1 lookup s
32757:  from all fwmark 0x1e lookup s
32758:  from 2.2.2.2 lookup b
32759:  from all fwmark 0x14 lookup b
32766:  from all lookup main 
32767:  from all lookup default
# ip route list table s
ip.addr.dns.serv1 via 1.1.1.2 dev eth0 
127.0.0.0/8 via 127.0.0.1 dev lo 
default via 1.1.1.2 dev eth0
# ip route list table b
ip.addr.dns.serv2 via 2.2.2.3 dev eth2 
127.0.0.0/8 via 127.0.0.1 dev lo 
default via 2.2.2.3 dev eth2

Маршрут по умолчанию для всей системы при этом установлен через 1.1.1.2, т.е. через интерфейс eth0.

Настраиваем icmp:

$IPT -t mangle -A OUTPUT -s $EXTIP2 -p icmp -j MARK --set-mark 0x14                                                                 
$IPT -t mangle -A OUTPUT -s $EXTIP -p icmp -j MARK --set-mark 0x1e

Пробуем:

# ping -I eth0 -c 3 ya.ru 
PING ya.ru (77.88.21.8) from 1.1.1.1 eth0: 56(84) bytes of data.
64 bytes from ya.ru (77.88.21.8): icmp_seq=1 ttl=52 time=16.5 ms
64 bytes from ya.ru (77.88.21.8): icmp_seq=2 ttl=52 time=16.1 ms
64 bytes from ya.ru (77.88.21.8): icmp_seq=3 ttl=52 time=16.4 ms

--- ya.ru ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 16.181/16.381/16.557/0.186 ms
gate ~ # ping -I eth2 -c 3 ya.ru 
PING ya.ru (77.88.21.8) from 1.1.1.1 eth2: 56(84) bytes of data.
64 bytes from ya.ru (77.88.21.8): icmp_seq=1 ttl=59 time=2.46 ms
64 bytes from ya.ru (77.88.21.8): icmp_seq=2 ttl=59 time=2.49 ms
64 bytes from ya.ru (77.88.21.8): icmp_seq=3 ttl=59 time=2.42 ms

--- ya.ru ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 2.425/2.460/2.495/0.028 ms

Как видно, всё работает. Для чистоты эксперимента в таблицах временно убирались правила from ip. В общем, метки от iptables принимаются и понимаются iproute2.

Теперь, пробуем пустить исходящий трафик, скажем, от squid через интерфейс eth2. По умолчанию, как выше сказано, он бегает через eth0. Добавляем правило фаервола:

$IPT -t mangle -A OUTPUT -p tcp --dport http -j MARK --set-mark 0x14

и смотрим, куда же побежит сей трафик по логам:

Feb 18 14:28:03 gate kernel: [46051.290116] ACCEPT IN= OUT=eth0 SRC=1.1.1.1 DST=213.180.204.11 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=23141 DF PROTO=TCP SPT=45386 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0 MARK=0x14 
Feb 18 14:28:05 gate kernel: [46053.183161] ACCEPT IN= OUT=eth0 SRC=1.1.1.1 DST=87.250.251.60 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=15276 DF PROTO=TCP SPT=58717 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0 MARK=0x14

Если последить через tcpdump, то выясняется, что исходящий трафик бежит через eth2, но с адресом eth0:

# tcpdump -i eth2 -n 'tcp port 80'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth2, link-type EN10MB (Ethernet), capture size 68 bytes
15:04:37.727833 IP 1.1.1.1.58404 > 78.140.142.125.80: . ack 3246838659 win 501 <nop,nop,timestamp[|tcp]>
15:04:37.734168 IP 1.1.1.1.58404 > 78.140.142.125.80: . ack 2897 win 501 <nop,nop,timestamp[|tcp]>

, а ответы возвращаются на интерфейс eth0, как и должно следовать из данного расклада.

Вопрос: как же заставить правильно работать эту связку? Ловить пакеты и менять адрес источника, и тогда, как понимаю, метить ничего не надо будет, iproute2 уже сказано, что делать с пакетами от соответствующих источников? Иных путей для решения проблемы нет?

У сквида в настройках есть

У сквида в настройках есть параметр - tcp_outgoung_adress. Указываете здесь ip нужного интерфейса и все запросы идут от него. В этом случае маркировать пакеты не нужно.
И еще да, думаю, что у исходящих пакетов можно менять адрес источника.

squid — это пример. Таких

squid — это пример. Таких приложений может быть несколько и не у всех может быть возможность отправлять пакеты с указанного адреса.

Для почтового сервера, к примеру, вышеописанное приводит к тому, что часть писем не доставляется, т.к. IP источника не прописан в DNS, ну и тд и тп.

Рабочее решение ,трафик ходит и без iptables

#!/bin/bash
ip route flush table T1
ip route flush table T2
ip rule delete table T1
ip rule delete table T2
ip rule add from x.x.x.x table T1
ip rule add from y.y.y.y table T2

ip route add x.x.x.0/24 via x.x.x.y dev ppp0 table T1
ip route add y.y.y.0/25 via y.y.y.x dev eth2 src y.y.y.y table T1
ip route add 10.168.0.0/24 dev eth0 src 10.168.0.254 table T1
ip route add 127.0.0.0/8 dev lo table T1
ip route add default dev ppp0 table T1

ip route add y.y.y.0/25 via y.y.y.x dev eth2 table T2
ip route add x.x.x.0/24 via x.x.x.y dev ppp0 src x.x.x.x table T2
ip route add 10.168.0.0/24 dev eth0 src 10.168.0.254 table T2
ip route add 127.0.0.0/8 dev lo table T2
ip route add default via y.y.y.x dev eth2 table T2

ip route add default scope global nexthop dev ppp0 weight 1 nexthop via y.y.y.x dev eth2 weight 1
ip route flush cache

(x.x.x.x,y.y.y.y -адреса интерфеисов)
(x.x.x.0 ,y.y.y.0 -сети провайдеров)
(x.x.x.y,y.y.y.x -гейты провайдеров)

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".