我有一个 VPN 连接(通过 Open VPN 实现),但正在尝试将流量路由到它周围的某些 IP/域,因此他们只使用我的裸互联网连接。根据我的研究,最好的方法是使用路由表。我发现的所有示例都没有奏效,所以我想真正了解发生了什么,以便更有效地进行故障排除。
当我在关闭 VPN 的情况下运行“路由”时,它看起来非常合理:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.1.1 0.0.0.0 UG 0 0 0 eth1
192.168.1.0 * 255.255.255.0 U 1 0 0 eth1
我怀疑第一行设置了默认行为 - 我们通过网关进行路由。如果目的地位于 192.168.1.* 范围/我的内部网络的任何地方,则第二行声明网关为 *(我猜这意味着使用上面那行的默认值 - 但如果我的网络跨越多个八位字节,我可以使用它来将某些块引导到某些网关)。
我的预期是,当我打开 VPN 时,它会保持大致相同,但我的“默认”网关会转移到某个向导 VPN IP。
如果这种理解是正确的,我只需要添加我想要绕过 VPN 的 IP 作为目的地,将我的实际路由器(192.168.1.1)添加为网关,一切就可以正常工作(如果这个语法很简单,我很乐意看到它)。
然而,一旦我打开 VPN,事情就变得混乱了,我开始怀疑自己的知识:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.172.1.5 128.0.0.0 UG 0 0 0 tun0
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth1
10.172.1.1 10.172.1.5 255.255.255.255 UGH 0 0 0 tun0
10.172.1.5 0.0.0.0 255.255.255.255 UH 0 0 0 tun0
128.0.0.0 10.172.1.5 128.0.0.0 UG 0 0 0 tun0
168.1.6.15 192.168.1.1 255.255.255.255 UGH 0 0 0 eth1
192.168.1.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
这是怎么回事?有人能解释一下这些额外的行是什么,以及为什么当我切换 vpn 时它们会出现/消失吗?
感谢您的任何建议!我见过一些“什么是路由表”文章,但我认为它们是为比我聪明得多的人写的 - 我对 Linux 还很陌生,很想得到一些傻瓜式的建议 :)
答案1
这个问题很好,但也很困难。
首先,一个一般原则:在路由表中,如果你有几条适用于同一目的地的规则,最具体一个被使用。例如,查看第二个 RT,假设您要 ping Google DNS 8.8.8.8。第一行和第二行都适用,但第一行稍微更具体一些,因为它的网络掩码比第二行更严格:第一行适用于范围内的所有 IP 地址
0.0.0.0 -> 127.255.255.255
第二条规则适用于所有 IP 地址,IE那些在范围内
0.0.0.0 -> 255.255.255.255
因此使用更窄/更严格/更具体的第一条规则:ping 8.8.8.8 将必须经过dev tun0
IP 地址 10.172.1.5。
第二点:你的第二条转发包含两个单播路由:它们是第四列中用 表示的。如果您使用新命令H
代替过时的命令,单播路由的存在会更清晰:route/netstat
$ ip route show
(你应该始终这样做)因为这里单播路由由表达式表示作用域链接。
这是钥匙了解(开放)VPN 路由。手册状态:
范围 SCOPE_VAL
路由前缀所涵盖的目的地的范围。SCOPE_VAL 可以是数字或文件 /etc/iproute2/rt_scopes 中的字符串。如果省略此参数,ip 将假定所有网关单播路由的范围为全局,直接单播和广播路由的范围为链接,本地路由的范围为主机。
什么是单播路由?
静态单播路由是手动配置的 IP 地址到下一跳目的地的映射,因此称为特定目的地路由...当您想要通过不同的下一跳而不是默认路由来路由发往特定网络/主机的流量时,请添加静态路由。
换句话说:如果这条规则确实不是那么,由于 ping 8.8.8.8 会经过 10.172.1.5(就您的情况而言),但 tun0 上没有默认网关,数据包将被传输到 eth0 接口,那里有一个默认网关,并且会从这里出去。但这是正常情况,您不会拥有 (Open)VPN。相反,存在一个单播规则,并且它尽可能严格:它会强制您(无论数据包发往谁)将 10.172.1.1 作为下一跳。
好吧,现在怎么办:我们如何联系 10.172.1.1?dev tun0
没有这样的规则,因此数据包被转移到eth0
,希望运气更好。 现在,我们可以应用剩余的哪条规则来转发我们的 ping 数据包? 事实上,eth0
也有一个单播路由,
168.1.6.15 192.168.1.1 255.255.255.255 UGH 0 0 0 eth1
这会强制它将数据包作为下一跳发送到 168.1.6.15。从那时起,它就不再是我们的责任了。
我们可以总结一下这个逻辑过程:
数据包到 8.8.8.8 ---> dev tun0 ---> 10.172.1.5 ---> 168.1.6.15
(Rule #1) (Rule #3) (Rule #6)
未完成的事情:
剩余规则之一,规则#5
128.0.0.0 10.172.1.5 128.0.0.0 UG 0 0 0 tun0
补充规则 #1
0.0.0.0 10.172.1.5 128.0.0.0 UG 0 0 0 tun0
这两条规则共同为全球所有 IP 地址提供了默认规则,但由于每一条规则都比规则 #2 稍微严格一些
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth1
它们优先于它,并用于通过 OpenVPN 路由您的所有互联网流量。事实上,上述规则是多余的,它在旧版本的 OpenVPN 中已被删除。但它现在保留了下来,因为它基本上从未被调用过,当 OpenVPN 被拆除时,它使重新安装 RT#1 变得更容易。
规则 #7 是通常的本地 LAN 规则。您丢失的像这样的规则
10.172.1.0/24 dev tun0 proto kernel scope link src 10.172.1.5
这是你联系 pcs 所必需的偏僻的LAN。这很可能是因为您使用按次付费服务作为 OpenVPN 服务器,该服务无意允许您访问其他本地计算机。如果您在路上时通过此 OpenVPN 连接到家庭 LAN(例如),那么您肯定希望能够联系 LAN 上的其他 PC,并且您会有一条这样的规则。
最后,规则#4
10.172.1.5 0.0.0.0 255.255.255.255 UH 0 0 0 tun0
对我来说完全是神秘的:我的任何一个(众多)OpenVPN 上都没有它,而且据我所知,它对我来说完全是多余的。
答案2
您还询问:
“规则 3 将 ...15 地址作为网关 — 为什么会匹配?如果匹配,为什么我们要开始查看 ...1(规则中的目标地址)。就好像源/目标被交换了一样?”
这很难理解,因为 openvpn 的默认拓扑设置是“net30”。似乎大多数解决方案资源都假设我们已经更改了默认拓扑设置。
“您的 OpenVPN 在“net30”拓扑模式下工作。在此模式下,OpenVPN 进程本身就是一个路由器。”并且……“即 10.8.0.5 实际上是 OpenVPN 路由器的地址,它“隐藏在进程内部”。 ”
我认为,10.8.0.5 相当于您设置上的 10.172.1.15。
https://community.openvpn.net/openvpn/wiki/Topology
net30 实际上已被“弃用”,但仍然是 OpenVPN 2.3 系列的默认设置,因为担心会破坏依赖此行为的向后兼容配置。每个客户端都分配有一个虚拟 /30 网络,Windows 客户端必须使用中间的两个 IP,通常会将偶数 IP 分配给客户端(尽管这只是惯例)。
使用 net30 拓扑的唯一真正原因是需要支持 2.0.9 之前的 Windows 客户端,或者必须支持任何 Windows 客户端并且必须支持无法在 tun 适配器上设置 IP+网络掩码的非 Windows 客户端。这些情况很少见,截至 2014 年,2.0.9 客户端已过时约 7 年。
Windows 将虚假的 /30 分配为本地网络,而非 Windows 将设置真正的点对点配置,将 IP 配对视为与下面描述的 p2p 拓扑相同。
由于客户端的在线网络只是 /30,因此在 net30 中路由到/跨越 VPN 范围变得更加困难,因此必须添加额外的“超网”路由才能到达 VPN 的其余部分,包括其指定 IP 上的服务器。这使得路由变得复杂,也使得理解配置变得更加困难。
在 /etc/openvpn/server/server.conf 中你会看到:
网络拓扑结构
# Should be subnet (addressing via IP) # unless Windows clients v2.0.9 and lower have to # be supported (then net30, i.e. a /30 per client) # Defaults to net30 (not recommended) ;topology subnet
删除“;”以启用子网拓扑。