我正在尝试在我的主服务器上设置策略路由。 我的networking如下所示:
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的stream量应该通过VPN路由。 我想要定义一些路由策略,以便通过VPN路由一些来自192.168.0.5的stream量 – 开始 – 从具有uid 2000的用户开始。策略路由使用iptables mark target和ip rule fwmark完成。
当从192.168.0.5使用用户2000连接时,tcpdump显示传出数据包,但是没有回来。 从192.168.0.35stream量工作正常(这里我没有使用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规则(表filter中的所有策略都是ACCEPT)
# 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
从192.168.0.5用户2000连接时显示没有stream量返回的TCP转储
# 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的build议:
# 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
另外,我已经禁用vpn的rp_filter
# echo 0 > /proc/sys/net/ipv4/conf/vpn/rp_filter
现在好了 – 我正在接收SYN,ACK数据包,但握手似乎没有完成。 此外传出数据包的校验和似乎是错误的…
就像一个线索 – 这是一个双重的NAT场景 – 我正在进入VPN的NAT数据包和我的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表中,以找出丢失包的位置。
我在标记之前和之后(基于uid),在nat之后(基于iface),在mangle prerouting(基于iface)和mangle input and forward(基于恢复的标记)
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…为什么? 路由不好?
确保你的路由是对称的,或者禁用反向path过滤(只有当你知道你在做什么,因为修复你的路由总是一个更好的select)。
让我们来做testing,来自192.168.0.33的stream量:
192.168.0.33 – > 192.178.100.10 iif eth0
ubuntu中默认启用反向path过滤。 它反转源地址和目的地址,并尝试select一个路由,就好像它有一个包含这些源地址和目的地址的数据包。 如果接口与收到数据包的接口不匹配,则认为该数据包是伪造的。
因此,内核试图路由192.178.100.10 – > 192.168.0.33 …它查找表主要…通过eth0,也是接收数据包的接口find条目192.168.0.0/24,所以数据包不丢弃。
所以你在NAT接口上发送10.200.2.235 – > 192.178.100.10。 VPN程序将其封装并将其作为192.168.0.5 – > remotevpn发送。 现在你从同一个界面从你的vpn收到一个答案。 反向path过滤显然会通过这里。 VPN对结果进行解封装(192.178.100.10 – > 10.200.2.235),然后进行NAT,修改数据包以恢复原始目的地址。 然后你有一个反向path过滤进行结果数据包:
192.178.100.10 – > 192.168.0.33 iff vpn
让我们尝试路由192.168.0.33到192.178.100.10 …查找表VPN …默认通过10.200.0.1这是在开发vpn:通过。
现在你想从你的主机上做东西,如192.168.0.5或者10.200.2.235(标记3)。你把它发送到你的VPN,它从192.168.0.5发送到vpn remote。 您将以相同的方式获得答案,则VPN将解封(192.178.100.10 – > 192.168.0.5(或10.200.2.235)),然后进行反向path过滤。
192.168.0.5或10.200.2.235 – > 192.178.100.10 …不查找表VPN(它没有标记,它不是来自192.168.0.32/27),所以它最终在表main中,告诉它使用接口eth0。 反向path过滤失败,因此数据包将作为IP源欺骗尝试丢弃。 因此你没有看到结果。
至于tcpdump为什么不显示这些数据包……也许VPN端点上也存在路由问题。
至于解决scheme,在你的情况下,我会使用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
你不应该禁用反向path过滤来使这个iptables解决scheme工作。 不必要地禁用rp_filter不是解决问题的好方法,只能隐藏它们。
现在为随机虽然:
我一直在猜测你的程序使用哪个IP地址。 find一个程序,实际上打印出它使用的源IP地址。 这或告诉telnet绑定到192.168.0.35或10.200.2.235。 tcpdump只会显示传出的数据包,并且只会在传入的数据包被unNATed之前显示,因此它不会告诉您哪个数据包实际使用了。 作为一个专家级的解决scheme,你也可以尝试把nflog放在一个链中,然后用tcpdump检查那个链中的内容。
不要伪装一切发送给vpn,只有不是来自vpn的IP或子网的东西。 伪装你自己的stream量,因为你自己的stream量似乎毫无意义。 也许conntrack被这个混淆了。
好吧,它的工作…我仍然不知道我以前做错了什么。 无论如何,为了得到它的工作,我曾经使用过:
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 xxxx table VPN sysctl -w net.ipv4.conf.vpn.rp_filter=2
希望它也能帮助别人。
我认为需要澄清的是以下angular色:
请参阅Gheorghe的“devise和实现Linux防火墙和QoS ….”的第116页)
nat的INPUT链(从未在Fedora 18的手册中提到过)
和
mangle的INPUT链(根据iptables手册页,进入包本身的包)
他们与过滤表的INPUT链有什么关系?
和
mangle的FORWARD链条和filter的FORWARD链条。
两个FORWARD链条有什么区别?
(好吧,我find了一个答案,但也可以别人审核这个: http: //www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_ :Ch14:_Linux_Firewalls_Using_iptables#.UMUF0HTqOIU )