使用 iptables 标记数据包以进行源 ip 路由

使用 iptables 标记数据包以进行源 ip 路由

我有一台linux机器,我用它作为网关和防火墙。

Linux 机器(网关/防火墙)连接到允许互联网连接的设备(路由器聚合器),它有 2 个 IP 地址172.16.61.1172.16.62.254.

                                    +---------+    +-----------------+       /
                                    |         |    |     Router      |      /
                                    |   GW    |    |   Aggregator    |     /     
                                    |         |    |                 |    /
                 +------------------| Firewall+----+-> 172.16.61.1   +---/
                 |                  |         |    |                 |   |
                 |                  |         +----+-> 172.16.62.254 |   |
        __       |                  |         |    |                 |   |
    ___/  \_     |                  +---------+    +-----------------+   |
  _/        \__  |                                                       |
 /             \ |                                                       |Internet
| Local network  |                                                       |
| 192.168.1.0/24 +                                                       |
| 192.168.3.0/24 |                                                       |
\_           __/                                                         \
   \__     __/                                                            \
      \___/                                                                
        

路由器聚合器充当允许访问互联网的网关,但它有一个特点:如果通过IP 172.16.62.254访问,则保证1Gb/s的带宽,如果通过地址172.16.61.1访问,则带宽受到限制至 300Mb/s。

要访问路由器聚合器通过ip 172.16.61.1访问,源ip必须属于网络172.16.61.0,而通过ip 172.16.62.254访问,源ip必须为172.16.62.100。为此,网关/防火墙必须对来自本地网络的源 IP 地址执行转换。

Linux机器的IP地址是:

$ 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: eth3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:14:5e:08:49:06 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.150/24 brd 192.168.1.255 scope global eth3
    inet 192.168.168.1/24 brd 192.168.168.255 scope global eth3:0
    inet 192.168.8.1/24 brd 192.168.8.255 scope global eth3:2
    inet6 fe80::214:5eff:fe08:4906/64 scope link 
       valid_lft forever preferred_lft forever
3: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether 00:13:49:24:41:6a brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.1/24 brd 192.168.3.255 scope global eth5
    inet6 fe80::213:49ff:fe24:416a/64 scope link 
       valid_lft forever preferred_lft forever
4: eth4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether 00:13:49:24:3e:e0 brd ff:ff:ff:ff:ff:ff
    inet 172.16.61.2/24 brd 172.16.61.255 scope global eth4
    inet 172.16.62.100/24 brd 172.16.62.255 scope global eth4:1
    inet 172.16.61.3/24 brd 172.16.61.255 scope global secondary eth4:2
    inet 172.16.61.4/24 brd 172.16.61.255 scope global secondary eth4:3
    inet 172.16.61.5/24 brd 172.16.61.255 scope global secondary eth4:4
    inet 172.16.61.6/24 brd 172.16.61.255 scope global secondary eth4:5
    inet 172.16.61.7/24 brd 172.16.61.255 scope global secondary eth4:6
     inet6 fe80::213:49ff:fe24:3ee0/64 scope link 
      valid_lft forever preferred_lft forever
5: sit0: <NOARP> mtu 1480 qdisc noop state DOWN 
    link/sit 0.0.0.0 brd 0.0.0.0

当一个数据包作为源地址转换为网络时172.16.61.0/24必须使用172.16.61.1作为网关,当一个数据包作为源地址转换为ip时172.16.62.100必须使用172.16.62.254作为网关。

仅参考网络172.16.61.0/24,地址转换由 iptables 使用以下命令完成:

iptables -t nat -A POSTROUTING  -s 192.168.1.0/24 -j SNAT --to-source 172.16.61.2
iptables -A OUTPUT -s 172.16.61.2 -j ACCEPT 

为了路由数据包,172.16.61.1我尝试使用以下方法标记它们:

iptables -A OUTPUT -t mangle -s 172.16.61.2 -j MARK --set-mark 2
iptables -A POSTROUTING -t mangle -s 192.168.1.0/255.255.255.0 -j MARK --set-mark 2

然后我使用 iproute2 来路由数据包,配置如下:

$ cat /etc/iproute2/rt_tables
#
# reserved values
#
255     local
254     main
253     default
0       unspec
#
# local
#
1       route61
2       route62

$ ip route show table route61
172.16.61.0/24 via 172.16.61.1 dev eth4 
default via 172.16.61.1 dev eth4 

$ ip rule show
0:      from all lookup local 
32764:  from all fwmark 0x2 lookup route61 
32765:  from 172.16.61.0/24 lookup route61 
32766:  from all lookup main 
32767:  from all lookup default 

但如果我尝试的话,这是行不通的

$ nc -v 216.58.205.78 443

我有

nc: connect to 216.58.205.78 port 443 (tcp) failed: Network is unreachable

我做错了什么?

