![这是这个想法的图形表示:](https://linux22.com/image/43987/%E8%BF%99%E6%98%AF%E8%BF%99%E4%B8%AA%E6%83%B3%E6%B3%95%E7%9A%84%E5%9B%BE%E5%BD%A2%E8%A1%A8%E7%A4%BA%EF%BC%9A.png)
简而言之,
3 个接口,eth0(LAN)、eth1(ADSL)、eth2(4G)。eth0
-> eth1:工作
(端口 80、443、4070)eth0 -> eth2:不发生
这是这个想法的图形表示:
端口 80 和 443 通过 eth2
其余部分通过 eth1
网络方案:
eth0: -ip 10.0.0.1 -net 10.0.0.0/8 -gw 10.0.0.1 (the servers own intf)
eth1: -ip 192.168.1.74 -net 192.168.1.0/24 -gw 192.168.1.254
eth2: -ip 192.168.1.91 -net 192.168.0.0/24 -gw 192.168.0.1
我认为这个新脚本将 22 和 4070 重新路由到正确的表。
但是,到达该表后,它不会重新路由到 eth2。
该脚本有效,除了 22 和 4070!
(端口 80 未注释,它可以工作,但通过 eth1 是错误的。)
modprobe iptable_nat
modprobe ip_conntrack
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -F PREROUTING
iptables -t nat -F
iptables -t mangle -F
iptables -F
# This next line restores any issues trying to connect to something
# if you get weird ACK packets when trying to connect (at least i did)!
iptables -t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark
ip route flush table main
iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 22 -j MARK --set-mark 1
### iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 80 -j MARK --set-mark 1
iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 4070 -j MARK --set-mark 1
## Setup routes
# LAN
route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0
# ADSL
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
# 4G (Only accessible if marking packages with \x01
route add -net 192.168.0.0 netmask 255.255.255.0 dev eth2
# Default via ADSL
## -- Does the same as ip route below? route add default gw 192.168.1.254
echo "201 eth2.out" >> /etc/iproute2/rt_tables
ip rule add fwmark 1 table eth2.out
ip route add default via 192.168.0.1 dev eth2 table eth2.out
ip route add default via 192.168.1.254 dev eth1
## Setup forwards
# From 4G to LAN
iptables -A FORWARD -i eth2 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From ADSL to LAN
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From LAN to ADSL (Default route out)
# - Note: If marked packages is sent to ADSL they will be mangled and rerouted to 4G
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
旧脚本:
Ignore everything below unless you're interested in retracing my steps!!
我创建了一个 router.sh 脚本来设置我的环境,以防我做错事。我有 3 个端口,我想将它们发送到 4G 连接,其余端口则通过固定电话 ADSL 连接发送。为此,我指示 iptables 在默认路由上破坏软件包,并在 --dport == 443 | 条件满足的情况下通过我的 4G 接口发送它们。 80| 4070
然而,这是行不通的;无论如何,我仍然通过我的固定电话被路由。
这就是我的脚本的样子:
#!/bin/bash
## routing tables
# wireless = 4G via eth2
# adsl = adsl via eth1
modprobe iptable_nat
modprobe ip_conntrack
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -t nat -F
ip route flush table main
ip route flush table wireless
ip route flush table adsl
## Setup routing tables
# ADSL
ip route add table adsl to 192.168.1.0/24 dev eth1
# 4G
ip route add table wireless to 192.168.0.0 dev eth2
ip rule add fwmark 0x1 table wireless
## Setup routes
# LAN
route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0
# ADSL
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
# 4G (Only accessible if marking packages with \x01
route add -net 192.168.0.0 netmask 255.255.255.0 dev eth2
# Default via ADSL
route add default gw 192.168.1.254
## Forward ports into the LAN
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.0.3:80
## Lets mark all packets we want for 4G forward
# HTTPS
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# HTTP
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 80 -j MARK --set-mark 1
# Spotify
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 4070 -j MARK --set-mark 1
## Setup forwards
# From 4G to LAN
iptables -A FORWARD -i eth2 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From ADSL to LAN
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# From LAN to ADSL (Default route out)
# - Note: If marked packages is sent to ADSL they will be mangled and rerouted to 4G
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -A FORWARD -j LOG
#iptables --table nat --append POSTROUTING --out-interface eth2 --jump SNAT --to-source "192.168.1.74"
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
我还尝试将这 3 个添加到脚本的底部:
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 80 -j SNAT --to "192.168.0.91"
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 443 -j SNAT --to "192.168.0.91"
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 4070 -j SNAT --to "192.168.0.91"
也尝试过但没有成功:
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 80 -j MARK --set-mark 1
最后但并非最不重要的一点是,尝试过:
## Lets mark all packets we want for 4G forward
# HTTPS
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# HTTP
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 80 -j MARK --set-mark 1
# Spotify
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 4070 -j MARK --set-mark 1
路由工作正常,我可以浏览网页、听音乐等等,但我通过错误的界面进行操作。我已经在谷歌上搜索了很长一段时间,找到了一些零碎的信息来理解我在做什么以及为什么要这样做。我可以通过 tc 进行流量整形,但如果可以通过在 iptables 中标记包来实现,那将对我有很大帮助。
我的猜测是我在不同的规则上做错了顺序,主要是假面舞会部分?或者是否应该存在?
有人可以解释一下如何DNAT比如说,从外部接口(一种或两种协议)到内部 10.0.0.0 地址空间的 tcp:80?
输出:
root@Netbridge:~# route -n Kernel IP routing table Destination
Gateway Genmask Flags Metric Ref Use Iface<br>
0.0.0.0 192.168.1.254 0.0.0.0 UG 0 0 0 eth1<br>
10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0<br>
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2<br>
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
root@Netbridge:~# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0c:29:7e:9e:4e
inet addr:10.0.0.1 Bcast:10.255.255.255 Mask:255.0.0.0
eth1 Link encap:Ethernet HWaddr 00:0c:29:7e:9e:58
inet addr:192.168.1.74 Bcast:192.168.1.255 Mask:255.255.255.0
eth2 Link encap:Ethernet HWaddr 00:0c:29:7e:9e:62
inet addr:192.168.0.91 Bcast:192.168.0.255 Mask:255.255.255.0
请遵循以下说明:
基于目标端口的不同接口上的输出流量
iptables 转发特定端口到特定网卡
在其他一些相关线程中。
答案1
BatchyX 已经对 iptables 和路由给出了一些非常好的解释,所以我将锻炼我的懒惰并直接进入脚本。
它应该将所有流量通过 192.168.0.91 NAT 到端口 80,443,22,4070。其余的将通过 192.168.1.254 进行 NAT。
我重新进行测试并最终遵循此指导。该指南中缺少的是我的脚本中的最后 3 行。我从另一个端口发现了这一点,但我失去了该链接的踪迹。
这是一个经过测试的工作脚本。
需要默认路由
我没有放入脚本中的一件事是设置默认路由。它应该是
route add default gw 192.168.1.254
当您这样做时route -n
,它应该是唯一的默认路由(Dest:0.0.0.0)
0.0.0.0 192.168.1.254 0.0.0.0 UG 0 0 0 eth1
fw-router.sh
# 重置/刷新 iptables iptables -F iptables-X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X iptables -P 输入接受 iptables -P 转发接受 iptables -P 输出接受 #Reset/Flush/Setup IP 路由(表 4) ip 路由刷新表 4 ip 路由显示表主 | grep -Ev ^默认|当读取 ROUTE 时;执行 ip 路由添加表 4 $ROUTE ;完毕 ip 路由添加表 4 默认通过 192.168.0.1 #用匹配的 D.Port 标记数据包 iptables -t mangle -A PREROUTING -p tcp --dport 22 -s 10.0.0.0/24 -j MARK --set-mark 4 iptables -t mangle -A PREROUTING -p tcp --dport 80 -s 10.0.0.0/24 -j MARK --set-mark 4 iptables -t mangle -A PREROUTING -p tcp --dport 443 -s 10.0.0.0/24 -j MARK --set-mark 4 iptables -t mangle -A PREROUTING -p tcp --dport 4070 -s 10.0.0.0/24 -j MARK --set-mark 4 #SNAT 规则 iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to-source 192.168.1.74 iptables -t nat -A POSTROUTING -o eth2 -j SNAT --to-source 192.168.0.91 #IP路由 ip 规则添加 fwmark 4 表 4 ip 路由刷新缓存 #IP堆栈 #这是指南中缺失的部分 echo 1 > /proc/sys/net/ipv4/ip_forward 对于 /proc/sys/net/ipv4/conf/*/rp_filter 中的 f ;执行 echo 0 > $f ;完毕 echo 0 > /proc/sys/net/ipv4/route/flush
PS1:简而言之,MASQUERADE
对于需要某种负载平衡或需要 DNAT 来处理传入流量的多个外部 IP 的 NAT 不起作用(在大多数情况下,绝对在您的情况下)。你需要SNAT
方向控制。
PS2:纯粹的 iptables 是不够的。
答案2
注意:我只考虑了第一个脚本,忽略了旧的脚本。
- 您不需要使用当前的 iptables 手动修改 netfilter 模块。这仅对于自定义连接跟踪器是必需的。
- 不要混淆
route
和ip route
。这是纯粹的邪恶。只需在任何地方使用ip
即可忘记ifconfig
androute
/etc/iproute2/rt_tables
重新启动后不会重置。一遍又一遍地附加相同的条目并不是一个好主意,您只需要执行一次。请记住,rt_tables
只需将名称别名定义为数值,它不会更改任何配置。现在
iptables
:在您的FORWARD
链中,您丢弃来自 LAN 到 4G 的数据包。这不好。该FORWARD
钩子在路由完成后使用。至此,所有的策略路由就完成了,已经知道数据包应该发送到4G还是ADSL了。期间FORWARD
或之后均不进行重新路由FORWARD
(好吧,从技术上讲,在严重情况下可以在之后进行重新路由POSTROUTING
,但回到正题)。
现在进行路由:请记住,Ubuntu 默认启用反向路径过滤。反向路径过滤的工作原理如下:当内核从接口 A 接收到数据包(无论是否转发)时,它将反转源地址和目标地址,并检查结果数据包是否应通过接口 A 路由。如果不是,则该数据包将作为地址欺骗尝试而被丢弃。
对于从 接收的数据包eth0
,这不是问题。对于从 收到的数据包eth1
,这也不是问题,因为当反转源 IP 地址和目标 IP 地址时,内核会将其作为表中的默认路由main
。对于从 接收的数据包eth2
,如果您没有标记,这是一个问题,因为内核将命中表中的默认路由main
,并认为这些数据包应该是从 接收的eth1
。最简单的解决方案是禁用 eth1 上的反向路径过滤:
sysctl -w net.ipv4.conf.eth1.rp_filter=0