在树莓派上使用ss和iptables实现fq功能

时间:2021-07-12 20:50:32

VPS购买地址

以下所有叙述均来自互联网上已有文章, 本人只做收集和整理工作.

写在前面的话: 一直想把家里的树梅派做成一个fq路由器, 期间也看过很多GitHub上的开源项目: Redsock, ChinaDNS等等, 都感觉不怎么尽如人意, 而且OpenWRT用起来也不怎么顺手. 最终还是回到最简单的Linux, 使用iptables, ss-libev和国家IP段轻轻松松搞定了. 个人觉得这是目前网上最简单的方案了.

1. 所需工具: 一台q外的vps, raspbian(打开转发功能), *-libev(这个基于C的版本支持ss-tunnel, 可用来UDP转发), IP地理位置库(用到了里面的不同国家的IP地址段), DNSMasq(用来接替家里的磊科Q3充当DNS和DHCP服务器).

2. 安装*-libev, 根据官方文档, 你可以添加*源, 通过apt-get的方式直接安装, 但是由于这个源的地址在q外, 所以此法行不通, 只能通过编译源代码的方式进行. 过程比较顺利, 唯一要注意的是编译之前需要安装libssl-dev, libpcre3-dev, 然后依次执行./configure --disable-documentation, make, make install即可.

3. 安装完之后在/etc/rc.local中添加如下两行代码(具体参数意义可以通过--help获得):

sudo ss-redir -c /etc/*-libev/config.json -f /var/run/ss-redir.pid &
 -L 8.8.4.4: -u -f /var/run/ss-tunnel.pid &     #让5353端口产生的流量走隧道, 5353端口干什么用的请见下文

附上/etc/*-libev/config.json

{
    "server":"1.2.3.4",
    ,
    "local_address":"0.0.0.0",
    ,
    "password":"XXXXXXX",
    ,
    "method":"aes-256-cfb"
}

4. 接下来就要对iptables进行设置了.

4.1 首先创建一个新链, 将私有和你vps的地址都执行RETURN动作, 然后将剩下所有通过树莓派的数据包的目的端口重定向到本机1080端口(即local_port), 如下:

稍稍解释一下这一段iptables规则(这里只涉及到nat表)

iptables -t nat -N * #首先创建一条新链
iptables -t nat -A PREROUTING -p tcp -j * #很多文章把这条放在最后并称为"Apply the rule", 但是我觉得把它放在第二条并称为"在PRE-ROUTING时先reference SS链"更易理解
iptables -t nat -A OUTPUT -p tcp -j * #让路由器本身的应用也能够fq
iptables -t nat -A * -d your_vps_ip -j RETURN #若遇到目的地址是自己的vps, 局域网私有地址, 中国IP段的话, 回到主链(不继续在SS链中向下执行)
iptables -t nat -A * -d 0.0.0.0/8 -j RETURN
iptables -t nat -A * -d 10.0.0.0/8 -j RETURN
iptables -t nat -A * -d 127.0.0.0/8 -j RETURN
iptables -t nat -A * -d 169.254.0.0/16 -j RETURN
iptables -t nat -A * -d 172.16.0.0/12 -j RETURN
iptables -t nat -A * -d 192.168.0.0/16 -j RETURN
iptables -t nat -A * -d 224.0.0.0/4 -j RETURN
iptables -t nat -A * -d 240.0.0.0/4 -j RETURN
iptables -t nat -A * -p tcp -j REDIRECT --to-ports 1080 #若目的地址不在前面那些范围内, 则将去往目的地址的流量转发到本机1080端口

4.2 参见我另一篇博文里面的办法获得中国所有IP地址段, 然后编辑成如下模式(注意, 此处我用了插入-I, 而非追加-A, 是因为你要确保这些规则必须在4.1的倒数第一条规则之前, 换句话说就是不将国内和私有局域网的流量转发到1080端口):

iptables -t nat -I * -d  -j RETURN

4.3 导入所有规则之后, 使用iptables-save > /home/pi/smart.iptables命令生成配置文件, 然后在/etc/rc.local中加入sudo iptables-restore < /home/pi/smart.iptables以实现每次开机自动加载所有规则.

5. 客户端的设置. 客户端的网关和DNS需要改成树莓派的IP地址.

6. 测试. 需要测试两个地方: 1. DNS是否被污染; 2. 国内国外地址是否被分流.

6.1 DNS是否被污染可以使用阿里巴巴的DNS解析一下被q网站, 然后再用你的DNS解析一下, 如果结果一样则说明你的配置没有成功, 反之则成功.

6.2 可以通过http://ip138.com/和https://www.whatismyip.com/来检测国内国外流量是否被分流.

7. 最后一步设置DNSMasq, 关闭DNS, 开启DHCP. 这一步的DNS设置是后加的, 因为我在实际使用中发现, 使用Google DNS解析国内诸如JD, taobao这样的网站会得到它们的国外IP, 这直接导致浏览体验非常差. 所以我让国内域名通过树莓派自身的dns-nameservers中设置的DNS服务器解析, 国外域名通过本机5353端口再转发到Google DNS进行解析.

7.1 在/etc/rc.local中加入sudo dnsmasq -C /etc/dnsmasq.conf (如果没有该文件可以通过这里下载)

#### DNS ####
port=53 #启用DNSMasq的DNS功能
conf-dir=/etc/dnsmasq.d #在这个目录下维护一张serverlist.conf列表, 将指定的域名通过本机的5353端口向国外DNS转发查询, 这样做的目的是让q外的地址不受DNS污染, 国内的地址可以使用国内DNS的CDN加速
listen-address=192.168.1.2,127.0.0.1
cache-size=1024
no-hosts
resolv-file=/etc/resolv.dnsmasq.conf  #nameserver 223.6.6.6

#### DHCP ####
dhcp-leasefile=/var/lib/misc/dnsmasq.leases
dhcp-range=192.168.1.101,192.168.1.150,12h
dhcp-option=1,255.255.255.0
dhcp-option=3,192.168.1.2
dhcp-option=6,192.168.1.2

serverlist.conf (更多网址按照自己需要添加)
server=/bbc.com/
server=/google.com/

2016年3月12日更新:

以上的方案使用了很长一段时间了,但最近发现一个问题:DNS对于q外的域名解析有问题。最直观的表现就是Chrome第一次无法打开被q网页,报DNS无法解析的错误,但是过几秒钟再去刷新就可以打开了。不知道为什么,希望谁能解释一下。不过解决办法倒是找到了,附在下面。

使用的工具:unbound(用来将DNS请求通过TCP传输)

1. 安装unbound. 我是编译安装1.5.8版本,开始之前请安装libexpat1-dev,然后./configure && make && make install

2. 安装完后配置文件在/usr/local/etc/unbound/unbound.conf,修改其中的几项内容

interface: 127.0.0.1
interface: 192.168.1.2
port:
tcp-upstream: yes
forward-zone:
    name: "."
    forward-addr: 8.8.8.8
    forward-first: no

3. 在运行unbound之前还需要通过useradd unbound创建用户,否则无法执行

4. 修改/etc/rc.local,设置其为开机启动,同时注释掉通过ss-tunnel的方式

sudo unbound -c /usr/local/etc/unbound/unbound.conf
#  -L  -u -f /var/run/ss-tunnel.pid &

参考:

https://github.com/*/*-libev

https://github.com/1265578519/pac