利用 Surge 访问局域网

Surge 其实是一个带隧道的三层静态路由表。

怎么理解上面这一句话呢?Surge 的简单用法就是作为一个代理软件,附带网络调试功能,但实际上 Surge 支持多种代理,并且可以为不同的域名和 IP 编写复杂的规则,有点类似编写静态路由,而且 Surge 支持为域名和 IP 编写不同的规则,所以说比静态路由功能更加强大。

回到主题,为了在公网轻松访问家里的局域网,我做了下面这些微小的工作。

  1. 利用公网 IP 和动态域名,在外网可以获取到家里的公网地址。
  2. 使用 ss-server 在路由器搭建代理。注意,直接把内网端口暴露在公网是极其危险的,即便是应用自带了有身份验证。为了保证不被暴力破解,我们需要用跳板访问内网,VPN 是常见的方法,但是配置太繁琐,一般来说 Shadowsocks 的对称加密已经足够安全了。
  3. 在路由器建立起代理,利用 Surge 编写规则,将特定的域名转发到访问局域网,例如我用了下面这一条规则:DOMAIN-SUFFIX,home,Home,force-remote-dns。这样,所有 *.home 都会转发给对应的代理进行域名解析,然后发起请求。

在路由器的 hosts 文件将域名解析到局域网 IP,例如是

# Home
10.0.0.1 router.home
10.0.0.249 mini.home

效果如下

在这套体系中,有两个地方是需要注意的

  1. 许多应用都会以 Raw TCP 的方式进行连接,例如是 SSH,此时不遵循系统代理配置,而 Surge 处理 Raw TCP 是通过自身的 Surge TUN,此时 App 会进行 DNS 本地解析并直接建立 TCP 连接。所以需要添加 force-remote-dns ,让 Surge 通过 Fake IP 的方式强制转发 Raw TCP。
  2. ss-server 为了性能的考虑,并没有使用 gethostbyname() 而是 libudns,所以实际上并不会从 /etc/hosts 读取 hosts 解析。在这里,我是通过 dnsmasq 去完成的。