由于武汉新冠肺炎(COVID-19)的关系,我被困在老家,自从我买了 ac68u 之后基本上就再也没折腾过网。由于长期在家办公,需要好的网络,还好手里有树莓派,还有 nas。只能使用传统技能(时代变化还真实快,一觉醒来工具链全变了)

这次优化网路的经历我准备写一个系列(预计三篇文章:代理,dns,分流增强)。我也不知道能不能写完,也说不定后面两篇文章会咕掉

实际上并没有咕掉,而且还多写了一篇。本系列文章:

  1. 这应该算是第零篇,建议先看这篇 细说 Debian 的网络管理 network/interfaces
  2. 自制旁路网关(一) ——使用clash做代理 (本篇)
  3. 自制旁路网关(一点一) ——增加clash订阅功能
  4. 自制旁路网关(二) ——用unbound和smartdns来优化dns服务
  5. 自制旁路网关(三) ——nftables 来做透明代理

不可否认,我省略了一些过于基础的细节,但本文的确是从我的笔记上摘录的

本系列用到的代码都在 Raspbian GNU/Linux 10 (buster) 上验证过,请放心食用

代理软件使用 clash ,这个软件的特色就是他的分流功能和自动选择节点

# 我是树莓 pi3b 请根据cpu架构选择合适的二进制包
wget https://github.com/Dreamacro/clash/releases/download/v0.17.1/clash-linux-armv7-v0.17.1.gz
gzip -d clash-linux-armv7-v0.17.1.gz
install -Dm755 clash-linux-armv7-v0.17.1 /usr/local/bin/clash

# 把 clash 配置目录放在 /etc 目录下
mkdir /etc/clash/

创建一个本地的 systemd 配置/etc/systemd/system/clash.service

[Unit]
Description=clash service
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/clash -d /etc/clash/
Restart=on-failure

[Install]
WantedBy=multi-user.target
systemctl start clash.service
systemctl enable clash.service

# 然后测试下 socks 代理是否可用
curl --socks5 localhost:7891 google.com

clash 里面其实内置了 dns 服务器的,这个默认是关闭的(clash 配置文件的官方文档写的够细了,只是藏的比较隐蔽)

dns:
  enable: true # set true to enable dns (default is false)
  ipv6: false # default is false
  listen: 0.0.0.0:53
  # default-nameserver: # resolve dns nameserver host, should fill pure IP
  #   - 114.114.114.114
  #   - 8.8.8.8
  enhanced-mode: redir-host # or fake-ip
  # fake-ip-range: 198.18.0.1/16 # if you don't know what it is, don't change it
  fake-ip-filter:
    - '*.lan'
    - localhost.ptlogin2.qq.com

关于 fake-ip 功能,请出门左转去 苏卡卡的 使用 KoolClash 作为代理网关

然后我们再给 clash 加个 UI,这个 webUI 没有提供预编译版本,要自行编译

其实我觉得这个 UI 没啥用

wget https://github.com/Dreamacro/clash-dashboard/archive/v0.3.0.tar.gz
tar -xzf v0.3.0.tar.gz
cd clash-dashboard-0.3.0/
npm install
npm run build

# 把编译结果上传到你的 clash 服务端。。。。因为我是在自己电脑上编译的
tar -cJf - dist/ | ssh <username>@<hostname> 'tar -xJf -'
cp -r dist /etc/clash/dashboard

然后来修改 clash 配置,webUI 相关的有这几项

# RESTful API for clash
external-controller: 127.0.0.1:9090

# 这个地方写编译成静态资源的路径,可以是相对路径或绝对路径 然后用扩展配置的地址 (`external-controller`) + /ui 访问
# 例如:http://127.0.0.1:9090/ui
external-ui: dashboard

# Secret for RESTful API (Optional)
# secret: ""

我个人是不推荐旁路网关自身流量也走透明代理

使用 iptable 来转发流量

iptables -t nat -N CLASH

# 私有 ip 流量不转发,完整的在下面
# 设置的 fake-ip 请注意检查这里
iptables -t nat -A CLASH -d 192.168.0.0/16 -j RETURN

iptables -t nat -A CLASH -p tcp -j REDIRECT --to-ports 7892
iptables -t nat -A PREROUTING -p tcp -j CLASH
# 内部流量不转发给 CLASH 直通
iptables -t nat -A CLASH -d 0.0.0.0/8 -j RETURN
iptables -t nat -A CLASH -d 10.0.0.0/8 -j RETURN
iptables -t nat -A CLASH -d 127.0.0.0/8 -j RETURN
iptables -t nat -A CLASH -d 169.254.0.0/16 -j RETURN
iptables -t nat -A CLASH -d 172.16.0.0/12 -j RETURN
iptables -t nat -A CLASH -d 192.168.0.0/16 -j RETURN
iptables -t nat -A CLASH -d 224.0.0.0/4 -j RETURN
iptables -t nat -A CLASH -d 240.0.0.0/4 -j RETURN

我觉得只写 iptables 版,我会被人耻笑(这和网上随手一搜的垃圾教程有什么两样。对,其实我写的也是垃圾)

来个 nftables 版的 (Raspbian buster 要先安装个 nft 的前端 apt install nftables

先创建一个私有地址的定义文件 /etc/nftables/private.nft

define private_list = {
	0.0.0.0/8,
	10.0.0.0/8,
	127.0.0.0/8,
	169.254.0.0/16,
	172.16.0.0/12,
	192.168.0.0/16,
	224.0.0.0/4,
	240.0.0.0/4
}

再来修改主配置文件 /etc/nftables.conf

#!/usr/sbin/nft -f

include "/etc/nftables/private.nft"

table ip nat {
	chain proxy {
		ip daddr $private_list return
			ip protocol tcp redirect to :7892
	}
	chain prerouting {
		type nat hook prerouting priority 0; policy accept;
		jump proxy
	}
}

然后执行清空设置 nft flush ruleset,让新的设置生效 nft -f /etc/nftables.conf

或者直接这样 sudo sh -c "nft flush ruleset && nft -f /etc/nftables.conf"

然后通过这条命令来看当前 nftables 的状态 sudo nft list ruleset

最后再设置一下开机启动

systemctl enable nftables.service

参考文章

使用 KoolClash 作为代理网关

在 Ubuntu18.04 上使用 clash 部署旁路代理网关(透明代理)

V2Ray 做透明代理

debian10 使用 nftables 替换 iptables