在 EdgeRouter Lite 上实现科学上网

从淘宝上买了一个 Ubiquiti EdgeRouter Lite,mips 平台的路由器,提供 3 个 1000Mbps 网络接口、基于 Debian 和 Vyatta 的 EdgeOS 操作平台,最重要的是有 4GB 的内置存储以及 512MB RAM,这使得此款机器的性能远远超过那些刷了 OpenWRT 的家用无线路由。

为了让路由正常运转,首先是配置基本的网络服务,这包括:

  • 配置 eth0 上的 PPPoE 拨号上网
  • 配置 eth1 和 eth2,添加到 bridge br0,并在 br0 上配置局域网 IP
  • 配置 br0 上的 DHCP 服务,实现 LAN 机器自动获取 IP
  • 配置 br0 上的 DNS Forward,在局域网网关上转发 DNS 请求
  • 在 PPPoE 接口上配置 NAT 服务,使 LAN 机器能访问外网

另外,为了支持无线网络,需要接入一个无线 AP,一般来说都是用家用无线路由器实现的,具体要注意以下几点:

  • 单独配置无线路由器,关掉局域网上的 DHCP 服务
  • 配置无线路由器的 LAN 端 IP,使之与 EdgeRouter Lite 的 br0 不在一个网段(尽量避免冲突)
  • 用网线连接 EdgeRouter Lite 的 LAN 口和无线路由器的 LAN 口

以上步骤照着说明和经验,很快可以完成,这样就实现了最基本的基于 NAT 的家庭网络服务。

接下来,为了科学上网(*翻*墙*),需要配置 tunnel 和额外的路由。

关于 tunnel,经仔细研究,发现可以用传统的 gre, sit 或者 ipip 隧道,但这些服务有一个缺点就是不能很好地支持 PPPoE 获取的动态 IP,虽然经过搜索,有人已经提供了利用 SSH 远程更新的思路和方案,但是在 EdgeOS 的 vbash shell 里没有直接支持,必须绕过上层的 EdgeOS 直接在 Linux OS 里写脚本,这样未免显得略微麻烦。EdgeOS 里倒是直接提供了 OpenVPN 的选项,这样一来直接用 OpenVPN 建立 site-to-site tunnel 倒是一个很直接的方案。

服务器端是一个米国的 VPS,跑着 FreeBSD 9.2-RELEASE,先用 ports 装上 security/openvpn,然后建立服务端,配置文件如下,非常简单:

# use tun device, for a layer-3 tunnel
dev tun
# tunnel over udp for better performance
proto udp
# config tunnel end-point ip for both local and remote
ifconfig 10.8.0.1 10.8.0.2
# add route to remote network
route 10.10.112.0 255.255.255.0 10.8.0.2
# use pre-shared static key since tls negotiation is interrupted
# by the great firewall
secret static.key
# avoid using default port
port 31194

verb 3
# enable lzo compression
comp-lzo

log-append /var/log/openvpn.log
# persist tun device and key
persist-tun
persist-key
# run as unprivileged user
user nobody
group nogroup

接下来是 EdgeRouter Lite 上的 OpenVPN 配置,如下

set interfaces openvpn vtun0 local-address 10.8.0.2
set interfaces openvpn vtun0 local-port 31194
set interfaces openvpn vtun0 mode site-to-site
set interfaces openvpn vtun0 openvpn-option '--comp-lzo '
set interfaces openvpn vtun0 remote-address 10.8.0.1
set interfaces openvpn vtun0 remote-host XXX.XXX.XXX.XXX
set interfaces openvpn vtun0 remote-port 31194
set interfaces openvpn vtun0 shared-secret-key-file /config/auth/static.key

这样隧道就建好了,通过  show interfaces 命令可以查看到,也可以 ping 通 tunnel 的远端地址,说明隧道连接是成功的。

为了把隧道当做出口,需要在远端配置 NAT 服务,对于 FreeBSD 来说,用 pf 或者 ipfw 都很容易做到。以 pf 为例,只需要一句配置语句:

nat on $external_if from { tun0:peer, $remote_subnet } to any -> $external_if

随后在 EdgeRouter Lite 上配置路由,使得访问 Google 和 Facebook 的包通过隧道出去。这里可以用策略路由,也可以用简单的静态路由来实现。关键是找到 Google 和 Facebook 的服务器 IP 地址段。

Google 的 IP 地址段非常好找,在 Google Help 上提到了可以通过 Google 的 SPF 记录来查找。简单地在 cmd 里运行 nslookup -type=txt _spf.google.com 8.8.4.4  ,可以看到有三个 netblock,再用 nslookup 查询一下,Google 的 IP 地址段就出来了。(目前第一个记录是 ipv4 地址,第二个是 ipv6 地址,第三个为空)

C:\Users\Xiaoding>nslookup -type=txt _netblocks.google.com 8.8.4.4
Server:  google-public-dns-b.google.com
Address:  8.8.4.4

Non-authoritative answer:
_netblocks.google.com   text =

        "v=spf1 ip4:216.239.32.0/19 ip4:64.233.160.0/19 ip4:66.249.80.0/20 ip4:7
2.14.192.0/18 ip4:209.85.128.0/17 ip4:66.102.0.0/20 ip4:74.125.0.0/16 ip4:64.18.
0.0/20 ip4:207.126.144.0/20 ip4:173.194.0.0/16 ~all"

Facebook 的 IP 地址段官方也提供了相应的列表,不过方式与 Google 略有不同,是发布在 Facebook developers 网站上的,在 Facebook content sharing best practice 这篇文章中直接列出了当前的 IP 地址段,也提供了命令行方式通过查询 Facebook 的自治系统(AS)路由广播来查询。

IP whitelisting

Your engineers can allow the following IP addresses access to pages that would otherwise be inaccessible to the public.

31.13.24.0/21
31.13.64.0/18
66.220.144.0/20
69.63.176.0/20
69.171.224.0/19
74.119.76.0/22
103.4.96.0/22
173.252.64.0/18
204.15.20.0/22
2401:db00::/32
2620:0:1c00::/40
2a03:2880::/32
Please note that these IP ranges can and do change regularly, so you should periodically run the following command to receive an updated list

whois -h whois.radb.net — ‘-i origin AS32934’ | grep ^route

在 EdgeRouter Lite 上配置好路由后,就可以成功地通过隧道实现“科学上网”了。

ubnt@EdgeRouterLite:~$ show firewall modify   GOOGLE_ROUTE

IPv4 Modify Firewall "GOOGLE_ROUTE":

 Active on (br0,IN)

rule  action   proto     packets  bytes
----  ------   -----     -------  -----
1     modify   all       30128    1699704
  condition - match-DST-NTWRK-GROUP Google

2     modify   all       1119     175999
  condition - match-DST-NTWRK-GROUP Facebook

10000 accept   all       379763   22430120