基于树莓派官方64位系统的Clash透明代理扶Wall及避坑指南

基于树莓派官方64位系统的Clash透明代理扶Wall及避坑指南

我们总是因为某些不可描述的原因需要使用网络魔法通道,传统的方式需要在终端设备上安装专门软件或者设置代理,前者有时候稍显麻烦,后者有的软件不支持这样的方式。在经过多方资料查找后,得知了可以通过树莓派搭建透明代理(部分人文章也称其为旁路由)的办法,用这个办法,通过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

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注