我有一个中间人设置,如下所示:
A <---> B <---> C
其中 A、B 和 C 是计算机,箭头代表以太网连接。
A 的 IP 为 10.0.0.10,C 的 IP 为 10.0.0.9
两者的网络掩码均为 255.255.255.0
我正在尝试使用没有配置 IP 的 Linux 桥接器在 B 上实现线内防火墙,如下所示:
brctl addbr br
brctl addif chlep1
brctl addif chlep2
ifconfig br 0.0.0.0 up
为了获取从 A 到 CI 的连接,请在 B 上配置 Iptables,如下所示
sysctl net.bridge.bridge-nf-call-arptables=1
sysctl net.bridge.bridge-nf-call-ip6tables=1
sysctl net.bridge.bridge-nf-call-iptables=1
iptables -t nat -I PREROUTING -p tcp -s 10.0.0.10 -d 10.0.0.9 -j REDIRECT --to-ports 40000
iptables -t nat -A PREROUTING -p tcp -s 10.0.0.10 -d 10.0.0.9 -j LOG
iptables -t filter -A INPUT -p tcp -s 10.0.0.10 -j LOG
iptables -t filter -A FORWARD -p tcp -s 10.0.0.10 -j LOG
我在 C 和 B 上都打开了一个监听套接字,就像这样
python
Python 2.7.5 (default, Aug 4 2017, 00:39:18)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM,0)
>>> sk.bind(('0.0.0.0',40000))
>>> sk.listen(1)
>>> conn, addr = sk.accept()
然后在AI上运行
python
Python 2.7.5 (default, Nov 6 2016, 00:28:07)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM,0)
>>> sk.connect(('10.0.0.9',40000))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 110] Connection timed out
>>>
检查 Iptables 中 BI 接收的规则数据包数量
[root@ace ~]# iptables -t nat -vL
Chain PREROUTING (policy ACCEPT 269 packets, 64867 bytes)
pkts bytes target prot opt in out source destination
4 240 REDIRECT tcp -- any any 10.0.0.10 10.0.0.9
redir ports 40000
0 0 LOG tcp -- any any 10.0.0.10 10.0.0.9
LOG level warning
Chain INPUT (policy ACCEPT 22 packets, 3425 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 1 packets, 76 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 2 packets, 160 bytes)
pkts bytes target prot opt in out source destination
[root@ace ~]#
[root@ace ~]#
[root@ace ~]#
[root@ace ~]#
[root@ace ~]# iptables -t filter -vL
Chain INPUT (policy ACCEPT 456 packets, 28706 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG tcp -- any any 10.0.0.10 anywhere
LOG level warning
Chain FORWARD (policy ACCEPT 8 packets, 672 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG tcp -- any any 10.0.0.10 anywhere
LOG level warning
Chain OUTPUT (policy ACCEPT 240 packets, 19382 bytes)
pkts bytes target prot opt in out source destination
dmesg 是空的。
为什么我没有劫持连接?注意:如果我使用 IP 地址配置网桥,我就可以劫持连接,这是我宁愿避免的事情
答案1
经过一些内核挖掘后发现了这一点。
实际的 iptables REDIRECTing 代码是在内核 netfilter 钩子中实现的,名为nf_nat_redirect_ipv4,在其中我们发现了这个相对简单的代码
...
/* Local packets: make them go to loopback */
if (hooknum == NF_INET_LOCAL_OUT) {
newdst = htonl(0x7F000001);
} else {
struct in_device *indev;
struct in_ifaddr *ifa;
newdst = 0;
rcu_read_lock();
indev = __in_dev_get_rcu(skb->dev);
if (indev && indev->ifa_list) {
ifa = indev->ifa_list;
newdst = ifa->ifa_local;
}
rcu_read_unlock();
if (!newdst)
return NF_DROP;
}
...
让我们把它拆开
...
if (hooknum == NF_INET_LOCAL_OUT) {
newdst = htonl(0x7F000001);
}
...
如果我们的 REDIRECT 来自 OUTPUT 链,则数据包的目标地址将更改为环回地址('127.0.0.1')
...
else {
struct in_device *indev;
struct in_ifaddr *ifa;
newdst = 0;
rcu_read_lock();
indev = __in_dev_get_rcu(skb->dev);
if (indev && indev->ifa_list) {
ifa = indev->ifa_list;
newdst = ifa->ifa_local;
}
rcu_read_unlock();
...
如果我们来自另一个链(只有 PREROUTING 因为我们已经处理了 OUTPUT)我们将数据包的目标地址设置为本地设备的地址,我们的地址将是 0
...
if (!newdst)
return NF_DROP;
}
...
零地址被视为错误值,我们的数据包不幸被丢弃:(