Linux NAT 应用进阶
展示了 Linux NAT 应用进阶 的五个例子
- 双供应商 + SNAT + 固定子网选路输出
- 双供应商 + SNAT + 带权重概率选路
- 多供应商 + SNAT + 带权重概率选路
- 双供应商 + DNAT + 原路返回
- 双供应商 + DNAT + 原路返回 + SNAT + 带权重概率选路
双供应商 + SNAT + 固定子网选路输出
拓扑:
LAN . WAN
.
. ens69f1
192.168.33.1/24 . 192.168.11.1/24 192.168.11.254/24 ---------
[client_1]-------------------------\ . /--------------------------------------[isp_1]----( )
gw: 192.168.33.254/24 \ ens69s0 . / ( )
\ 192.168.33.254/24 . / ( )
[switch]-----------------------[firewall] ( clound )---[server]
/ \ ens69f2 ( )
192.168.33.2/24 / \ 192.168.22.1/24 192.168.22.254/24 ( )
[client_2]-------------------------/ \--------------------------------------[isp_2]----( )
gw: 192.168.33.254/24 ---------
需求
- 源地址 是 192.168.33.1/32 的报文 默认路由 网关为 192.168.11.254 (isp_1)。
- 源地址 是 192.168.33.2/32 的报文 默认路由 网关为 192.168.22.254 (isp_2)。
- 源地址 192.168.33.0/24 的报文 都 伪装成外网地址。
设计方案
- 策略路由
添加两张的策略路由表。按照不同的 标签来 选择不同的 供应商。
供应商 | 源地址 | 策略路由表 id | 默认路由网关 | 流出网口 |
---|---|---|---|---|
isp_1 | 192.168.33.1/32 | 1 | 192.168.11.254 | ens69f1 |
isp_2 | 192.168.33.2/32 | 2 | 192.168.22.254 | ens69f2 |
- SNAT
源地址 192.168.33.0/24 的报文 都 伪装成外网地址。
供应商 | 流出网口 | SNAT 到 外网地址 |
---|---|---|
isp_1 | ens69f1 | 192.168.11.1 |
isp_2 | ens69f2 | 192.168.22.1 |
设计实施
firewall 的配置指令:
ip link set ens69f0 up
ip a a 192.168.33.254/24 dev ens69f0
ip link set ens69f1 up
ip a a 192.168.11.1/24 dev ens69f1
ip link set ens69f2 up
ip a a 192.168.22.1/24 dev ens69f2
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
# 策略路由
# table 1
# 源地址 是 192.168.33.1/32 的报文 默认路由 网关为 192.168.11.254。
ip route add table 1 default via 192.168.11.254 dev ens69f1
ip rule add from 192.168.33.1/32 table 1
# table 2
# 源地址 是 192.168.33.2/32 的报文 默认路由 网关为 192.168.22.254。
ip route add table 2 default via 192.168.22.254 dev ens69f2
ip rule add from 192.168.33.2/32 table 2
# 确认主路由表中,有以下直联路由
# ip route show
> ip route add 192.168.11.0/24 dev ens69f1 proto kernel scope link src 192.168.11.1
> ip route add 192.168.22.0/24 dev ens69f2 proto kernel scope link src 192.168.22.1
> ip route add 192.168.33.0/24 dev ens69f0 proto kernel scope link src 192.168.33.254
# SNAT
# 源地址 192.168.33.0/24 的报文 都 伪装成外网地址。
iptables -t nat -A POSTROUTING -s 192.168.33.0/24 -j MASQUERADE
验证
略
双供应商 + SNAT + 带权重概率选路
拓扑:
LAN . WAN
.
. ens69f1
192.168.33.1/24 . 192.168.11.1/24 192.168.11.254/24 ---------
[client_1]-------------------------\ . /--------------------------------------[isp_1]----( )
gw: 192.168.33.254/24 \ ens69s0 . / ( )
\ 192.168.33.254/24 . / ( )
[switch]-----------------------[firewall] ( clound )---[server]
/ \ ens69f2 ( )
192.168.33.2/24 / \ 192.168.22.1/24 192.168.22.254/24 ( )
[client_2]-------------------------/ \--------------------------------------[isp_2]----( )
gw: 192.168.33.254/24 ---------
需求
- 源地址 192.168.33.0/24 的报文 都 伪装成外网地址。
- 源地址 192.168.33.0/24 的报文 20% 新建连接的 默认路由 网关为 192.168.11.254 (isp_1)。
- 源地址 192.168.33.0/24 的报文 80% 新建连接的 默认路由 网关为 192.168.22.254 (isp_2)。
- 同一连接的报文,保证走相同的出口。
- 子连接,保证与主连接走相同的出口。
设计方案
- 对新建流打标签
在 PREROUTING 链,对新建的流打 按照 按照权重打上标签。
使用 state 的 --state NEW,来匹配新建的连接。
使用 statistic 的 --probability ,来生成随机数。随机选路。
使用 CONNMARK 的 --set-mark ,对新建的流打上标签。
使用 CONNMARK 的 --restore-mark,将 ct->mark(连接跟踪标签)拷贝到 skb->mark(报文标签)
供应商 | 需求新建连接走包概率 | –probability 参数 | 标签 |
---|---|---|---|
isp_1 | 20% | 0.2 | 0x11/0xff |
isp_2 | 80% | 1 | 0x22/0xff |
- 策略路由
添加两张的策略路由表。按照不同的 标签来 选择不同的 供应商。
供应商 | 标签 | 策略路由表 id | 默认路由网关 | 流出网口 |
---|---|---|---|---|
isp_1 | 0x11/0xff | 1 | 192.168.11.254 | ens69f1 |
isp_2 | 0x22/0xff | 2 | 192.168.22.254 | ens69f2 |
- SNAT
源地址 192.168.33.0/24 的报文 都 伪装成外网地址。
供应商 | 流出网口 | SNAT 到 外网地址 |
---|---|---|
isp_1 | ens69f1 | 192.168.11.1 |
isp_2 | ens69f2 | 192.168.22.1 |
注意:
子连接可以得到主连接的 ct_mark。可以保持子连接与主连接走相同的出口。
所以没有需要格外对 状态 为 RELATED 子连接 打 mark。
以下是内核的代码实现。
static struct nf_conntrack_tuple_hash* init_conntrack(...)
{
/* ... */
#ifdef CONFIG_NF_CONNTRACK_MARK
ct->mark = exp->master->mark; /* 子连接可以得到主连接的 ct_mark */
#endif
/* ... */
}
设计实施
firewall 的配置指令:
ip link set ens69f0 up
ip add add 192.168.33.254/24 dev ens69f0
ip link set ens69f1 up
ip add add 192.168.11.1/24 dev ens69f1
ip link set ens69f2 up
ip add add 192.168.22.1/24 dev ens69f2
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
# 对新建流打标签
# 对于 源地址 192.168.33.0/24 的 新建连接
# 1. 设置 20% 的概率 打上 0x11/0xff 标签。
# 2. 将没有打上标签(ct_mark 在初始化的时候 是 0x0 )的新建连接,都打上 0x22/0xff 标签。
# 3. 从 ct->mark(连接跟踪标签)拷贝到 skb->mark(报文标签)。
iptables -t mangle -A PREROUTING -s 192.168.33.0/24 -m state --state NEW -m statistic --mode random --probability 0.2 -j CONNMARK --set-mark 0x11/0xff
iptables -t mangle -A PREROUTING -s 192.168.33.0/24 -m state --state NEW -m connmark --mark 0x0/0xff -j CONNMARK --set-mark 0x22/0xff
iptables -t mangle -A PREROUTING -s 192.168.33.0/24 -j CONNMARK --restore-mark --ctmask 0xff --nfmask 0xff
# 策略路由
# table 1
# 源地址 是 192.168.33.0/24 并且 打上 0x11/0xff标签 的报文 默认路由 网关为 192.168.11.254。
ip rout