使用树莓派和VLAN交换机组建单臂路由器,通过SS代理上网

目标

创建一个代理网关,所有通过有线或者无线连接通过该网关上网的设备可以:

  • 根据域名判断是走国内的DNS还是国外的DNS,走国外DNS时,通过SS代理请求,防止DNS污染
  • 根据目标IP地址自动选择线路,国外流量都走SS代理

准备

  • 一个SS服务器,Linode或者Digital Ocean上5刀/月的服务器就够用了,SS服务器的架设方法请自行百度。
  • 一个运行最新版本Raspbian的树莓派3B+。理论上任何安装Linux并带有线网卡和无线网卡的设备都可以,只是不同的Linux发行版配置会稍有不同。选择树莓派3B+因为其自带有线和无线网卡,官方的Raspbian运行稳定、内核版本高(ipset在低版本内核中很难安装),缺点是网卡不是千兆的。我在KVM虚拟机中运行的Arch和Orange Pi Zero Plus上运行的Armbian上都成功搭建过类似的网关。
  • 一个支持VLAN Tagging(802.1Q)功能的交换机。我用的是必联BL-SG108M,八口千兆,淘宝卖140,价格公道,功能够用。也可以使用一个USB有线网卡配一个普通的交换机,除VLAN之外,其他配置类似,但这种配置就不是单臂路由器了。

网络拓扑与交换机配置

网络拓扑图

将交换机端口分为两个VLAN,VLAN2和VLAN3(这个设备很诡异,VLAN1不允许删除或修改)。端口1至端口6为VLAN2,端口6至端口8为VLAN3,交换机通过端口1连接家里的路由器,树莓派连接端口6(跨两个VLAN)。此时,空闲的端口2~5为非代理端口,直接走家里的路由器,端口7、8为代理端口,数据会通过树莓派网关进行转发,可以根据需要调整VLAN2与VLAN3的端口数量。

VLAN配置

VLAN Tag配置

在配置交换机前,需要先设置交换机的IP地址为局域网内可用的地址。VLAN划分好后,可以设置端口隔离,但是因为没有找到官方详细的说明,我按照自己的想法将端口1~5和7、8进行了隔离,运行中没有碰到问题,但是VLAN3内的设备无法访问交换机的管理页面。

配置网关

树莓派网关需要运行DNS服务(dnsmasq),代理服务(shadowsocks-libev)及无线AP服务(hostapd)并且需要通过iptables和ipset进行NAT转发。

系统配置

更新系统到最新的状态:

1
2
apt update
apt dist-upgrade -y

安装需要的软件包:

1
apt install -y vim git dnsutils lsof bridge-utils hostapd dnsmasq ipset ntp haveged python-m2crypto shadowsocks-libev

修改时区并启用NTP服务:

1
2
3
rm -rf /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
systemctl enable ntp

网络配置

修改/etc/network/interfaces的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
auto eth0.2
iface eth0.2 inet manual
vlan-raw-device eth0

iface eth0.3 inet manual
vlan-raw-device eth0

auto br0
iface br0 inet manual
bridge_ports eth0.2

auto br1
iface br1 inet manual
bridge_ports eth0.3

这里配置了两个VLAN,号码需要和前边交换机的号码对应,同时建了两个网桥,方便今后添加更多的接入方式,br0为外网,br1为内网。

Raspbian使用dhcpcd来配置网络地址,修改/etc/dhcpcd.conf,在文件最后添加如下内容:

1
2
3
4
5
6
7
8
9
10
denyinterfaces eth0 eth0.2 eth0.3

interface br1
static ip_address=192.168.51.1/24
static routers=192.168.51.1
static domain_name_servers=192.168.51.1
nogateway

interface wlan0
nohook wpa_supplicant

上边配置中用了192.168.51.0/24这个网段,可以根据需要自行调整,nogateway可以保证使用br0为默认网关而不是br1。

SS服务

SS全家桶客户端一共有三个服务:

  • shadowsocks-libev-local:socks5正向代理服务,非代理VLAN中的终端可以通过这个socks5代理上网,配合Proxychains与Switch Omega这类的软件使用。
  • shadowsocks-libev-redir:socks5透明代理服务,所有需要代理的网路流量都会根据iptables规则转发到这个服务的监听端口。
  • shadowsocks-libev-tunnel:本地端口转发工具,这里用于解决dns污染问题。

下边是三个服务的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
cat <<EOT >> /etc/shadowsocks-libev/local.json
{
"server": "SS服务器的IP地址",
"server_port": SS服务端口号,
"local_address": "0.0.0.0",
"local_port": 1080,
"password": "SS服务器的密码",
"timeout": 300,
"method": "aes-256-cfb",
"fast_open": false
}
EOT
cat <<EOT >> /etc/shadowsocks-libev/redir.json
{
"server": "SS服务器的IP地址",
"server_port": SS服务端口号,
"local_address": "0.0.0.0",
"local_port": 1088,
"password": "SS服务器的密码",
"timeout": 300,
"method": "aes-256-cfb",
"mode": "tcp_and_udp",
"fast_open": false
}
EOT
cat <<EOT >> /etc/shadowsocks-libev/tunnel.json
{
"server": "SS服务器的IP地址",
"server_port": SS服务端口号,
"local_address": "0.0.0.0",
"local_port": 15353,
"password": "SS服务器的密码",
"timeout": 300,
"method": "aes-256-cfb",
"tunnel_address": "8.8.8.8:53",
"mode": "tcp_and_udp",
"fast_open": false
}
EOT

停止默认的SS服务并启用上边的三个代理服务:

1
2
3
4
5
systemctl stop shadowsocks-libev
systemctl disable shadowsocks-libev
systemctl enable shadowsocks-libev-local@local
systemctl enable shadowsocks-libev-redir@redir
systemctl enable shadowsocks-libev-tunnel@tunnel

DNS服务

很多的大型网站,在国内外会提供不同的版本,如果我们都用国外的DNS来解析,可能会看到非中国的版本或者被解析到国外的服务器而影响浏览速度。所以需要使用一个列表来指定所有的国内网站走国内的DNS:

1
2
git clone --depth 1 https://github.com/felixonmars/dnsmasq-china-list.git
cp dnsmasq-china-list/accelerated-domains.china.conf dnsmasq-china-list/bogus-nxdomain.china.conf /etc/dnsmasq.d/

接下来配置dnsmasq并启用服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat << EOT >> /etc/dnsmasq.conf
strict-order
no-resolv
no-poll
server=127.0.0.1#15353
interface=br1
dhcp-range=192.168.51.50,192.168.51.100,255.255.255.0,24h
cache-size=10240
local=/ss/
domain=ss
expand-hosts
conf-dir=/etc/dnsmasq.d
EOT

systemctl enable dnsmasq

配置无线AP

配置hostapd:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat <<EOT >> /etc/hostapd/hostapd.conf
interface=wlan0
bridge=br1
driver=nl80211
ssid=SS
hw_mode=g
channel=7
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=ssproxy1234
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
EOT

echo 'DAEMON_CONF="/etc/hostapd/hostapd.conf"' >> /etc/default/hostapd

systemctl enable hostapd

树莓派3B+的无线网卡支持2.4G与5G模式,这里使用的是2.4G模式,以确保最好的兼容性(hw_mode=g),无线网络的名称为SS,密码为ssproxy1234,可以根据需要自行修改,另外也要注意频段最好避开家里路由器的频段,这里的频段是7(channel=7)。

配置iptables与ipset

下载国内IP地址列表并加入ipset:

1
2
3
4
5
6
curl -sL http://f.ip.cn/rt/chnroutes.txt | egrep -v '^$|^#' > chinaip.txt
ipset -N chinaip hash:net
for i in `cat chinaip.txt`; do echo ipset -A chinaip $i >> chinaip.sh; done
bash chinaip.sh
ipset -S > /etc/ipset.chinaip
rm -rf chinaip.txt chinaip.sh

配置iptables规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -t raw -F
iptables -t raw -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -N shadowsocks
iptables -t nat -A shadowsocks -d 0/8 -j RETURN
iptables -t nat -A shadowsocks -d 127/8 -j RETURN
iptables -t nat -A shadowsocks -d 10/8 -j RETURN
iptables -t nat -A shadowsocks -d 169.254/16 -j RETURN
iptables -t nat -A shadowsocks -d 172.16/12 -j RETURN
iptables -t nat -A shadowsocks -d 192.168/16 -j RETURN
iptables -t nat -A shadowsocks -d 224/4 -j RETURN
iptables -t nat -A shadowsocks -d 240/4 -j RETURN
iptables -t nat -A shadowsocks -d SS服务器地址 -j RETURN
iptables -t nat -A shadowsocks -m set --match-set chinaip dst -j RETURN
iptables -t nat -A shadowsocks -p tcp -j REDIRECT --to-ports 1088
iptables -t nat -A shadowsocks -p udp ! --dport 53 -j REDIRECT --to-ports 1088
iptables -t nat -A OUTPUT -p tcp -j shadowsocks
iptables -t nat -A OUTPUT -p udp ! --dport 53 -j shadowsocks
iptables -t nat -A PREROUTING -p tcp -s 192.168.51/24 -j shadowsocks
iptables -t nat -A PREROUTING -p udp ! --dport 53 -s 192.168.51/24 -j shadowsocks
iptables -t nat -A POSTROUTING -s 192.168.51/24 -j MASQUERADE

iptables-save > /etc/iptables.up.rules

注意替换上边命令中的“SS服务器地址”。

当网络连接启动时,自动加载以上规则:

1
2
3
4
5
6
7
cat <<EOT >> /etc/network/if-pre-up.d/iptables
#!/bin/sh
/sbin/ipset -R < /etc/ipset.chinaip
/sbin/iptables-restore < /etc/iptables.up.rules
EOT

chmod +x /etc/network/if-pre-up.d/iptables

调整内核参数

调整内核,允许转发并参考SS的文档做相应的优化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
cat <<EOT >> /etc/sysctl.d/50-ss.conf
# max open files
fs.file-max = 1024000
# max read buffer
net.core.rmem_max = 67108864
# max write buffer
net.core.wmem_max = 67108864
# default read buffer
net.core.rmem_default = 65536
# default write buffer
net.core.wmem_default = 65536
# max processor input queue
net.core.netdev_max_backlog = 4096
# max backlog
net.core.somaxconn = 4096

# resist SYN flood attacks
net.ipv4.tcp_syncookies = 1
# reuse timewait sockets when safe
net.ipv4.tcp_tw_reuse = 1
# turn off fast timewait sockets recycling
net.ipv4.tcp_tw_recycle = 0
# short FIN timeout
net.ipv4.tcp_fin_timeout = 30
# short keepalive time
net.ipv4.tcp_keepalive_time = 1200
# outbound port range
net.ipv4.ip_local_port_range = 10000 65000
# max SYN backlog
net.ipv4.tcp_max_syn_backlog = 4096
# max timewait sockets held by system simultaneously
net.ipv4.tcp_max_tw_buckets = 5000
# TCP receive buffer
net.ipv4.tcp_rmem = 4096 87380 67108864
# TCP write buffer
net.ipv4.tcp_wmem = 4096 65536 67108864
# turn on path MTU discovery
net.ipv4.tcp_mtu_probing = 1

# for high-latency network
# net.ipv4.tcp_congestion_control = cubic
# forward ipv4
net.ipv4.ip_forward = 1
EOT

cat <<EOT >> /etc/security/limits.conf
* soft nofile 512000
* hard nofile 1024000
EOT

echo "ulimit -SHn 1024000" >> /etc/profile

sysctl --system

ulimit -n 512000

总结

全部配置完成后,重启树莓派,终端通过网线连接交换机的7、8口,或者连接名称为SS的无线网络,都可以自动的代理上网了。