![根据本地用户 ID 设置源 IP 的 iptables 规则](https://linux22.com/image/637368/%E6%A0%B9%E6%8D%AE%E6%9C%AC%E5%9C%B0%E7%94%A8%E6%88%B7%20ID%20%E8%AE%BE%E7%BD%AE%E6%BA%90%20IP%20%E7%9A%84%20iptables%20%E8%A7%84%E5%88%99.png)
我有两个用户,alpha (uid 500) 和 beta (uid 501),以及两个分配为 eth0 和 eth0:1 的 IP 地址。我希望由用户 alpha 启动的进程发出的所有传出数据包都标记为 eth0 的源 IP 地址,而来自用户 beta 进程的所有数据包都标记为 eth0:1 的源 IP 地址。
通过搜索本论坛和其他地方提供的答案,我发现我应该做这样的事情:
# mark packets with 11 or 12 depending which user they came from:
iptables -A OUTPUT -m owner --uid-owner 500 -j MARK --set-mark 11
iptables -A OUTPUT -m owner --uid-owner 501 -j MARK --set-mark 12
# now, for a packet having mark 11 (or 12), set source IP to 192.168.1.1 (or .2)
iptables -t nat -I POSTROUTING -m connmark --mark 11 -j SNAT --to-source 192.168.1.1
iptables -t nat -I POSTROUTING -m connmark --mark 12 -j SNAT --to-source 192.168.1.2
上述方法有效吗?是否有更简单的设置(一步而不是两步)?我该如何使用tcpdump
来验证它确实有效?
答案1
不幸的是,由于工作方式的原因netfilter
,您无法进行“一步式”设置。
- 数据包所有者只能在 OUTPUT 链中检测到,但是
- SNAT只能在POSTROUTING链中执行
也就是说,我建议不要使用 SNAT,而是使用netfilter
和的组合iproute2
,例如:
为了netfilter
:
iptables -A OUTPUT -m owner --uid-owner 500 -j MARK --set-mark 500
iptables -A OUTPUT -m owner --uid-owner 501 -j MARK --set-mark 501
为了iproute2
:
ip rule add fwmark 500 table 500
ip rule add fwmark 501 table 501
ip route add default via $gateway dev eth0 src $ip_eth0 table 500
ip route add default via $gateway dev eth0 src $ip_eth0_1 table 501
答案2
现在(iptables v1.4.21)只需一步即可完成:
iptables -t nat -A POSTROUTING ! -o lo -m owner --uid-owner 1030 -j SNAT --to-source 10.0.0.85
并且 uid 为 1030 的用户将从 10.0.0.85 发起所有连接(如果 ip 位于传出接口上)。