我在实验室配置的台式机有两个网络接口连接外部网络, eno2
连接教育网、wlo1
连接校园网。其中, 教育网接口提供千兆对等的互联网访问, 但无法访问校园网内部资源; 而校园网接口通过无线网络连接, 可以访问校园网资源, 但互联网访问速度有限, 并且按照流量计费(虽然目前疫情期间免费)。于是, 我配置了路由表, 让去往校园网的流量走校园网接口, 其他流量走教育网接口。此外, 台式机下面挂了192.168.1.0/24
的子网, 目前接了一个树莓派。
然而, 上述配置方法存在问题。当我使用笔记本电脑在校园网环境下使用教育网IP地址远程连接台式机时, 台式机的响应包会以教育网IP地址(即我发送请求使用的地址)为源地址, 然后由于响应包的目标IP地址为校园网地址, 根据路由表, 响应包会被发送至校园网接口。由于源地址不正确, 校园网会拒绝转发这一响应包。类似地, 当我使用笔记本电脑在非校园网环境下使用校园网IP地址远程连接台式机时, 台式机的响应包会以校园网IP地址为源地址, 被发送至教育网接口, 产生同样的问题。(事实上, 我发现教育网接口允许伪造源地址, 但这不在本文讨论范围内了。)
为了解决这一问题, 一个直观的想法是, 若源IP地址已经确定, 就应当使用对应的接口发送数据包。于是, 我配置了基于源地址的策略路由表: 如果源地址是教育网地址, 无论目标地址如何, 都使用教育网接口; 如果源地址是校园网地址, 无论目标地址如何, 都使用校园网接口。对于台式机向外创建的新连接, 由于源地址尚未确定, Linux会查询默认的路由表, 即本文第一段一开始配置的路由表, 然后选择出接口上配置的地址作为源地址, 因此不受前面的策略路由影响。
至此, 对于台式机自身, 上面的问题就解决了。进一步, 为了使得我可以远程访问树莓派, 我在台式机上添加了iptables的DNAT规则, 把2222端口转发至树莓派的ssh端口(22):
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 2222 -j DNAT --to-destination 192.168.1.树莓派:22
然而, 当我尝试使用笔记本电脑在校园网环境下使用台式机的教育网IP地址远程连接树莓派时, 却发现无法连接。聪明的读者意识到问题所在了吗?
事实上, 上述DNAT规则隐含了一个POSTROUTING阶段的SNAT, 即在查询路由表之后把树莓派发的响应包的源IP地址和端口号转换回台式机的。注意到, 在查询路由表时, 这个响应包的源IP地址还未被改变, 为192.168.1.树莓派
, 因此, 系统会查询默认路由表, 然后选择校园网接口作为出接口。
为了解决这些问题, 需要换一种策略路由的方式。经Soha指点, 我们可以在收到包的时候对包所对应的流打上标签, 记录这个流对应的接口。然后利用策略路由, 让有标记的流的包在此后的通信中都使用相同的接口。
首先, 利用iptables维护包和流的标签信息:
# 对于本机生成的包, 如果对应的流有标签, 那么给包设置同样的标签。 iptables -t mangle -A OUTPUT -m connmark --mark 1000 -j CONNMARK --restore-mark iptables -t mangle -A OUTPUT -m connmark --mark 1001 -j CONNMARK --restore-mark # 对于接收到的包, 如果对应的流有标签, 那么给包设置同样的标签。这些包一般是从其它接口收到, 并需要被转发至连接外部网络的接口。 iptables -t mangle -A PREROUTING -m connmark --mark 1000 -j CONNMARK --restore-mark iptables -t mangle -A PREROUTING -m connmark --mark 1001 -j CONNMARK --restore-mark # 对于接收到的包, 匹配接口, 然后给对应的流设置自定义的标签。 iptables -t mangle -A PREROUTING -i eno2 -j CONNMARK --set-mark 1000 iptables -t mangle -A PREROUTING -i wlo1 -j CONNMARK --set-mark 1001
然后, 配置策略路由规则以及不同标签对应的路由表。配置结果如下所示:
# ip rule 0: from all lookup local 0: from all fwmark 0x3e9 lookup 1001 0: from all fwmark 0x3e8 lookup 1000 ... # ip route show table 1000 default via 教育网网关 dev eno2 proto static 教育网网络前缀/长度 dev eno2 proto static scope link 192.168.1.0/24 dev br0 proto static scope link # ip route show table 1001 default via 校园网网关 dev wlo1 proto static onlink 校园网网络前缀/长度 dev wlo1 proto static scope link 192.168.1.0/24 dev br0 proto static scope link
其中, 每个路由表都需要配置192.168.1.0/24
的直连路由, 否则转发不正确。同时, 每个路由表都需要配置相应出接口所在子网的直连路由, 否则部分同一子网的包需要经过路由器转发, 路径不是最优。此外, 注意到, 策略路由使用的是包的标签, 而不是流的标签, 因此, 需要前面iptables的相关配置。
至此, 怎么样都可以访问了。
发表评论