Skip to content

bypassLan 逻辑错误地将私有局域网流量路由到 VPN 中 #63

Description

@HeXis-YS

描述

当启用 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 支持)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions