描述
当启用 prefs.bypassLan 时,当前实现会先添加私有网络(RFC1918)的路由,然后再添加默认路由:
|
if (prefs.bypassLan) { |
|
addRoute("10.0.0.0", 8) |
|
addRoute("172.16.0.0", 12) |
|
addRoute("192.168.0.0", 16) |
|
} |
|
if (prefs.ipv4) { |
|
addAddress(prefs.tunnelIpv4Address, prefs.tunnelIpv4Prefix) |
|
addRoute("0.0.0.0", 0) |
|
prefs.dnsIpv4.takeIf { it.isNotEmpty() }?.also { addDnsServer(it) } |
|
} |
然而,根据 IP 路由的最长前缀匹配原则(Longest Prefix Match)
If multiple routes match the packet destination, route with the longest prefix takes precedence.
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
都比 0.0.0.0/0 更具体,因此会优先匹配。
这会导致局域网流量被明确路由到 VPN 中,与“绕过局域网(bypass LAN)”的预期行为相矛盾。
预期行为
当启用 bypassLan 时,私有局域网流量(RFC1918 地址段)不应通过 VPN。
实际行为
由于显式添加了私有地址段的路由,局域网流量被导入 VPN 隧道中,无法绕过 VPN。
问题根源
在 Android 的 VpnService.Builder 中:
addRoute() 的含义是指定哪些流量应通过 VPN。
未添加到路由表的流量才会绕过 VPN。
当前实现通过显式添加 RFC1918 地址段路由,实际上强制局域网流量进入 VPN,逻辑上与 bypassLan 的语义相反。
建议修复方案
当启用 bypassLan 时,不应添加私有网络路由。
可以考虑:
-
在全局代理(Full Tunnel)模式下,仅添加默认路由 0.0.0.0/0
-
在需要绕过局域网时,不将 RFC1918 地址段添加至 VPN 路由
-
或者使用更精细的分流策略(例如 excludeRoute(),如 API 支持)
描述
当启用
prefs.bypassLan时,当前实现会先添加私有网络(RFC1918)的路由,然后再添加默认路由:SimpleXray/app/src/main/kotlin/com/simplexray/an/service/TProxyService.kt
Lines 298 to 302 in f13c327
SimpleXray/app/src/main/kotlin/com/simplexray/an/service/TProxyService.kt
Lines 306 to 310 in f13c327
然而,根据 IP 路由的最长前缀匹配原则(Longest Prefix Match)
10.0.0.0/8172.16.0.0/12192.168.0.0/16都比
0.0.0.0/0更具体,因此会优先匹配。这会导致局域网流量被明确路由到 VPN 中,与“绕过局域网(bypass LAN)”的预期行为相矛盾。
预期行为
当启用 bypassLan 时,私有局域网流量(RFC1918 地址段)不应通过 VPN。
实际行为
由于显式添加了私有地址段的路由,局域网流量被导入 VPN 隧道中,无法绕过 VPN。
问题根源
在 Android 的 VpnService.Builder 中:
addRoute() 的含义是指定哪些流量应通过 VPN。
未添加到路由表的流量才会绕过 VPN。
当前实现通过显式添加 RFC1918 地址段路由,实际上强制局域网流量进入 VPN,逻辑上与 bypassLan 的语义相反。
建议修复方案
当启用 bypassLan 时,不应添加私有网络路由。
可以考虑:
在全局代理(Full Tunnel)模式下,仅添加默认路由
0.0.0.0/0在需要绕过局域网时,不将 RFC1918 地址段添加至 VPN 路由
或者使用更精细的分流策略(例如
excludeRoute(),如 API 支持)