我们总是因为某些不可描述的原因需要使用网络魔法通道,传统的方式需要在终端设备上安装专门软件或者设置代理,前者有时候稍显麻烦,后者有的软件不支持这样的方式。在经过多方资料查找后,得知了可以通过树莓派搭建透明代理(部分人文章也称其为旁路由)的办法,用这个办法,通过iptables的转发可以让树莓派充当整个局域网的网关,在树莓派上通过clash进行流量的分流从而达到代理的目的。然而在具体操作中由于版本等原因具有诸多坑点,难以设置成功或成功后不稳定,本文在整理前人总结的基础上,尽可能避开他们。
1 准备工作
1.1 设备准备
- 树莓派4B或3B(我因为在运行其他东西使用的是RAM 8G版本,但是实际上RAM 1G以上应该都行);
- 路由器和光猫;
- 宽带;
- 适量网线。
1.2 软件准备
- 节点订阅地址或者节点列表地址加转换器
- 路由器正确配置宽带连接;
- 树莓派安装RaspberryPi OS 64bit Beta版本(建议使用无图形接口版本),32Bit版本也行但是速度似乎会慢一些,大内存也没办法充分利用;
- 连接树莓派到路由器的LAN口(本文使用有线连接到eth0接口,如需无线连接请自行修改相应配置文件)。
1.3 网络结构
初始的网络结构如下:
树莓派 --> 路由器LAN --> 光猫 --> Internet
其他设备 --> 路由器LAN --> 光猫 --> Internet
要实现的目标:
其他设备(Domestic连接) --> 树莓派(分流) ---直连---> InnerInternet
其他设备(Abroad连接) --> 树莓派(分流) ---隧道---> 代理机 --> OutterInternet
1.4 基本说明
- 本文着重于透明代理本身,不会对细枝末节的终端使用、SSH配置等做说明,仅做简要提示,如果不明白请自行查阅资料。
- 命令前加sudo为root权限运行。
- 首次启动请通过SSH终端连接树莓派,进行基本用户名密码设置,并扩展树莓派文件系统。
- 本文默认树莓派IP为192.168.1.30
2 安装和配置 Clash
先进行clash和网页面板的安装和基本配置[1]。 访问 https://github.com/Dreamacro/clash 查看有关 Clash 的信息。下载armv8(64位)或者armv7(32位)版本到/home/pi/app/clash
中,可以直接通过wget命令下载也可以下载后使用WinSCP上传。 上传后通过chmod +x clash-linux-armv8
赋予运行权限。 通过./clash
运行来自动创建配置文件目录和配置文件。 接下来进入配置文件目录cd ~/.config/clash
创建预配置文件parsers.yaml
,注意该parsers.yaml
最后会被添加到你的订阅配置文件开头,如果有冲突请自行调整内容。
authentication: #socks5代理用户配置(如不需要可以删除)
- "用户名:密码"
dns:
enable: true
ipv6: false
listen: 192.168.1.30:53
enhanced-mode: redir-host #也可以选择fake-ip
fake-ip-range: 192.18.0.1/16
default-nameserver:
#用于解析下面的DoH和DoT的DNS
- 223.5.5.5
- 223.6.6.6
- 119.29.29.29
- 182.254.116.116
nameserver:
# 不可信但速度快的DNS
- https://doh.pub/dns-query
- https://dns.alidns.com/dns-query
- tls://rubyfish.cn:853
fallback:
# 可信DNS(根据Clash工作原理不填问题也不大)
- https://doh.opendns.com/dns-query
- tls://1.1.1.1:853
- tls://dns.google:853
fallback-filter:
geoip: true
ipcidr:
- 240.0.0.0/4
hosts:
rubyfish.cn: 175.24.154.79
dns.pub: 175.24.219.66
doh.pub: 175.24.219.66
dns.google: 8.8.4.4
dns.alidns.com: 223.5.5.5
doh.opendns.com: 146.112.41.2
tproxy-port: 7893
external-controller: 0.0.0.0:9090
external-ui: clash-dashboard
secret: "ui访问密码"
接下来安装clash-dashboard以便通过浏览器查看和管理运行状况。
git clone https://github.com/Dreamacro/clash-dashboard.git
git checkout -b gh-pages origin/gh-pages
最后我们编写systemd作为clash的守护进程[2]。 先进入clash安装目录cd ~/app/clash
创建文件start-clash.sh
用于启动clash
#!/bin/bash
#设置Clash目录
CLASH_DIR=/home/pi/.config/clash
#启动Clash
/home/pi/app/clash/clash-linux-armv8 -d $CLASH_DIR
创建stop-clash.sh
用于停止clash
#!/bin/bash
pkill -9 clash
创建update-clash.sh
用于更新clash,本文将更新和启动停止分开,是因为本文采用的是爬虫爬取的免费节点,如果你有稳定节点,也可以采取将更新的内容合并到开始或停止脚本中。注意,请不要一次性添加过多节点以免程序卡死。通过适当的订阅转换器会让你的订阅更适合你。
#!/bin/bash
CLASH_DIR=/home/pi/.config/clash
CLASH_URL=你的订阅地址
curl -L -o ${CLASH_DIR}/config.yaml ${CLASH_URL}
if [ $? -eq 0 ]; then
sed -i /external-controller/d ${CLASH_DIR}/config.yaml
cat ${CLASH_DIR}/parsers.yaml > ${CLASH_DIR}/config.tmp
cat ${CLASH_DIR}/config.yaml >> ${CLASH_DIR}/config.tmp
mv ${CLASH_DIR}/config.tmp ${CLASH_DIR}/config.yaml
fi
以root权限创建文件/lib/systemd/system/clash.service
为以下内容:
[Unit]
Description=A rule based proxy in Go.
After=network.target nss-lookup.target
[Service]
WorkingDirectory=/home/pi/.config/clash
Type=simple
User=root
Restart=on-abort
ExecStart=/home/pi/app/clash/start-clash.sh
ExecStop=/home/pi/app/clash/stop-clash.sh
[Install]
WantedBy=multi-user.target
保存后运行systemctl enable clash & systemctl start clash
来运行clash并添加自启动。 今后可以使用systemctl status clash
查看clash运行状态。 根据我们之前的配置,你也可以使用http://192.168.1.30:9090/ui
来访问网页面板。
3 系统的配置
3.1 静态IP配置
常见的配置静态IP是使用/etc/dhcpcd.conf
文件,但是我配置完整设置后,发现在某些设备连接时正常,另一些设备连接后使用时dhcpcd检测到IP地址冲突,然后自行更换IP地址,这样会产生问题,后面上网查了发现可能是这个系统版本的dhcpd有问题[3],于是我们禁用dhcpcd,改用systemd-networkd配置静态IP。 首先创建配置文件/etc/systemd/network/eth0.network
为以下内容
[Match]
Name=eth0
[Network]
Address=192.168.1.30/24
Gateway=192.168.1.1
DNS=223.5.5.5
DNS=119.29.29.29
然后运行systemctl stop dhcpcd & systemctl disable dhcpcd
关闭dhcpcd服务,然后紧接着开启systemd-networkd服务systemctl enable systemd-networkd & systemctl start systemd-networkd
。 此时树莓派SSH可能会发生中断,重新连接即可。
3.2 内核参数优化设置
树莓派在作为代理转发时候,会产生大量的socks连接,而默认情况下系统允许打开的文件数量极其有限,我们先修改ulimit中的nofile参数,来解除资源限制[4]。修改文件/etc/security/limits.conf
,加入以下内容到末尾
* soft nofile 262144
root soft nofile 262144
* hard nofile 393216
root hard nofile 393216
然后我们配置内核参数,开启内核的转发功能,使用bbr拥塞算法对网络进行优化[5],修改/etc/sysctl.conf
为以下内容
#
# /etc/sysctl.conf - Configuration file for setting system variables
# See /etc/sysctl.d/ for additional system variables.
# See sysctl.conf (5) for information.
#
#kernel.domainname = example.com
# Uncomment the following to stop low-level messages on console
kernel.printk = 3 4 1 3
##############################################################3
# Functions previously found in netbase
#
# Uncomment the next two lines to enable Spoof protection (reverse-path filter)
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1
# Uncomment the next line to enable TCP/IP SYN cookies
# See http://lwn.net/Articles/277146/
# Note: This may impact IPv6 TCP sessions too
net.ipv4.tcp_syncookies=1
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
# Enabling this option disables Stateless Address Autoconfiguration
# based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1
###################################################################
# Additional settings - these settings can improve the network
# security of the host and prevent against some network attacks
# including spoofing attacks and man in the middle attacks through
# redirection. Some network environments, however, require that these
# settings are disabled so review and enable them as needed.
#
# Do not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0
#net.ipv6.conf.all.accept_redirects = 0
# _or_
# Accept ICMP redirects only for gateways listed in our default
# gateway list (enabled by default)
# net.ipv4.conf.all.secure_redirects = 1
#
# Do not send ICMP redirects (we are not a router)
#net.ipv4.conf.all.send_redirects = 0
#
# Do not accept IP source route packets (we are not a router)
#net.ipv4.conf.all.accept_source_route = 0
#net.ipv6.conf.all.accept_source_route = 0
#
# Log Martian Packets
#net.ipv4.conf.all.log_martians = 1
#
###################################################################
# Magic system request Key
# 0=disable, 1=enable all
# Debian kernels have this set to 0 (disable the key)
# See https://www.kernel.org/doc/Documentation/sysrq.txt
# for what other values do
#kernel.sysrq=1
###################################################################
# Protected links
#
# Protects against creating or following links under certain conditions
# Debian kernels have both set to 1 (restricted)
# See https://www.kernel.org/doc/Documentation/sysctl/fs.txt
#fs.protected_hardlinks=0
#fs.protected_symlinks=0
vm.swappiness=60
net.ipv4.tcp_congestion_control=bbr
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_frto = 2
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_fastopen = 3
#ADDON
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 8192 87380 16777216
net.ipv4.udp_rmem_min = 16384
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.ipv4.tcp_wmem = 8192 65536 16777216
net.ipv4.udp_wmem_min = 16384
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 16384
net.core.dev_weight = 64
net.core.optmem_max = 65535
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_max_orphans = 16384
net.ipv4.tcp_orphan_retries = 0
net.ipv4.ipfrag_low_thresh = 196608
net.ipv6.ip6frag_low_thresh = 196608
net.ipv4.ipfrag_high_thresh = 262144
net.ipv6.ip6frag_high_thresh = 262144
net.unix.max_dgram_qlen = 50
net.ipv4.neigh.default.gc_thresh3 = 2048
net.ipv4.neigh.default.gc_thresh2 = 1024
net.ipv4.neigh.default.gc_thresh1 = 32
net.ipv4.neigh.default.gc_interval = 30
net.ipv4.neigh.default.proxy_qlen = 96
net.ipv4.neigh.default.unres_qlen = 6
net.ipv4.tcp_ecn = 1
net.ipv4.tcp_reordering = 3
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.route.flush = 1
net.ipv6.route.flush = 1
保存后运行systemctl -p
使其生效。
3.2 iptables转发配置
iptables用于配置相应的转发功能[6],同时通过fwmark防止网络环路,同时由于TProxy同时支持TCP和UDP转发,本配置文件两者转发均开启,请根据需要取用。
以下命令请先直接运行,然后再添加到/etc/rc.local
以便开机自动运行,请不要使用netfilter-persistent和iptables-persistent,根据我测试似乎工作不太正常。
# ROUTE RULES
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
# CREATE TABLE
iptables -t mangle -N clash
# RETURN LOCAL AND LANS
iptables -t mangle -A clash -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 169.254.0.0/16 -j RETURN
iptables -t mangle -A clash -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A clash -d 192.168.50.0/16 -j RETURN
iptables -t mangle -A clash -d 192.168.9.0/16 -j RETURN
iptables -t mangle -A clash -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A clash -d 240.0.0.0/4 -j RETURN
# FORWARD ALL
iptables -t mangle -A clash -p udp -j TPROXY --on-port 7893 --tproxy-mark 1
iptables -t mangle -A clash -p tcp -j TPROXY --on-port 7893 --tproxy-mark 1
# REDIRECT
iptables -t mangle -A PREROUTING -j clash
至此整个透明代理配置完毕。将网络下其他设备的默认网关和DNS设为树莓派即可,也可以直接调整路由器的DHCP服务器设置。
4 缺陷与不足
- 通过该方法配置的iptables转发,树莓派本身流量是不走代理的,如果需要使某些或者全部应用走代理,需要配合cgroup使用,直接设置OUTPUT链将会产生网络环路。
- 在使用自动生成节点时,不要一次性加入太多,否则可能会使网页面板卡死,甚至整个树莓派死机。
- Clash使用root权限运行,可能会有安全隐患,这主要是由于53端口绑定的需要。如果必要的话,可以使其绑定其他高位端口,然后通过iptables将53端口转发到那个端口。
Reference
[1] 在 Raspberry Pi 上运行 Clash 作为透明代理 – Tech Cafe. (2021). Retrieved 18 September 2021, from https://cherysunzhang.com/2020/05/deploy-clash-as-transparent-proxy-on-raspberry-pi/
[2] Clash For Linux自动更新订阅配置 – 翰林木子的笔记本. (2021). Retrieved 18 September 2021, from https://ytlee.cn/2021/04/clash-for-linux-automatically-renews-the-subscription-link/
[3] DHCPCD fails again, with DAD detection this time - Raspberry Pi Forums. (2021). Retrieved 18 September 2021, from https://www.raspberrypi.org/forums/viewtopic.php?t=302782
[4] linux中/etc/security/limits.conf配置文件说明 - 云+社区 - 腾讯云. (2021). Retrieved 18 September 2021, from https://cloud.tencent.com/developer/article/1403636
[5] 软路由的网络性能优化 - Starx\'s Home. (2021). Retrieved 18 September 2021, from https://www.starx.ink/archives/%E8%BD%AF%E8%B7%AF%E7%94%B1%E7%9A%84%E7%BD%91%E7%BB%9C%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/
[6] Clash 作为网关的透明代理. (2021). Retrieved 18 September 2021, from https://www.wogong.net/blog/2020/11/clash-transparent-proxy