ホームサーバーでポリシールーティングを設定しようとしています。私のネットワークは次のようになります。
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 marktargetとiprulefwmarkを使用して行われます。
192.168.0.5からユーザー2000を使用して接続すると、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ルール(テーブルフィルターのすべてのポリシーは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から接続が確立されたときに、トラフィックが戻ってこないことを示す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が提案したことを実行しました:
# 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.
パケットが失われる場所を見つけるために、マングルテーブルとNATテーブルにロギングルールを追加しました。
マーキングの前後(uidに基づく)、nat postrouting(out ifaceに基づく)、mangle prerouting(in 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に到達することはありません...なぜですか?悪いルーティング?
ルーティングが対称的であることを確認するか、リバースパスフィルタリングを無効にします(ルーティングを修正することが常により良い選択であるため、何をしているのかがわかっている場合のみ)。
192.168.0.33からのトラフィックでテストを実行しましょう。
192.168.0.33-> 192.178.100.10 iif eth0
リバースパスフィルタリングは、ubuntuではデフォルトで有効になっています。送信元アドレスと宛先アドレスを反転し、これらの送信元アドレスと宛先アドレスを持つパケットがあるかのようにルートを選択しようとします。インターフェイスがパケットを受信したインターフェイスと一致しない場合、パケットはスプーフィングされたと見なされます。
したがって、カーネルは192.178.100.10-> 192.168.0.33をルーティングしようとします...テーブルmainを検索します...パケットが受信されたインターフェイスでもあるeth0を介してエントリ192.168.0.0/24を見つけます。ドロップされません。
したがって、NATそれで、VPNインターフェースで10.200.2.235-> 192.178.100.10を送信します。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 iff vpn
192.168.0.33を192.178.100.10にルーティングしてみましょう...ルックアップテーブルVPN ...デフォルトはdevvpnにある10.200.0.1を介して:PASS。
ここで、ホストから192.168.0.5またはマーク3の付いた10.200.2.235として処理を実行します。これをVPNに送信すると、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からのものではない)ため、テーブルmainになり、使用するように指示されます。インターフェイス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された後の発信パケットのみを表示し、NATが解除される前の着信パケットのみを表示するため、実際に使用されているパケットは表示されません。エキスパートソリューションとして、nflogをチェーンに入れて、そのチェーンに何が入るかをtcpdumpで調べることもできます。
VPNに送信されるすべてのものを偽装しないでください。vpn
のIPまたはサブネットからのものだけを偽装してください。自分のトラフィックを自分のトラフィックに見せかけるのは無意味に思えます。たぶん、conntrackはそれによって混乱しています。
OK、動作しました...以前に何が間違っていたのかまだわかりません。とにかく、それを機能させるために私は使用しました:
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
それが他の人にも役立つことを願っています。