我的系统有两个网络接口,它们都使用不同的 IP 地址连接到互联网。我希望对传入请求的响应通过接收它们的同一接口发送。
由于德国互联网提供商的性质,我的网络接口的公共 IP 地址每 24 小时更改一次。这是与类似问题的主要区别在与传入相同的界面上回复?,其响应均依赖于基于接口 IP 地址定义 IP 规则。
我可以配置一个 IP 规则,根据接口而不是其 IP 地址来选择路由表吗?到目前为止,我已经有但尚未成功应用的想法是使用iif
或oif
选项或设置fwmark
using iptables mangle。
答案1
感谢您在评论中提供的所有提示。基于它们,我提出了两种可能的解决方案。
方案一:ip规则
假设我有两个接口eth1
和eth2
,并且eth1
应该是用于传出连接的默认设备,我将定义第二个路由表,该路由表将使用eth2
并设置一个 ip 规则,该规则使用此路由表来响应 上的传入请求eth2
:
iptables -t mangle -A INPUT -j CONNMARK -i eth2 --set-mark 2
iptables -t mangle -A OUTPUT -j CONNMARK -m connmark --mark 2 --restore-mark
ip route add 192.168.1.0/24 dev eth2 table 1234
ip route add default via 192.168.1.1 table 1234
ip rule add fwmark 2 lookup 1234
(对于 IPv6,请使用ip6tables
和重复相同的操作ip -6
。)
CONNMARK
添加一个标记联系(包括响应)与 相对MARK
,它为(传入)添加一个标记包仅有的。该INPUT
规则设置connmark
传入的请求eth2
及其响应。OUTPUT
with 规则会将--restore-mark
复制connmark
到 a 中mark
,这是必要的,因为fwmark
ip 规则的匹配器只匹配mark
s 而不是connmark
s。
在OUTPUT
我添加的规则中-m connmark --mark 2
,以确保仅为具有 of 的包设置connmark
标记2
。我添加这个是因为否则它会覆盖所有传出连接的标记,例如破坏依赖于其自身标记的 Wireguard。
路由连接
上述规则仅匹配eth2
由机器本身处理的传入连接,但不匹配路由到另一台机器的连接。为了支持该用例,请使用以下附加规则:
iptables -t mangle -A PREROUTING -j CONNMARK -m connmark --mark 2 --restore-mark
iptables -t mangle -A PREROUTING -j CONNMARK -i eth2 --set-mark 2
第二条规则将标记通过 传入的每个数据包eth2
,而第一个规则将匹配其的每个数据包联系已经有一个 connmark2
并将复制该标记联系到包(确保对最初传入的数据包的响应eth2
也被标记)。
为此,1234
还需要将路线目的地添加到表中!
解决方案 2:ip 命名空间
通过此解决方案,两个网络接口将完全彼此分离。每个进程将被分配给其中一个命名空间,因此只能看到两个网络接口之一。这意味着应该通过两个网络接口(例如 ssh)访问的服务需要启动两次,每个命名空间一次。由于进程和网络接口彼此严格分开,因此响应会自动通过正确的接口发送。据我了解,这甚至意味着当我通过一个特定网络接口 SSH 到计算机上时,我从该 SSH 会话发起的任何传出网络请求将始终使用同一网络接口。
我还没有尝试过这个解决方案,因为它对于我的用例来说并不是很完美,但是从我可以在网上找到的信息来看,它应该配置如下:
ip netns add net2
ip link set eth2 netns net2
net2
然后,您可以使用运行命名空间范围内的任何命令ip netns exec net2 <command>
。任何配置或使用网络接口的 DHCP 客户端或其他软件都必须以这种方式启动。在我看来,不同 Linux 发行版的网络配置解决方案之间还没有对命名空间的广泛支持,因此可能需要一些手动脚本才能使其正常工作。