这篇文章上次修改于 434 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

关于 clash

我尽量写的简单一些, 以编辑配置文件为主, 减少命令行的操作.

最近一次重新编辑时换回了 Arch, 一个目的是想使用尽可能少的软件来配置网络部分.

来自官方文档:
Clash是一个跨平台的基于规则的代理工具, 在网络和应用层运行, 支持各种代理和反审查协议的开箱即用.
在一些互联网受到严格审查或封锁的国家和地区, 它已被互联网用户广泛采用. 无论如何, 任何想要改善其 Internet 体验的人都可以使用 Clash.

项目地址: https://github.com/Dreamacro/clash
我用的是闭源版的 Clash Premium 内核, 除此之外还有 Meta 内核.
这也是软路由的核心部分, 只要你想完全可以 All in one.

原理

开始之前还是讲讲软路由工作的原理, 不感兴趣跳过即可.

软件环境: Arch (Gigabit Ethernet) + clash-premium

硬件环境: J4125 + AX3000 (AP)

直接或间接连接软路由的设备通过 DHCP 下发 clash DNS 或通过 DNS 劫持的形式请求 clash 返回 tun 网段的 IP, 继而将所有流量导向 clash 的 utun (例如 Telegram IP 直连则会通过自动配置路由表等方式解决, 这一点不需要人为干预.)

关于这一点我们可以通过命令验证:

# ip rule show                                                                                                                                                                                                                                                                                                                                    
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
# ip route show                                                                                                                                                                                                                                                                                                                                   default via 10.247.241.1 dev bond0 proto dhcp src 10.247.241.29 metric 1024
10.0.0.0/16 dev br0 proto kernel scope link src 10.0.0.1
10.247.241.0/24 dev bond0 proto kernel scope link src 10.247.241.29 metric 1024
10.247.241.1 dev bond0 proto dhcp scope link src 10.247.241.29 metric 1024
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-0c8b7a40470a proto kernel scope link src 172.18.0.1
172.19.0.0/16 dev br-2e9335ade4db proto kernel scope link src 172.19.0.1
172.24.0.0/16 dev br-98423b6cfa04 proto kernel scope link src 172.24.0.1 linkdown
172.25.0.0/16 dev br-4c2b590a294b proto kernel scope link src 172.25.0.1
199.6.0.0/16 via 199.6.0.2 dev utun proto static

由于 2023/02/16 版本后砍掉了 redir-host 模式, 因此只能选择剩下的 fake-ip 了. 就像名字一样, 这个模式下返回的 IP 全是假的.....
到现在整个项目都没了.

Meta 版本依然提供 redir-host, 但是二者配置并不兼容甚至存在无法修改的部分, 最后还是选择了 premium.

一切路由去广告都不靠谱, 老老实实客户端干!!!

