如何将所有流量从特定接口路由到特定网关而不是默认路由?

如何将所有流量从特定接口路由到特定网关而不是默认路由?

在我的机器上,我有两个接口:(wlan0默认路由)和tun0.该tun0接口只是一个本地网络,它的 IP 范围是172.16.150.0/24,我的机器(机器 A)的 IP 地址是172.16.150.1,另一台机器(机器 B)的 IP 地址是172.16.150.128。我设置了一个 wifi 热点,它为我创建了另一个界面ap0。我想ap0通过机器B路由来自接口的所有流量(因此网关应该是172.16.150.128)。

$ ip route
default via 192.168.0.1 dev wlan0 proto dhcp src 192.168.0.179 metric 1024
172.16.150.0/24 dev tun0 proto kernel scope link src 172.16.150.1 metric 1024
192.168.0.0/24 dev wlan0 proto kernel scope link src 192.168.0.179 metric 1024 
192.168.0.1 dev wlan0 proto dhcp scope link src 192.168.0.179 metric 1024 
192.168.12.0/24 dev ap0 proto kernel scope link src 192.168.12.1

此时,由于默认路由是192.168.0.1,因此它将所有流量路由wlan0到我的家庭路由器的接口。

我不是一个经验丰富的 Linux 用户,所以我不确定如何让 Linux 内核通过ap0网关路由所有流量172.16.150.128,但这就是我尝试过的:

$ ip route add default 192.168.12.0/24 via 172.16.150.128
Error: either "to" is duplicate, or "192.168.12.0/24" is a garbage.

在这里,我尝试让内核192.168.12.0/24通过网关路由来自子网的所有流量172.16.150.128

$ ip route add 192.168.12.0/24 via 172.16.150.128
RTNETLINK answers: File exists

与之前的命令相同,但没有这个default词。我读到过ip addr flush dev ap0可能有帮助的地方,但它会重置接口及其 IP 地址,因此我需要通过手动恢复 IP 地址ip addr add或重新启动 wifi 热点。

我认为这不是正确的方法,因为我不想刷新接口,而是想将路由更改default为特定网关。

我怎样才能做到这一点?

答案1

简单的路由在这里是不够的。简单路由关心目的地。但这里的目标是根据来源改变路线。这样做称为策略路由。在 Linux 上,这是通过使用其他选择器(不仅仅是目的地)来实现的,例如源 IP 地址或源数据包的传入接口来选择备用路由表。这些备用路由表可以有其他路由,包括其他默认路由,最终为数据包选择与常用路由不同的路由。主要的路由表。

这通常与一些组合使用ip rule add ... lookup TABLE+ 一些ip route add ... table TABLE,根据要解决的问题量身定制选择。通常ip rule ...会有基于源的选择器来进行不同的处理,同时ip route ...会有(并且只能有)用于这种情况的替代目标。

因此,对于这种情况,可以像下面这样做。

  • 准备备用路由表(使用任意表 1000)

    该表应包含所需的所有内容,因此将手动复制主路由表的部分内容

    ip route add 192.168.12.0/24 dev ap0 table 1000
    ip route add 172.16.150.0/24 dev tun0 table 1000
    

    当然,为了实现目标,也有备用默认路由:

    ip route add default via 172.16.150.128 dev tun0 table 1000
    
  • 为两个相关接口选择备用路由表

    ip rule add iif ap0 lookup 1000
    ip rule add iif tun0 lookup 1000
    

    路由规则应如下所示:

    # ip rule
    0:    from all lookup local
    32764:    from all iif tun0 lookup 1000
    32765:    from all iif ap0 lookup 1000
    32766:    from all lookup main
    32767:    from all lookup default
    

这解决了机器上的路由问题(但请参阅下一部分有关远程系统路由或使用 NAT 的内容):

  • 来自的任何数据包ap0将使用备用路由表并将被发送到tun0

    这包括发送到互联网的流量,该流量将通过 172.16.150.128。详细信息:专门发送到本机的流量,实际上会使用当地的首先是路由表,所以仍然可以照常工作。

  • 来自的任何数据包都tun0将使用备用路由表

    • (如果发送到该系统,实际上当地的路由表将首先将其路由到该系统)

    • 如果发送到 192.168.12.0/24 它将使用ap0

    • 有关详细信息:在其他情况下,路由查找会将流量发送回 172.16.150.128

      但这种情况在实践中绝对不应该发生。

如果ap0tun0曾经下降然后上升,则表1000中的相关路由将丢失并且必须重新添加。


还剩下一个问题:如果 172.16.150.0/24 LAN 上的系统对 192.168.12.0/24 一无所知,它们将永远不会向该系统 (172.16.150.1) 发回回复流量。他们可能会使用自己的默认网关,即 172.16.150.128。同样,172.16.150.128 可能会将 192.168.12.0/24 的任何流量发送到其自己的上游网关,离开从这台机器,而不是通过这台机器。

要解决这个问题:

  • 让 172.16.150.0/24 中的其他系统知道该 LAN(首选)

    只需在 172.16.150.128 上添加路由就足够了:172.16.150.0/24 中的其他系统将尝试通过 172.16.150.128 发送数据包,除了通过 172.16.150.1 路由数据包之外,还会发送 ICMP 重定向以告诉这些其他系统发送他们直接在那里。如果 172.16.150.128 系统也运行 Linux,这应该很简单:

    ip route add 192.168.12.0/24 via 172.16.150.1
    

    所有系统也可以直接添加完全相同的路线。如果通过 DHCP 配置,则应使用 DHCP 选项 121(对于较旧的 Windows 客户端可能使用选项 249)将此设置添加到 DHCP 配置中,但这超出了本答案的范围。

  • 否则,如果之前的更改无法完成(例如:无法控制 172.16.150.128),请使用 NAT

    如果无法在 172.16.150.0/24(尤其是 172.16.150.128)中的系统上设置正确的路由,那么仍然可以使用 NAT 将所有 192.168.12.0/24 折叠到可到达的 172.16.150.1 中。在机器上添加:

    iptables -t nat -A POSTROUTING -s 192.168.12.0/24 -o tun0 -j MASQUERADE
    

    此方法允许从 192.168.12.0/24 到 172.16.150.0/24 并通过 172.16.150.128 的流量沿着回复数据包到达 Internet,但不允许从除此之外的任何其他位置访问 192.168.12.0/24 上的任何服务机器。需要针对特定​​端口/服务进行其他 NAT 设置才能创建例外。

相关内容