iptables
背景:我已经好几年没有做过任何事情了...我在 VMWare 上的虚拟机中运行 Fedora 16,并将我的防火墙 (TomatoUSB) 端口转发到虚拟机。
虚拟机位于192.168.1.155
.我知道数据包正在发送到虚拟机......
基于这个插图要查看数据包应该如何发送,我希望数据包能够流出nat-PREROUTING
并进入mangle-INPUT
或mangle-FORWARD
除非内核由于某些其他原因而丢弃它们。
所以我打开了一些日志记录:
iptables -t mangle -v -A PREROUTING -j LOG -p tcp --destination-port 80 --log-prefix 'mangle-PREROUTING '
iptables -t nat -v -A PREROUTING -j LOG -p tcp --destination-port 80 --log-prefix 'nat-PREROUTING '
iptables -t filter -v -I INPUT 1 -j LOG -p tcp --destination-port 80 --log-prefix 'filter-INPUT '
iptables -t filter -v -I FORWARD 1 -j LOG -p tcp --destination-port 80 --log-prefix 'filter-FORWARD '
iptables -t mangle -v -I INPUT 1 -j LOG -p tcp --destination-port 80 --log-prefix 'mangle-INPUT '
iptables -t mangle -v -I FORWARD 1 -j LOG -p tcp --destination-port 80 --log-prefix 'mangle-FORWARD '
然后我用了一个外部测试服务我可以看到数据包穿过PREROUTING
链条,但随后被忽略:
Apr 23 19:11:52 webmail64 kernel: [ 351.116042] mangle-PREROUTING IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:bc:ae:c5:c3:68:f9:08:00 SRC=66.249.67.195 DST=192.168.1.155 LEN=60 TOS=0x00 PREC=0x20 TTL=48 ID=20466 DF PROTO=TCP SPT=64135 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0
Apr 23 19:11:52 webmail64 kernel: [ 351.121701] nat-PREROUTING IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:bc:ae:c5:c3:68:f9:08:00 SRC=66.249.67.195 DST=192.168.1.155 LEN=60 TOS=0x00 PREC=0x20 TTL=48 ID=20466 DF PROTO=TCP SPT=64135 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0
Apr 23 19:11:55 webmail64 kernel: [ 354.113372] mangle-PREROUTING IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:bc:ae:c5:c3:68:f9:08:00 SRC=66.249.67.195 DST=192.168.1.155 LEN=60 TOS=0x00 PREC=0x20 TTL=48 ID=20467 DF PROTO=TCP SPT=64135 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0
Apr 23 19:11:55 webmail64 kernel: [ 354.114834] nat-PREROUTING IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:bc:ae:c5:c3:68:f9:08:00 SRC=66.249.67.195 DST=192.168.1.155 LEN=60 TOS=0x00 PREC=0x20 TTL=48 ID=20467 DF PROTO=TCP SPT=64135 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0
Apr 23 19:12:01 webmail64 kernel: [ 360.109534] mangle-PREROUTING IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:bc:ae:c5:c3:68:f9:08:00 SRC=66.249.67.195 DST=192.168.1.155 LEN=60 TOS=0x00 PREC=0x20 TTL=48 ID=20468 DF PROTO=TCP SPT=64135 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0
Apr 23 19:12:01 webmail64 kernel: [ 360.111023] nat-PREROUTING IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:bc:ae:c5:c3:68:f9:08:00 SRC=66.249.67.195 DST=192.168.1.155 LEN=60 TOS=0x00 PREC=0x20 TTL=48 ID=20468 DF PROTO=TCP SPT=64135 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0
你可以看到这TTL
很好。虚拟机的 IP 是192.168.1.155
这样的,所以它应该转到INPUT
下一个,但它永远不会成功。如果数据包来自我的网络内部,则符合预期:
Apr 23 19:20:03 webmail64 kernel: [ 841.725402] mangle-PREROUTING IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:00:1f:3b:cb:2e:99:08:00 SRC=192.168.1.69 DST=192.168.1.155 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=4562 DF PROTO=TCP SPT=61520 DPT=80 WINDOW=4042 RES=0x00 ACK FIN URGP=0
Apr 23 19:20:03 webmail64 kernel: [ 841.729647] mangle-INPUT IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:00:1f:3b:cb:2e:99:08:00 SRC=192.168.1.69 DST=192.168.1.155 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=4562 DF PROTO=TCP SPT=61520 DPT=80 WINDOW=4042 RES=0x00 ACK FIN URGP=0
Apr 23 19:20:03 webmail64 kernel: [ 841.731056] filter-INPUT IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:00:1f:3b:cb:2e:99:08:00 SRC=192.168.1.69 DST=192.168.1.155 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=4562 DF PROTO=TCP SPT=61520 DPT=80 WINDOW=4042 RES=0x00 ACK FIN URGP=0
Apr 23 19:20:03 webmail64 kernel: [ 841.732784] mangle-PREROUTING IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:00:1f:3b:cb:2e:99:08:00 SRC=192.168.1.69 DST=192.168.1.155 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=4563 DF PROTO=TCP SPT=61520 DPT=80 WINDOW=4042 RES=0x00 ACK URGP=0
Apr 23 19:20:03 webmail64 kernel: [ 841.734257] mangle-INPUT IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:00:1f:3b:cb:2e:99:08:00 SRC=192.168.1.69 DST=192.168.1.155 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=4563 DF PROTO=TCP SPT=61520 DPT=80 WINDOW=4042 RES=0x00 ACK URGP=0
Apr 23 19:20:03 webmail64 kernel: [ 841.735676] filter-INPUT IN=eth1 OUT= MAC=00:0c:29:fa:36:c7:00:1f:3b:cb:2e:99:08:00 SRC=192.168.1.69 DST=192.168.1.155 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=4563 DF PROTO=TCP SPT=61520 DPT=80 WINDOW=4042 RES=0x00 ACK URGP=0
我尝试了什么?
- 关闭 SELinux
- 完全关闭
iptables
- 确保默认策略是
ACCEPT
- 看到数据包计数
ACCEPT
增加了
- 看到数据包计数
- 打开 IP 转发 (
/proc/sys/net/ipv4/ip_forward
) 以防万一
我的设置:* kernel
= Linux webmail64 3.3.2-1.fc16.x86_64 #1 SMP Sat Apr 14 00:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
*iptables v1.4.12
以下是所有iptables
重要的信息:
[root@webmail64 ~]# iptables-save
# Generated by iptables-save v1.4.12 on Mon Apr 23 20:47:24 2012
*nat
:PREROUTING ACCEPT [916:127527]
:INPUT ACCEPT [1:60]
:OUTPUT ACCEPT [87:7857]
:POSTROUTING ACCEPT [87:7857]
-A PREROUTING -p tcp -m tcp --dport 80 -j LOG --log-prefix "nat-PREROUTING "
COMMIT
# Completed on Mon Apr 23 20:47:24 2012
# Generated by iptables-save v1.4.12 on Mon Apr 23 20:47:24 2012
*mangle
:PREROUTING ACCEPT [1402:193108]
:INPUT ACCEPT [1343:189856]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [303:67789]
:POSTROUTING ACCEPT [303:67789]
-A PREROUTING -p tcp -m tcp --dport 80 -j LOG --log-prefix "mangle-PREROUTING "
-A INPUT -p tcp -m tcp --dport 80 -j LOG --log-prefix "mangle-INPUT "
-A FORWARD -p tcp -m tcp --dport 80 -j LOG --log-prefix "mangle-FORWARD "
COMMIT
# Completed on Mon Apr 23 20:47:24 2012
# Generated by iptables-save v1.4.12 on Mon Apr 23 20:47:24 2012
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1075:220262]
-A INPUT -p tcp -m tcp --dport 80 -j LOG --log-prefix "filter-INPUT "
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -p tcp -m tcp --dport 80 -j LOG --log-prefix "filter-FORWARD "
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
# Completed on Mon Apr 23 20:47:24 2012
接下来我可以去哪里看?
更新
我被要求运行tcpdump
,看起来我从未发送ACK
数据包?:
tcpdump -i eth1 -An -vvv \(net 50 or net 173\)
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
19:31:26.305048 IP (tos 0x20, ttl 53, id 26094, offset 0, flags [DF], proto TCP (6), length 60)
50.22.90.226.48891 > 192.168.1.155.http: Flags [S], cksum 0xca12 (correct), seq 2918539684, win 5840, options [mss 1460,sackOK,TS val 1152517194 ecr 0,nop,wscale 7], length 0
E .<[email protected]....................
D..J........
19:31:26.521815 IP (tos 0x20, ttl 53, id 61033, offset 0, flags [DF], proto TCP (6), length 60)
50.22.90.226.48892 > 192.168.1.155.http: Flags [S], cksum 0x82b4 (correct), seq 1826089481, win 5840, options [mss 1460,sackOK,TS val 1152517216 ecr 0,nop,wscale 7], length 0
E .<[email protected].. ...................
D..`........
19:31:29.300994 IP (tos 0x20, ttl 53, id 26095, offset 0, flags [DF], proto TCP (6), length 60)
50.22.90.226.48891 > 192.168.1.155.http: Flags [S], cksum 0xc8e6 (correct), seq 2918539684, win 5840, options [mss 1460,sackOK,TS val 1152517494 ecr 0,nop,wscale 7], length 0
E .<[email protected]....................
D..v........
19:31:29.521214 IP (tos 0x20, ttl 53, id 61034, offset 0, flags [DF], proto TCP (6), length 60)
50.22.90.226.48892 > 192.168.1.155.http: Flags [S], cksum 0x8188 (correct), seq 1826089481, win 5840, options [mss 1460,sackOK,TS val 1152517516 ecr 0,nop,wscale 7], length 0
E .<[email protected].. ...................
D...........
19:31:35.302578 IP (tos 0x20, ttl 53, id 26096, offset 0, flags [DF], proto TCP (6), length 60)
50.22.90.226.48891 > 192.168.1.155.http: Flags [S], cksum 0xc68e (correct), seq 2918539684, win 5840, options [mss 1460,sackOK,TS val 1152518094 ecr 0,nop,wscale 7], length 0
E .<[email protected]....................
D...........
19:31:35.532347 IP (tos 0x20, ttl 53, id 61035, offset 0, flags [DF], proto TCP (6), length 60)
50.22.90.226.48892 > 192.168.1.155.http: Flags [S], cksum 0x7f2f (correct), seq 1826089481, win 5840, options [mss 1460,sackOK,TS val 1152518117 ecr 0,nop,wscale 7], length 0
E .<[email protected].. ........./.........
D...........
答案1
我知道这有点晚了,但是……楼主知道它负责那个IP?这是我放在我创建的规则文件顶部的架构。您可以在其他地方找到类似的流程图,但以 ASCII 格式显示(不想称其为艺术;))在终端上可能非常有用。
大多数情况下,我心里都知道这一点,但是,嘿,如果忘记了,有一个参考也没什么坏处。
###############################################################################
###
### PACKET FLOW THROUGH NETFILTER TABLES AND CHAINS
###
###
### {Packet in}
### |
### v
### +-----------------+
### |mangle/PREROUTING|
### +-----------------+
### |
### v
### +-----------------+
### | nat/PREROUTING |
### +-----------------+
### |
### v
### *~~~~~~~~~~~~~~~~~*
### | kernel routing |
### *~~~~~~~~~~~~~~~~~*
### |
### v
### .------------{?for this host?}------------.
### yes! | | no!
### v v
### +-----------------+ +-----------------+
### | mangle/INPUT | | mangle/FORWARD |
### +-----------------+ +-----------------+
### | |
### v v
### +-----------------+ +-----------------+
### | filter/INPUT | | filter/FORWARD |
### +-----------------+ +-----------------+
### | |
### v |
### *~~~~~~~~~~~~~~~~~~~~* |
### | response & routing | |
### *~~~~~~~~~~~~~~~~~~~~* |
### | |
### v |
### +-----------------+ |
### | mangle/OUTPUT | |
### +-----------------+ |
### | |
### v |
### +-----------------+ |
### | nat/OUTPUT | |
### +-----------------+ |
### | |
### v |
### +-----------------+ |
### | filter/OUTPUT | |
### +-----------------+ |
### | |
### .-------------------+---------------------.
### |
### v
### +------------------+
### |mangle/POSTROUTING|
### +------------------+
### |
### v
### +------------------+
### | nat/POSTROUTING |
### +------------------+
### |
### v
### {Packet out}
###
###############################################################################
这是什么意思?
路由可以使用路由表(上面流程图中的“内核路由”)或使用 netfilter 进行。现在,如果 - 这是您的情况最有可能的情况 - 您没有相应地设置路由表,内核将不知道数据包必须去往何处并最终将其丢弃。顺便说一句:在这种情况下,创建一个自定义链非常有用,LOG
然后DROP
按该顺序添加规则。这样您就可以看到哪些规则受到了影响。同样有用的是iptables-save -c
将数据包和字节计数器添加到每个规则行,类似于它为链附加它的方式(格式[packets:bytes]
)。
对于通过我转发到虚拟机的端口,DNAT
我有以下配方(将在下面解释):
#!/bin/bash
VMNET=192.168.1.0/24
MAINIP=66.249.67.195
CONTIP=192.168.1.2
VMPORT=80
INPORT=80
ACTION="-I"
iptables -t nat $ACTION PREROUTING -d $MAINIP -p tcp --dport $INPORT -j DNAT --to-destination $CONTIP:$VMPORT
iptables -t nat $ACTION POSTROUTING -s $VMNET ! -d $VMNET -p tcp -j MASQUERADE --to-ports 1024-65535
iptables -t nat $ACTION POSTROUTING -s $VMNET ! -d $VMNET -p udp -j MASQUERADE --to-ports 1024-65535
iptables -t nat $ACTION POSTROUTING -s $VMNET ! -d $VMNET -j MASQUERADE
iptables -t filter $ACTION INPUT -p tcp -d $MAINIP --dport $INPORT -j ACCEPT
iptables -t filter $ACTION FORWARD -p tcp --dport $INPORT -d $VMNET -j ACCEPT
iptables -t filter $ACTION FORWARD -p tcp --dport $INPORT -d $MAINIP -j ACCEPT
请注意,您可能想要更改顺序以适应您自己的规则。另外,如果OUTPUT
链没有ACCEPT
默认策略,请确保添加输出规则,尽管出于所有实际目的,这应该通过拥有RELATED,ESTABLISHED
状态规则来满足。您还可以细化接口以进行匹配或通过通配符进行匹配。例如,我为虚拟访客的网桥提供了所有前缀_
(下划线),因此可以匹配-i _+
和-o _+
。同样,对于多个网卡 ( eth0
, eth1
),您可以将其与 相匹配-i eth+
。
所以这里发生的是:
DNAT
插入一条规则,该规则$INPORT
接受 TCP(主机)端口上的输入并将其“路由”到$CONTIP:$VMPORT
,即容器的 IP 和容器中的端口。是的,他们可能有所不同。如果他们不这样做,可以省略目标部分(即只是“$CONTIP”)。- 掩盖流量的三个规则从虚拟访客的子网但不去到另一位虚拟客人。
INPUT
允许公共 IP 上的传入数据包(未给出接口,但可能是!)端口通过的规则$INPORT
。我认为这条规则并不是严格需要的,至少如果您将其绑定到公共接口则不需要。$INPORT
将流量转发到虚拟来宾子网的规则($VMNET
)$INPORT
将流量转发到公共 IP ($MAINIP
)的规则
sysctl
最后但并非最不重要的一点是( )的值/proc/sys/net/ipv4/ip_forward
应该是:
# cat /proc/sys/net/ipv4/ip_forward
1
让你的主机成为路由器。
如果不用于echo 1
写入上面的“文件”,procfs
或者更好地使用sysctl -w net.ipv4.ip_forward=1
as root
。
答案2
我还是不知道为什么但我让它工作了。
我有两个接口,eth0
(192.168.99.x)和eth1
(192.168.1.x)。它们的存在是出于遗留原因,当我想要一个新的虚拟机并复制我以前的虚拟机时,我很懒。不管怎样,我只是禁用了eth0
,一切正常。
我检查了一些rp_filter
设置,/etc/sysctl.conf
但没有解决它(但让我认为这是一个奇怪的 IF 问题)。这些设置记录在包/usr/share/doc/kernel-doc-x.x.x/Documentation/networking/ip-sysctl.txt
中kernel-doc
。
现在它可以工作了,我将把它留在这里供搜索引擎查找,也许有一天这会对其他人有所帮助。