在之前的版本中我折腾过好几个方案, 最后决定跑一个纯粹的 clash.
我有三个理由:
1.分流功能大家用的都是同一个思路和类似的规则, 那么结果应该也就差不多.
2.去广告功能那几家的规则覆盖范围也差不多, 而且关键是我连规则 (几十万条规则警告) 中十分之一的广告域名都碰不到.
3.众所周知路由端去广告并不纯粹, 对于不使用单独广告域名的网站的广告一点办法都没有, 要克服这一点需要非常完善的去广告规则以及 HTTPS 解密, 但这又会带来新的问题. (浏览器会提示 MITM

配置

前置

如果是我这种桌面操作系统很可能已经开启了某个网络管理软件比如 NetworkManager. 如果有, 下载完需要的软件后先关掉, 否则会造成冲突.

# 关闭 NetworkManager
sudo systemctl disable NetworkManager NetworkManager-wait-online
# 查找其他服务, 自行判断是否关闭. 文件路径为 /etc/systemd/system
systemctl --type=service

如果网不好可以选择手动添加镜像源或者用这条命令自动找最快的镜像源, 非必须.

sudo reflector --verbose --latest 5 --sort rate --save /etc/pacman.d/mirrorlist
# sudo vim /etc/pacman.conf
# 如果节点不存在就添加到文件结尾
[archlinuxcn]
Server = https://mirrors.bfsu.edu.cn/archlinuxcn/$arch

保存后执行 sudo pacman -Sy archlinuxcn-keyringyay -S archlinuxcn/clash-premium-bin, 不用 yay 用其他包管理软件也无所谓, 大同小异.

下面提到的软件都可以用 yay 直接安装, 这里就不再赘述了. 配置到最后记得把这些软件全部设置成开机自启.

DHCP

DHCP (Dynamic Host Configuration Protocol 动态主机设置协议) 是用于给连接软路由 LAN 口的设备下发 IP 的, 可以说是必须功能.

# 显式启动前置服务 
sudo systemctl enable systemd-networkd systemd-resolved

接下来要编辑的都是 /etc/systemd/network 下的文件, 有三种类型: link netdev network 但我们只需要后面两个就够用了.

关于文件的命名风格略有讲究, 感兴趣的可以去 看看, 长话短说就是以字典序第一个匹配成功的为准, 所以推荐的文件名应该是 10-xxx.network 这样的.

虽然文件名可以带 - 但不推荐网卡也这样命名, 否则可能会遇到命令行操作时转义字符的坑.

简单配置

适用于网口数量不超过两个的软路由. 你说单网口? 趁早扔了换一个吧.

1.打开 WAN 口并接收上游 DHCP 通告

# sudo vim /etc/systemd/network/xxx.network

[Match]
Description=wan
Name=eno1

[Network]
DHCP=ipv4
IPv6AcceptRA=yes

[DHCPv4]
UseHostname=true

这样 WAN 口会拥有一个通过 DHCP 获取到的 IPv4 地址, 软路由自己就有网了 (难道之前一直没网?

2.打开 LAN 口

和上面一样, 再创建一个 xxx.network 即可.

[Match]
Description=lan
Name=enp1s0

[Link]
Multicast=yes

[Network]
Address=10.0.0.1/16
MulticastDNS=yes
IPMasquerade=both
IPv6SendRA=yes
DHCPv6PrefixDelegation=yes

[IPv6SendRA]
Managed=yes
OtherInformation=yes

进阶配置

涉及到了 netdev, 文档写的也很复杂, 但只要这样做就好了不需要知道配置项的作用.

适用于多网口设备, 因为 LAN / WAN 是完全分开写的, 所以可以和上面混着来也没问题.
但是由于上面是我之前使用的配置, 而下面是我现在使用的配置, 所以下面的也许更完善一些

1.创建 bond 设备用于聚合多个 WAN 网卡

注意这个是 .netdev 文件!

[NetDev]
Name=bond0
Kind=bond

[Bond]
Mode=balance-alb
PrimaryReselectPolicy=always
MinLinks=1

bond 有七种 Mode 并且有着明显的差别, balance-rr 的特点是流量会被分的很均匀但实测发现测速正常看视频非常卡, 而 balance-tlb 就像单行道上行下行是分开的, 具体区别可以看 这里

2.为 bond 网卡开启 DHCP

这个是 .network 文件.

[Match]
Description=wan
Name=bond0

[Network]
DHCP=yes
IPv6AcceptRA=yes

[DHCPv4]
UseHostname=false

3.将指定 WAN 口加入 bond

这个是 .network 文件.

[Match]
Name=eno1 enp4s0

[Network]
Bond=bond0

4.为 LAN 口创建一个网桥设备

注意这个是 .netdev 文件!

[NetDev]
Name=br0
Kind=bridge

5.为网桥配置 IP

这个是 .network 文件.

[Match]
Description=lan
Name=br0

[Link]
Multicast=yes

[Network]
Address=10.0.0.1/16
MulticastDNS=true
IPMasquerade=both
IPv6SendRA=yes
DHCPv6PrefixDelegation=yes

[IPv6SendRA]
Managed=yes
OtherInformation=yes

6.将 LAN 口加入网桥

这个是 .network 文件.

[Match]
Name=enp1s0 enp2s0

[Network]
Bridge=br0

完成后重启一下 systemd-networkd.service 就好了

配置 Lan 口的 DHCP 服务器

可以在上面的基础上在 lan.network 添加最少一行实现. 指定 DNS 和下面的设定租期只是因为我碰到了一些幺蛾子....

[Match]
Name=br0

[Network]
Address=10.0.0.1/16
+ DHCPServer=yes
+ DNS=10.0.0.1
+ DNS=223.5.5.5
......
+ [DHCPServer]
+ DefaultLeaseTimeSec=60s
+ MaxLeaseTimeSec=600s

又或者有其他需求可以使用更专业点的 DHCPD

把默认的乱七八糟配置全部注释掉然后添加下面的这些.

# sudo vim /etc/dhcpd.conf
subnet 10.0.0.0 netmask 255.255.0.0 {
  range 10.0.1.1 10.0.10.254;
  option subnet-mask 255.255.0.0;
  option domain-name "dns.kazusa.cc";
  option domain-name-servers 10.0.0.1;
  option routers 10.0.0.1;
}

然后让 dhcpd 服务只在 Lan 口开启

sudo cp /usr/lib/systemd/system/dhcpd4.service /etc/systemd/system/[email protected]
sudo vim /etc/systemd/system/[email protected]

在文件这一行结尾加上一个 %I

- ExecStart=/usr/bin/dhcpd -4 -q -cf /etc/dhcpd.conf -pf /run/dhcpd4/dhcpd.pid
+ ExecStart=/usr/bin/dhcpd -4 -q -cf /etc/dhcpd.conf -pf /run/dhcpd4/dhcpd.pid %I

执行 sudo systemctl enable [email protected], 注意这里是要在 LAN 网卡开启 DHCP 服务器, 如果桥接则是网桥!

此时电脑应该可以自动获取到一个 10.0.1.x 的 IP.

5.开启内核网络转发
sudo vim /etc/sysctl.d/ipforward.conf, 创建这个文件并写入如下内容. 不同设备在这些地方可能不一样, 比如有的是 /etc/sysctl.conf 有的是 /etc/sysctl.conf.d 文件夹, 二者并没有什么太大的区别.

net.ipv4.ip_forward=1

刷新刚才的配置 sudo sysctl -p /etc/sysctl.d/ipforward.conf, 正常会输出写入的配置并且没有报错.

至此软路由能够自动获取 WAN 口下发的 IP 也能给 LAN 口下发子网 IP.

配置 DNS

这篇文章中软路由本身的 DNS 是由 systemd-resolved.service 管理的, 当然你也可以关掉换其他的.

首先看看 53 端口 sudo lsof -i :53, 不出意外应该可以看到 systemd-resolve 的字样. 这表示 DNS 的默认端口被这个服务占用了, 我们先把它给挪走.
sudo vim /etc/systemd/resolved.conf, 默认应该是全部注释的, 取消注释并修改即可

[Resolve]
DNS=223.5.5.5
DNSStubListener=no

打个链接, 其实这份文件经常被不同软件修改.....
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

然后重启服务

sudo systemctl restart systemd-resolved

现在软路由的 53 端口就空着了, 并且不影响系统本身的 DNS 解析.

下面我们将要在 clash 中劫持 223.5.5.5 实现不管有没有运行 clash 都有一个可用 DNS.

Clash

因为加起来太长了所以我挪到外面又写了一篇 单独讲 Clash 配置文件.

默认的 clash 是用户级别的服务, 我们可以创建一个系统级的.

# sudo vim /etc/systemd/system/clash.service
[Unit]
Description=Just proxy.
After=network-online.target remote-fs.target
Wants=network-online.target

[Service]
Type=exec
User=root
Restart=on-abort
ExecStart=/usr/bin/clash -d /etc/clash -f /etc/clash/config.yaml

[Install]
WantedBy=multi-user.target

用户级的长这样, 带一个 @ 而且默认配置文件在 ~/.config/clash 下.

# cat /usr/lib/systemd/system/[email protected]                                                                                                                                                                                                          
[Unit]
Description=A rule based proxy in Go for %i.
After=network.target

[Service]
Type=exec
User=%i
Restart=on-abort
ExecStart=/usr/bin/clash

[Install]
WantedBy=multi-user.target

现在应该还不能正常用, 可能是 tun 转发需要重启设备后才能生效, 但可以通过显式指定代理来用.

到这里重启设备应该就没问题了, 如果是连接 AP 出现了幺蛾子那么拔掉网线重连或者重启路由器应该就没问题了.

最后

买了快半年, 现在对于 Linux 和网络部分可以说是相当熟悉了. 大道至简, 越到后面越喜欢简单的配置. 从一开始的各种软件大杂烩到最后的两个系统级服务加一个用户级软件搞定.

感谢:

用 Arch Linux 做软路由 — 凌莞咕噜咕噜~

使用 clash 搭建透明网关实现旁路科学上网自由 - akiyaの博客