更新:

我尝试了什么AB在 url 的帖子中建议 路由策略数据库未检测到标记的数据包

我添加了以下行

iptables -t mangle -I OUTPUT -m connmark ! --mark 0 -j CONNMARK --restore-mark
iptables -A OUTPUT -t mangle -s 172.16.61.2 -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j CONNMARK --save-mark

mangle 表原来是

$ iptables -t mangle -L  -v -n --line-numbers
Chain PREROUTING (policy ACCEPT 31455 packets, 11M bytes)
num   pkts bytes target     prot opt in     out     source               destination    
1        1    98 CONNMARK   all  --  *      *       0.0.0.0/0            0.0.0.0/0           MARK match !0x0 CONNMARK save  

Chain INPUT (policy ACCEPT 2800 packets, 199K bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 28028 packets, 11M bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 1860 packets, 433K bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        1    70 CONNMARK   all  --  *      *       0.0.0.0/0            0.0.0.0/0           CONNMARK match !0x0 CONNMARK restore 
2       13   818 MARK       all  --  *      *       172.16.61.2          0.0.0.0/0           MARK set 0x2 

没有得到结果。

以下说明:

sysctl -w net.ipv4.conf.eth0.rp_filter=2
sysctl -w net.ipv4.fwmark_reflect=1

报告它们是未知密钥。

iptables-save -c输出清除了一些与帖子无关的行

# Generated by iptables-save v1.3.8 on Wed Aug 11 13:11:07 2021
*filter
:INPUT DROP [79:12622]
:FORWARD DROP [18:1104]
:OUTPUT DROP [0:0]
[633:37905] -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT 
[0:0] -A INPUT -p udp -m state --state ESTABLISHED -j ACCEPT 
[0:0] -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT 
[2:152] -A INPUT -s 192.168.1.0/255.255.255.0 -p tcp -j ACCEPT 
[0:0] -A INPUT -s 192.168.1.0/255.255.255.0 -p udp -j ACCEPT 
[10:1936] -A INPUT -s 192.168.1.0/255.255.255.0 -p icmp -j ACCEPT 
[8:696] -A FORWARD -p udp -m state --state ESTABLISHED -j ACCEPT 
[129:20225] -A FORWARD -p tcp -m state --state ESTABLISHED -j ACCEPT 
[0:0] -A FORWARD -p icmp -m state --state ESTABLISHED -j ACCEPT 
[0:0] -A FORWARD -s 192.168.1.0/255.255.255.0 -p icmp -j ACCEPT 
[33:3014] -A FORWARD -s 192.168.1.0/255.255.255.0 -p tcp -j ACCEPT 
[8:532] -A FORWARD -s 192.168.1.0/255.255.255.0 -p udp -j ACCEPT 
[1026:179208] -A OUTPUT -p tcp -m state --state ESTABLISHED -j ACCEPT 
[0:0] -A OUTPUT -p udp -m state --state ESTABLISHED -j ACCEPT 
[0:0] -A OUTPUT -p icmp -m state --state ESTABLISHED -j ACCEPT 
[10:1656] -A OUTPUT -s 192.168.1.0/255.255.255.0 -p tcp -j ACCEPT 
[2:140] -A OUTPUT -s 192.168.1.0/255.255.255.0 -p udp -j ACCEPT 
[0:0] -A OUTPUT -s 192.168.1.0/255.255.255.0 -p icmp -j ACCEPT 
[0:0] -A OUTPUT -s 172.16.61.2 -j ACCEPT 
COMMIT   
*mangle
:PREROUTING ACCEPT [920:78186]
:INPUT ACCEPT [724:52615]
:FORWARD ACCEPT [196:25571]
:OUTPUT ACCEPT [1040:181200]
:POSTROUTING ACCEPT [1218:205667]
[2:196] -A PREROUTING -m mark ! --mark 0x0 -j CONNMARK --save-mark 
[2:168] -A OUTPUT -m connmark ! --mark 0x0 -j CONNMARK --restore-mark 
[2:196] -A OUTPUT -s 172.16.61.2 -j MARK --set-mark 0x2 
COMMIT
*nat
:PREROUTING ACCEPT [127:16611]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [2:242]
[30:2978] -A POSTROUTING -s 192.168.1.0/255.255.255.0 -j SNAT --to-source 172.16.61.2 
COMMIT

更新:

我已经尝试过什么AB在 url 的帖子中建议用于标记路由表流量的 IPTable mangle 规则:

"Adding any default route in table main (even using a non-existing router as long as it's a valid syntax) would allow the intended flow:"
$ ip route add default via 192.168.168.150

$ ip route show table main
192.168.3.0/24 dev eth5  proto kernel  scope link  src 192.168.3.1 
192.168.1.0/24 dev eth3  proto kernel  scope link  src 192.168.1.150 
172.16.62.0/24 dev eth4  proto kernel  scope link  src 172.16.62.100 
172.16.61.0/24 dev eth4  proto kernel  scope link  src 172.16.61.2 
192.168.168.0/24 dev eth3  proto kernel  scope link  src 192.168.168.1 
192.168.8.0/24 dev eth3  proto kernel  scope link  src 192.168.8.1 
169.254.0.0/16 dev eth5  scope link 
10.200.0.0/16 via 192.168.1.185 dev eth3 
default via 192.168.168.150 dev eth3 

从今起网关/防火墙我可以连接到互联网,如下所示

nc -v 216.58.205.78 443
Connection to 216.58.205.78 443 port [tcp/https] succeeded!

我还无法从属于本地网络 192.168.1.0 并使用网关/防火墙作为网关,我可能认为这是由于以下事实:

iptables -t nat -A POSTROUTING  -s 192.168.1.0/24 -j SNAT --to-source 172.16.61.2

之后执行

iptables -A OUTPUT -t mangle -s 172.16.61.2 -j MARK --set-mark 2

因此61号公路不使用路由表。

tcpdump -ni any '(host 192.168.1.5 or host 172.16.61.2)' and port 443当我nc -v 216.58.205.78 443从本地网络上的 pc 192.168.1.5运行时的输出是

12:15:51.184032 IP 192.168.1.5.58870 > 216.58.205.78.https: S 4157294472:4157294472(0) win 29200 <mss 1460,sackOK,timestamp 14470157 0,nop,wscale 7>
12:15:52.186303 IP 192.168.1.5.58870 > 216.58.205.78.https: S 4157294472:4157294472(0) win 29200 <mss 1460,sackOK,timestamp 14471160 0,nop,wscale 7>
12:15:54.190008 IP 192.168.1.5.58870 > 216.58.205.78.https: S 4157294472:4157294472(0) win 29200 <mss 1460,sackOK,timestamp 14473164 0,nop,wscale 7>

我们看到 IP 转换来自192.168.1.5172.16.61.2没有执行

如果打开网关/防火墙我运行route add -net 0.0.0.0 gw 172.16.61.1 netmask 0.0.0.0 dev eth4tcpdump 的输出变为:

13:00:53.194649 IP 192.168.1.5.59188 > 216.58.205.78.https: S 3448270320:3448270320(0) win 29200 <mss 1460,sackOK,timestamp 17172595 0,nop,wscale 7>
13:00:53.194879 IP 172.16.61.2.59188 > 216.58.205.78.https: S 3448270320:3448270320(0) win 29200 <mss 1460,sackOK,timestamp 17172595 0,nop,wscale 7>
13:00:53.223644 IP 216.58.205.78.https > 172.16.61.2.59188: S 3227185810:3227185810(0) ack 3448270321 win 65535 <mss 1430,sackOK,timestamp 3513192655 17172595,nop,wscale 8>
13:00:53.223691 IP 216.58.205.78.https > 192.168.1.5.59188: S 3227185810:3227185810(0) ack 3448270321 win 65535 <mss 1430,sackOK,timestamp 3513192655 17172595,nop,wscale 8>
13:00:53.223785 IP 192.168.1.5.59188 > 216.58.205.78.https: . ack 1 win 229 <nop,nop,timestamp 17172625 3513192655>
13:00:53.223819 IP 172.16.61.2.59188 > 216.58.205.78.https: . ack 1 win 229 <nop,nop,timestamp 17172625 3513192655>

更新 : 现在我正在尝试iptables -A PREROUTING -t mangle -s 192.168.1.0/24 ! -d 192.168.1.0/255.255.255.0 -j MARK --set-mark 0x2,似乎取得了一些不错的结果。它允许我从电脑 192.168.1.5 连接到互联网,但不允许我连接到同一本地网络内的电脑 192.168.3.5。

更新 :

我对 mangle 表进行了以下更改,现在它似乎可以工作:

iptables -t mangle -I OUTPUT -m connmark ! --mark 0 -j CONNMARK --restore-mark
iptables -A OUTPUT -t mangle -s 172.16.62.100 -j MARK --set-mark 1
iptables -A OUTPUT -t mangle -s 172.16.61.2   -j MARK --set-mark 2
iptables -A PREROUTING -t mangle -s 192.168.1.0/24 -d 192.168.3.0/24 -j ACCEPT
iptables -A PREROUTING -t mangle -s 192.168.3.0/24 -d 172.16.61.2    -j ACCEPT
iptables -A PREROUTING -t mangle -s 192.168.1.0/24 ! -d 192.168.1.0/24 -j MARK --set-mark 0x2
iptables -A PREROUTING -t mangle -s 192.168.3.5    ! -d 192.168.3.0/24 -j MARK --set-mark 0x1
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j CONNMARK --save-mark

相关内容