я пытаюсь настроить маршрутизацию политики на моем домашнем сервере. Моя сеть выглядит так:
Host routed VPN gateway Internet link
through VPN
192.168.0.35/24 ---> 192.168.0.5/24 ---> 192.168.0.1 DSL router
10.200.2.235/22 .... .... 10.200.0.1 VPN server
Трафик из 192.168.0.32/27 должен маршрутизироваться через VPN. Я хотел определить некоторые политики маршрутизации для маршрутизации некоторого трафика из 192.168.0.5 через VPN - для начала - от пользователя с uid 2000. Маршрутизация политик выполняется с использованием iptables mark target и ip rule fwmark.
При подключении с использованием пользователя 2000 из 192.168.0.5 tcpdump показывает исходящие пакеты, но ничего не возвращается. Трафик с 192.168.0.35 работает нормально (здесь я использую не fwmark, а политику src).
# uname -a
Linux placebo 3.2.0-34-generic #53-Ubuntu SMP Thu Nov 15 10:49:02 UTC 2012 i686 i686 i386 GNU/Linux
# iptables -V
iptables v1.4.12
# ip -V
ip utility, iproute2-ss111117
Правила IPtables (все политики в фильтре таблицы ПРИНЯТЫ)
# iptables -t mangle -nvL
Chain PREROUTING (policy ACCEPT 770K packets, 314M bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 767K packets, 312M bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 5520 packets, 1920K bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 782K packets, 901M bytes)
pkts bytes target prot opt in out source destination
74 4707 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 owner UID match 2000 MARK set 0x3
Chain POSTROUTING (policy ACCEPT 788K packets, 903M bytes)
pkts bytes target prot opt in out source destination
# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 996 packets, 51172 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 7 packets, 432 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 1364 packets, 112K bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 2302 packets, 160K bytes)
pkts bytes target prot opt in out source destination
119 7588 MASQUERADE all -- * vpn 0.0.0.0/0 0.0.0.0/0
Маршрутизация:
# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master lan state UNKNOWN qlen 1000
link/ether 00:40:63:f9:c3:8f brd ff:ff:ff:ff:ff:ff
valid_lft forever preferred_lft forever
3: lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 00:40:63:f9:c3:8f brd ff:ff:ff:ff:ff:ff
inet 192.168.0.5/24 brd 192.168.0.255 scope global lan
inet6 fe80::240:63ff:fef9:c38f/64 scope link
valid_lft forever preferred_lft forever
4: vpn: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100
link/none
inet 10.200.2.235/22 brd 10.200.3.255 scope global vpn
# ip rule show
0: from all lookup local
32764: from all fwmark 0x3 lookup VPN
32765: from 192.168.0.32/27 lookup VPN
32766: from all lookup main
32767: from all lookup default
# ip route show table VPN
default via 10.200.0.1 dev vpn
10.200.0.0/22 dev vpn proto kernel scope link src 10.200.2.235
192.168.0.0/24 dev lan proto kernel scope link src 192.168.0.5
# ip route show
default via 192.168.0.1 dev lan metric 100
10.200.0.0/22 dev vpn proto kernel scope link src 10.200.2.235
192.168.0.0/24 dev lan proto kernel scope link src 192.168.0.5
Дамп TCP, показывающий, что трафик не возвращается при подключении от пользователя 192.168.0.5 2000
# tcpdump -i vpn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vpn, link-type RAW (Raw IP), capture size 65535 bytes
### Traffic from user 2000 on 192.168.0.5 ###
10:19:05.629985 IP 10.200.2.235.37291 > 10.100-78-194.akamai.com.http: Flags [S], seq 2868799562, win 14600, options [mss 1460,sackOK,TS val 6887764 ecr 0,nop,wscale 4], length 0
10:19:21.678001 IP 10.200.2.235.37291 > 10.100-78-194.akamai.com.http: Flags [S], seq 2868799562, win 14600, options [mss 1460,sackOK,TS val 6891776 ecr 0,nop,wscale 4], length 0
### Traffic from 192.168.0.35 ###
10:23:12.066174 IP 10.200.2.235.49247 > 10.100-78-194.akamai.com.http: Flags [S], seq 2294159276, win 65535, options [mss 1460,nop,wscale 4,nop,nop,TS val 557451322 ecr 0,sackOK,eol], length 0
10:23:12.265640 IP 10.100-78-194.akamai.com.http > 10.200.2.235.49247: Flags [S.], seq 2521908813, ack 2294159277, win 14480, options [mss 1367,sackOK,TS val 388565772 ecr 557451322,nop,wscale 1], length 0
10:23:12.276573 IP 10.200.2.235.49247 > 10.100-78-194.akamai.com.http: Flags [.], ack 1, win 8214, options [nop,nop,TS val 557451534 ecr 388565772], length 0
10:23:12.293030 IP 10.200.2.235.49247 > 10.100-78-194.akamai.com.http: Flags [P.], seq 1:480, ack 1, win 8214, options [nop,nop,TS val 557451552 ecr 388565772], length 479
10:23:12.574773 IP 10.100-78-194.akamai.com.http > 10.200.2.235.49247: Flags [.], ack 480, win 7776, options [nop,nop,TS val 388566081 ecr 557451552], length 0
Я сделал то, что предложил @BatchyX:
# iptables -t mangle -nvL
Chain PREROUTING (policy ACCEPT 3 packets, 179 bytes)
pkts bytes target prot opt in out source destination
173 15993 CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK restore
Chain INPUT (policy ACCEPT 3 packets, 179 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 1 packets, 67 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 1 packets, 60 bytes)
pkts bytes target prot opt in out source destination
83 5247 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 owner UID match 2000 MARK set 0x3
166 16053 CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK save
Chain POSTROUTING (policy ACCEPT 2 packets, 127 bytes)
pkts bytes target prot opt in out source destination
Также я отключил rp_filter для vpn
# echo 0 > /proc/sys/net/ipv4/conf/vpn/rp_filter
Сейчас лучше - я получаю пакеты SYN, ACK, но рукопожатие, похоже, не завершается. Также контрольная сумма исходящих пакетов кажется неправильной ...
В качестве подсказки - это сценарий с двойным NAT - я преобразую пакеты, входящие в VPN, и мой провайдер VPN преобразует их в NAT перед их пересылкой в мир.
# tcpdump -vvi vpn
tcpdump: listening on vpn, link-type RAW (Raw IP), capture size 65535 bytes
16:27:56.308479 IP (tos 0x10, ttl 64, id 49013, offset 0, flags [DF], proto TCP (6), length 60)
10.200.2.235.58020 > wi-in-f104.1e100.net.http: Flags [S], cksum 0xff0b (incorrect -> 0x9790), seq 3580181028, win 14600, options [mss 1460,sackOK,TS val 12420433 ecr 0,nop,wscale 4], length 0
16:27:56.488691 IP (tos 0x0, ttl 46, id 44196, offset 0, flags [none], proto TCP (6), length 60)
wi-in-f104.1e100.net.http > 10.200.2.235.58020: Flags [S.], cksum 0x12a2 (correct), seq 3226424033, ack 3580181029, win 14180, options [mss 1367,sackOK,TS val 1968045661 ecr 12420433,nop,wscale 6], length 0
16:27:56.799066 IP (tos 0x0, ttl 46, id 44197, offset 0, flags [none], proto TCP (6), length 60)
wi-in-f104.1e100.net.http > 10.200.2.235.58020: Flags [S.], cksum 0x116c (correct), seq 3226424033, ack 3580181029, win 14180, options [mss 1367,sackOK,TS val 1968045971 ecr 12420433,nop,wscale 6], length 0
Как было сказано ранее, сейчас я получаю SYN, ACK, но не могу завершить рукопожатие с пакетом ACK. Итак, если я использую telnet из учетной записи маршрутизированного пользователя, я получаю:
routed@placebo ~ # telnet 85.214.204.92 80
Trying 85.214.204.92...
telnet: Unable to connect to remote host: Connection timed out
И соответствующий tcpdump:
# tcpdump -vvi vpn
tcpdump: listening on vpn, link-type RAW (Raw IP), capture size 65535 bytes
20:33:51.940151 IP (tos 0x10, ttl 64, id 65041, offset 0, flags [DF], proto TCP (6), length 60)
10.200.2.235.60547 > korn.vibfolks.eu.http: Flags [S], cksum 0x3014 (incorrect -> 0xe817), seq 151728396, win 14600, options [mss 1460,sackOK,TS val 16109341 ecr 0,nop,wscale 4], length 0
20:33:52.142823 IP (tos 0x0, ttl 50, id 0, offset 0, flags [DF], proto TCP (6), length 60)
korn.vibfolks.eu.http > 10.200.2.235.60547: Flags [S.], cksum 0xf897 (correct), seq 986246473, ack 151728397, win 14480, options [mss 1367,sackOK,TS val 62899312 ecr 16109341,nop,wscale 6], length 0
20:33:52.937974 IP (tos 0x10, ttl 64, id 65042, offset 0, flags [DF], proto TCP (6), length 60)
10.200.2.235.60547 > korn.vibfolks.eu.http: Flags [S], cksum 0x3014 (incorrect -> 0xe71d), seq 151728396, win 14600, options [mss 1460,sackOK,TS val 16109591 ecr 0,nop,wscale 4], length 0
20:33:53.140728 IP (tos 0x0, ttl 50, id 0, offset 0, flags [DF], proto TCP (6), length 60)
korn.vibfolks.eu.http > 10.200.2.235.60547: Flags [S.], cksum 0xf79e (correct), seq 986246473, ack 151728397, win 14480, options [mss 1367,sackOK,TS val 62899561 ecr 16109341,nop,wscale 6], length 0
20:33:53.341764 IP (tos 0x0, ttl 50, id 0, offset 0, flags [DF], proto TCP (6), length 60)
korn.vibfolks.eu.http > 10.200.2.235.60547: Flags [S.], cksum 0xf76b (correct), seq 986246473, ack 151728397, win 14480, options [mss 1367,sackOK,TS val 62899612 ecr 16109341,nop,wscale 6], length 0
Но пользователь без маршрутизации подключается без проблем:
nonrouted@placebo ~ $ telnet 85.214.204.92 80
Trying 85.214.204.92...
Connected to 85.214.204.92.
Escape character is '^]'.
^]
telnet> quit
Connection closed.
Я добавил правила регистрации в таблицы mangle и nat, чтобы узнать, где теряются пакеты.
Я вхожу в mangle до и после маркировки (на основе uid), в nat postrouting (на основе out iface), в mangle prerouting (на основе iface) и в mangle input и вперед (на основе восстановленной метки)
Dec 9 01:00:55 placebo kernel: [80760.497780] [VPN mangle OUTPUT pre] IN= OUT=lan SRC=192.168.0.5 DST=85.214.204.137 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=30041 DF PROTO=TCP SPT=48700 DPT=80 SEQ=3158481901 ACK=0 WINDOW=14600 RES=0x00 SYN URGP=0 OPT (020405B40402080A0132EEB40000000001030304)
Dec 9 01:00:55 placebo kernel: [80760.497819] [VPN mangle OUTPUT post] IN= OUT=lan SRC=192.168.0.5 DST=85.214.204.137 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=30041 DF PROTO=TCP SPT=48700 DPT=80 SEQ=3158481901 ACK=0 WINDOW=14600 RES=0x00 SYN URGP=0 OPT (020405B40402080A0132EEB40000000001030304) MARK=0x3
Dec 9 01:00:55 placebo kernel: [80760.497875] [VPN nat POSTROUTING] IN= OUT=vpn SRC=192.168.0.5 DST=85.214.204.137 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=30041 DF PROTO=TCP SPT=48700 DPT=80 SEQ=3158481901 ACK=0 WINDOW=14600 RES=0x00 SYN URGP=0 OPT (020405B40402080A0132EEB40000000001030304) MARK=0x3
Dec 9 01:00:55 placebo kernel: [80760.695265] [VPN mangle PREROUTING pre] IN=vpn OUT= MAC= SRC=85.214.204.137 DST=10.200.2.235 LEN=60 TOS=0x00 PREC=0x00 TTL=50 ID=0 DF PROTO=TCP SPT=80 DPT=48700 SEQ=3597895441 ACK=3158481902 WINDOW=14480 RES=0x00 ACK SYN URGP=0 OPT (020405570402080A03FCE5720132EEB401030306)
Dec 9 01:00:55 placebo kernel: [80760.695305] [VPN mangle PREROUTING post] IN=vpn OUT= MAC= SRC=85.214.204.137 DST=10.200.2.235 LEN=60 TOS=0x00 PREC=0x00 TTL=50 ID=0 DF PROTO=TCP SPT=80 DPT=48700 SEQ=3597895441 ACK=3158481902 WINDOW=14480 RES=0x00 ACK SYN URGP=0 OPT (020405570402080A03FCE5720132EEB401030306) MARK=0x3
Conntrack показывает:
# conntrack -L --output extended | grep 85.214.204.137 | grep tcp
ipv4 2 tcp 6 59 SYN_RECV src=192.168.0.5 dst=85.214.204.137 sport=48724 dport=80 src=85.214.204.137 dst=10.200.2.235 sport=80 dport=48724 mark=3 use=1
Вывод - пакеты никогда не попадают на INPUT ... почему? плохая маршрутизация?
Убедитесь, что ваша маршрутизация является симметричной, или отключите фильтрацию обратного пути (только если вы знаете, что делаете, потому что исправление вашей маршрутизации всегда лучший выбор).
Давайте проведем тест с трафиком с 192.168.0.33:
192.168.0.33 -> 192.178.100.10 iif eth0
Фильтрация обратного пути включена по умолчанию в ubuntu. Он инвертирует адрес источника и назначения и пытается выбрать маршрут, как если бы у него был пакет с этими адресами источника и назначения. Если интерфейс не соответствует интерфейсу, на котором был получен пакет, пакет считается подделанным.
Итак, ядро пытается маршрутизировать 192.178.100.10 -> 192.168.0.33 ... оно ищет в таблице main ... находит запись 192.168.0.0/24 через eth0, который также является интерфейсом, на котором был получен пакет, поэтому пакет не сбрасывается.
так что вы NAT и отправляете 10.200.2.235 -> 192.178.100.10 на интерфейс VPN. программа VPN инкапсулирует это и отправляет это как 192.168.0.5 -> remotevpn. Теперь вы получаете ответ от своего vpn через тот же интерфейс. здесь явно будет проходить фильтрация обратного пути. VPN декапсулирует результаты (192.178.100.10 -> 10.200.2.235), затем выполняется NAT, изменяя пакет для восстановления исходного адреса назначения. Затем у вас есть фильтрация обратного пути для полученного пакета:
192.178.100.10 -> 192.168.0.33 если и впн
Давайте попробуем маршрутизировать 192.168.0.33 на 192.178.100.10 ... таблица поиска VPN ... по умолчанию через 10.200.0.1, который находится на dev vpn: PASS.
Теперь вы хотите делать что-то со своего хоста, например, 192.168.0.5 или 10.200.2.235 с отметкой 3. Вы отправляете это в свой VPN, который отправляет его с 192.168.0.5 на пульт vpn. Вы получите ответ таким же образом, тогда VPN декапсулирует (192.178.100.10 -> 192.168.0.5 (или 10.200.2.235)), затем будет выполняться фильтрация обратного пути.
192.168.0.5 или 10.200.2.235 -> 192.178.100.10 ... не выполняет поиск в таблице VPN (у него нет отметки и он не исходит из 192.168.0.32/27), поэтому он попадает в основную таблицу, которая говорит ему использовать интерфейс eth0. Фильтрация обратного пути не выполняется, поэтому пакет отбрасывается как попытка подмены IP-адреса. Таким образом, вы не видите результатов.
Что касается того, почему tcpdump не показывает эти пакеты ... может быть, проблема с маршрутизацией и на конечной точке VPN.
Что касается решения, в вашем случае я бы использовал метку подключения conntrack и установил метку входящего пакета на метку подключения conntrack:
# keep that rule
OUTPUT -m owner .... -j MARK 0x3
# add this one after the previous one: it saves the current mark into connmark
OUTPUT -j CONNMARK --save-mark
# and add this one (in mangle), which sets the mark to the connmark
# if conntrack determines that it is from the same connection.
PREROUTING -j CONNMARK --restore-mark
Вам не нужно отключать фильтрацию обратного пути, чтобы это решение iptables работало. отключение rp_filter без необходимости не является хорошим способом решения проблем, оно только скрывает их.
Теперь о случайных мыслях:
Я все время гадаю, какой IP-адрес используется вашими программами. Найдите программу, которая действительно распечатывает, какой исходный IP-адрес она использует. Это или указание telnet привязаться к 192.168.0.35 или 10.200.2.235. tcpdump будет показывать исходящий пакет только после того, как он будет преобразован в NAT, и будет отображать только входящий пакет до того, как они будут отменены, поэтому он не сообщает вам, какой из них фактически используется. В качестве экспертного решения вы также можете попробовать поместить nflog в цепочку и проверить с помощью tcpdump, что входит в эту цепочку.
Не маскируйте все, что идет к vpn, только то, что не исходит от vpn
IP или подсеть. Маскировать собственный трафик под собственный трафик кажется бессмысленным. Может быть, это смущает Коннтрака.
Хорошо, все заработало ... Я до сих пор не знаю, что я делал раньше не так. В любом случае, чтобы заставить его работать, я использовал:
iptables -t mangle -A OUTPUT -m owner --uid-owner 2000 -j MARK --set-mark 3
iptables -t nat -A POSTROUTING -o vpn -j MASQUERADE
ip rule add fwmark 3 lookup VPN
ip route add default via x.x.x.x table VPN
sysctl -w net.ipv4.conf.vpn.rp_filter=2
Надеюсь, это поможет и другим.
Я думаю, что необходимо прояснить роли:
см. стр. 116 книги Георга «Проектирование и реализация межсетевых экранов Linux и QoS…»)
Цепочка INPUT nat: (никогда не упоминается на странице руководства Fedora 18)
и
цепочка INPUT mangle: (для пакетов, поступающих в сам ящик, согласно странице руководства iptables)
каковы их отношения с таблица фильтров ВВОД цепь ?
и
цепочка FORWARD mangle и цепочка FORWARD фильтра.
В чем разница между двумя цепями FORWARD?
(Хорошо, я нашел ответ, но может ли кто-нибудь еще проверить это: http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:Ch14: _Linux_Firewalls_Using_iptables # .UMUF0HTqOIU)