前言
我们继续趁热打铁,将UnblockNeteaseMusic也一起部署了,因为它也要用到 nftables
来实现。
下载与安装
unblockneteasemusic
这个名称太长了,我们把它更名为 unblocknem
。我默认你已经按照 前文(二) 安装好了必要的软件了。以下为root用户运行的命令。
1
2
3
4
5
6
7
8
9
|
## 检查最新稳定版的版本号,如果获取不到请检查网络
remote_ver=$(curl -sS https://api.github.com/repos/UnblockNeteaseMusic/server/releases/latest | jq -r .tag_name | sed 's|v||' | grep -v "null"); echo $remote_ver
## 下载最新稳定版(前一句有输出这一句才能正常执行)
cd /tmp
wget -q --progress=bar:dot --show-progress -O "unblockneteasemusic-linux-x64" "https://github.com/UnblockNeteaseMusic/server/releases/download/v${remote_ver}/unblockneteasemusic-linux-x64"
## 安装
install -p unblockneteasemusic-linux-x64 /usr/local/bin/unblocknem
|
创建服务
unblocknem.service
创建工作目录/var/lib/unblocknem
。
1
|
mkdir -p /var/lib/unblocknem
|
创建文件 /etc/systemd/system/unblocknem.service
,内容如下。这时 clash
的配置文件为 /var/lib/unblocknem/unblocknem.env
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[Unit]
Description = Revive unavailable songs for Netease Cloud Music (Refactored & Enhanced version).
Wants = network-online.target clash.service
After = network-online.target
[Service]
Type = simple
Restart = always
EnvironmentFile = -/var/lib/unblocknem/unblocknem.env
WorkingDirectory = /var/lib/unblocknem
ExecStart = /usr/local/bin/unblocknem
RestartSec = 10
StartLimitInterval = 0
[Install]
WantedBy = multi-user.target
|
如果你比较讲究Linux哲学,可以把 EnvironmentFile
改成下面这样,这时 unblocknem
的配置文件为 /etc/default/unblocknem
。
1
|
EnvironmentFile = -/etc/default/unblocknem
|
如果不想以root用户运行 unblocknem
,可以自行创建用户 unblocknem
和用户组 unblocknem
,然后在 /etc/systemd/system/unblocknem.service
的 [Service]
单元下增加下面两行,同时修改 /var/lib/unblocknem
及其子文件为该普通用户所有。(后续的脚本都是以root用户为运行用户进行的,如果要把 unblocknem
服务调整为普通用户运行,请自行修改脚本)。
1
2
|
User = unblocknem
Group = unblocknem
|
注意:由于各音源政策一直在变化,可能unblockneteasemusic
默认的音源顺序(见官方README)无法使用,你可以查看unblocknem.service
的运行日志来确认(方式见后文),这时需要你自己调整音源的顺序,也就是在ExecStart
中增加-o
参数,同时设置/etc/default/unblocknem
中的FOLLOW_SOURCE_ORDER=true
。ExecStart
设置音源顺序举例如下:
1
|
ExecStart = /usr/local/bin/unblocknem -o ytdlp bilibili
|
安装依赖
在 前文(二) 我们已经安装了UnblockNeteaseMusic的一个依赖项: yt-dlp,在实际运行中,部分情况下还需要另外一个依赖:phantomjs。这个软件已经多年没有更新过了。
1
2
3
4
|
cd /tmp
wget -q --progress=bar:dot --show-progress -O phantomjs-2.1.1-linux-x86_64.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
tar --no-same-owner -xf phantomjs-2.1.1-linux-x86_64.tar.bz2 # 需要安装bzip2才能解压
install -p phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs
|
unblocknem 的配置文件
没有配置文件, unblocknem
也是可以以默认配置启动的。如有需要,可以新建 /var/lib/unblocknem/unblocknem.env
或 /etc/default/unblocknem
,内容如下,请注意按照注释修改。全部环境变量详见 官方README。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
# 全部环境变量详见:https://github.com/UnblockNeteaseMusic/server
# 激活无损音质获取
ENABLE_FLAC=true
# 激活本地黑胶 VIP,可选值:true(等同于 CVIP)、cvip 和 svip
ENABLE_LOCAL_VIP=svip
# 仅对这些 UID 激活本地黑胶 VIP,默认为对全部用户生效
# LOCAL_VIP_UID=123456789,1234,123456
# 激活故障的 Netease HTTPDNS 查询(不建议)
# ENABLE_HTTPDNS=true
# 屏蔽应用内部分广告
BLOCK_ADS=true
# 禁用更新检测
DISABLE_UPGRADE_CHECK=true
# 激活开发模式。需要自己用 yarn 安装依赖 (dependencies)
# DEVELOPMENT=true
# 严格按照配置音源的顺序进行查询
# FOLLOW_SOURCE_ORDER=true
# 输出机器可读的 JSON 记录格式
# JSON_LOG=true
# 停用 cache
# NO_CACHE=true
# 允许的最低源音质,小于该值将被替换
# MIN_BR=320000
# 选择所有音源中的最高码率替换音频
SELECT_MAX_BR=true
# 日志输出等级。请见〈日志等级〉部分
# LOG_LEVEL=debug
# 从 Pino 端设置日志输出的文件位置。也可以用 *sh 的输出重导向功能 (node app.js >> app.log) 代替
# LOG_FILE=app.log
# JOOX 音源的 wmid 和 session_key cookie
# JOOX_COOKIE="wmid=<your_wmid>; session_key=<your_session_key>"
# 咪咕音源的 aversionid cookie
# MIGU_COOKIE="<your_aversionid>"
# QQ 音源的 uin 和 qm_keyst cookie
# QQ_COOKIE="uin=123456789; qm_keyst=Q_H_L_6hTegBdoCzFj6bcUUpuhkOP11234ChsOkfKiOdvcIOFKiQQf4oGjykQ"
# Youtube 音源的 Data API v3 Key
# YOUTUBE_KEY="Adjeuskn12xdEvQfLHnvfC12386QAApcOt5Kh1g"
# 自定义证书文件
SIGN_CERT="/var/lib/unblocknem/server.crt"
# 自定义密钥文件
SIGN_KEY="/var/lib/unblocknem/server.key"
# 在其他音源搜索歌曲时携带专辑名称(默认搜索条件 歌曲名 - 歌手,启用后搜索条件 歌曲名 - 歌手 专辑名
# SEARCH_ALBUM=true
|
生成自己的证书
1
2
3
|
cd /var/lib/unblocknem
wget https://raw.githubusercontent.com/UnblockNeteaseMusic/server/enhanced/generate-cert.sh
env TYPE="RSA" ISSUENAME="Your Name" bash generate-cert.sh
|
脚本会在 /var/lib/unblocknem
目录下生成这些文件。如果你不以root用户来启动 unblocknem
,则请注意修改它们的所有者。
1
2
3
4
5
6
7
|
/var/lib/unblocknem
├── ca.crt
├── ca.key
├── ca.srl
├── server.crt
├── server.csr
└── server.key
|
调整 nftables 规则
在 前文(四) 中我们为 clash
创建了一些 nftables
规则,现在我们多了 unblocknem
,它也需要,所以我们要调整一下 前文(四) 中的 /usr/local/bin/mynftables.nft
,调整为下面这个样子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#!/usr/sbin/nft -f
## 清空旧规则
flush ruleset
## 只处理指定网卡的流量,要和ip规则中的接口操持一致
define interface = ens18
## clash的透明代理端口
define tproxy_port = 7895
## clash打的标记(routing-mark)
define clash_mark = 666
## 常规流量标记,ip rule中加的标记,要和ip规则中保持一致,对应 "ip rule add fwmark 1 lookup 100" 中的 "1"
define default_mark = 1
## 本机运行了服务并且需要在公网上访问的tcp端口(本机开放在公网上的端口),仅本地局域网访问的服务端口可不用在此变量中,以半角逗号分隔
define local_tcp_port = {
2222, # ssh,按需设置
8080-8088 # nginx webui,按需设置
}
## 要绕过的局域网内tcp流量经由本机访问的目标端口,也就是允许局域网内其他主机主动设置DNS服务器为其他服务器,而非旁路由
define lan_2_dport_tcp = {
53 # dns查询
}
## 要绕过的局域网内udp流量经由本机访问的目标端口,也就是允许局域网内其他主机主动设置DNS服务器为其他服务器,而非旁路由;另外也允许局域网内其他主机访问远程的NTP服务器
define lan_2_dport_udp = {
53, # dns查询
123 # ntp端口
}
## 保留ip地址
define private_address = {
127.0.0.0/8,
100.64.0.0/10,
169.254.0.0/16,
224.0.0.0/4,
240.0.0.0/4,
10.0.0.0/8,
172.16.0.0/12,
192.168.0.0/16
}
## 大陆ip地址
include "/var/lib/clash/geoip4_cn.nft"
## 网易云音乐ip地址
include "/var/lib/clash/nem_address.nft"
table ip clash {
## 保留ipv4集合
set private_address_set {
type ipv4_addr
flags interval
elements = $private_address
}
## 网易云音乐ipv4集合
set nem_address_set {
type ipv4_addr
flags interval
elements = $nem_address
}
## 大陆ipv4集合
set geoip4_cn_set {
type ipv4_addr
flags interval
elements = $geoip4_cn
}
## prerouting链
chain prerouting {
type filter hook prerouting priority filter; policy accept;
ip protocol { tcp, udp } socket transparent 1 meta mark set $default_mark accept # 绕过已经建立的连接
meta mark $default_mark goto clash_tproxy # 已经打上default_mark标记的属于本机流量转过来的,直接进入透明代理
fib daddr type { local, broadcast, anycast, multicast } accept # 绕过本地、单播、组播、多播地址
tcp dport $lan_2_dport_tcp accept # 绕过经由本机到目标端口的tcp流量
udp dport $lan_2_dport_udp accept # 绕过经由本地到目标端口的udp流量
ip daddr @private_address_set accept # 绕过目标地址为保留ip的地址
ip daddr @nem_address_set goto clash_tproxy # 将网易云音乐的流量转发到透明代理
ip daddr @geoip4_cn_set accept # 绕过目标地址为大陆ip的地址
# ip protocol udp accept # 绕过全部udp流量(udp不进行透明代理)
goto clash_tproxy # 其他流量透明代理到clash
}
## 透明代理
chain clash_tproxy {
ip protocol { tcp, udp } tproxy to :$tproxy_port meta mark set $default_mark
}
## output链
chain output {
type route hook output priority filter; policy accept;
oifname != $interface accept # 绕过本机内部通信的流量(接口lo)
meta mark $clash_mark accept # 绕过本机clash发出的流量
fib daddr type { local, broadcast, anycast, multicast } accept # 绕过本地、单播、组播、多播地址
udp dport { 53, 123 } accept # 绕过本机dns查询、NTP流量
tcp sport $local_tcp_port accept # 绕过本地运行了服务的tcp端口,如果并不需要从公网访问这些端口,可以注释掉本行
ip daddr @private_address_set accept # 绕过目标地址为保留ip的地址
ip daddr @geoip4_cn_set accept # 绕过目标地址为大陆ip的地址
ip protocol { tcp, udp } meta mark set $default_mark # 其他流量重路由到prerouting
}
}
|
注意到我们在第51行多引用了一个文件 /var/lib/clash/nem_address.nft
(可先下载这个并非最新的文件到指定位置来将就一下:nem_address.nft,我们将在 本系列第(七)篇 用定时任务来自动更新这个文件),在第63-67行多形成了一个集合 nem_address_set
,在第85行插入了一行规则 ip daddr @nem_address_set goto clash_tproxy
,这条规则插入在 ip daddr @geoip4_cn_set accept
之前,表示虽然网易云音乐IP是中国大陆IP,但要在直接接收前转到透明代理并停止后续规则。现在的 prerouting
链内容有点多,其实可以一拆为三。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
## prerouting链
chain prerouting {
type filter hook prerouting priority filter; policy accept;
fib daddr type { local, broadcast, anycast, multicast } accept # 绕过本地、单播、组播、多播地址
tcp dport $lan_2_dport_tcp accept # 绕过经由本机到目标端口的tcp流量
udp dport $lan_2_dport_udp accept # 绕过经由本地到目标端口的udp流量
ip daddr @private_address_set accept # 绕过目标地址为保留ip的地址
ip daddr @geoip4_cn_set accept # 绕过目标地址为大陆ip的地址
# ip protocol udp accept # 绕过全部udp流量(udp不进行透明代理)
goto clash_tproxy # 其他流量透明代理到clash
}
## prerouting链绕过已经建立的连接,已经打上default_mark标记的属于本机流量转过来的,直接进入透明代理
chain divert {
type filter hook prerouting priority mangle; policy accept;
ip protocol { tcp, udp } socket transparent 1 meta mark set $default_mark accept
meta mark $default_mark goto clash_tproxy
}
## 局域网中访问网易云音乐的流量,第一次全部进行透明代理,优先级需要比绕过大陆ip先执行(mangle为-150,filter为0)
chain neteasemusic {
type filter hook prerouting priority dstnat; policy accept;
ip daddr @nem_address_set goto clash_tproxy
}
|
一拆为三后,新的 divert
链的优先级为 mangle
(-150),新的neteasemusic
链的优先级为 dstnat
(-100),而新的 prerouting
链则仍是 filter
(0),数值越小,优先级越高,所以 ip daddr @nem_address_set goto clash_tproxy
这条规则仍然早于 ip daddr @geoip4_cn_set accept
执行。这样也可以让网易云音乐IP在被直接接收前就转到透明代理去。
unblocknem
工作在应用层,clash
转给它后,它出来的流量会经由 output
链中的 ip daddr @geoip4_cn_set accept
直接出去,不会形成环路(output
链并没有再劫持这部分流量)。这也就意味着上述规则只能代理局域网中除旁路由以外其他设备(以旁路由为网关的)的网易云音乐流量,不能代理旁路由自己的网易云音乐流量。
设想一个这样的场景:unblocknem
设置了 ytdlp
(Youtube)为劫持音源,那么局域网中以旁路由为网关的客户端A在播放灰色歌曲触发 unblocknem
时,流量是怎么运作的呢?
对照前文(四)的题图,客户端A的流量先进入旁路由的 prerouting
链,按上述说明触发该链中的 ip daddr @nem_address_set goto clash_tproxy
规则将流量转向我们的 unblocknem
HTTP代理,然后 unblocknem
代理会将流量劫持向Youtube,也就是说 unblocknem
会在旁路由中产生向Youtube的请求。前文已经说过,unblocknem
工作在应用层,它产生的流量会先进入 output
链。如果它请求的是国内的音源,那么将会由 output
链中 ip daddr @geoip4_cn_set accept
规则直接放行,而现在它请求的是Youtube需要走代理,所以流量会在 output
链中触发 ip protocol { tcp, udp } meta mark set $default_mark
这条规则,将其打上标记并重路由到 prerouting
链,然后按照前文(四)所说进行透明代理。也就是说,在这个假设场景下,客户端A在播放灰色歌曲时,流量经过了clash的两次透明代理。
调整 clash 配置文件
我们后续将在 本系列第(七)篇 用定时任务来自动在 clash
的配置中自动插入下面这些内容。
在 clash
的配置文件中 proxies:
部分新增:
1
2
3
4
|
- name: 🎶 网易代理
server: 10.0.0.2
port: 8080
type: http
|
proxy-groups:
部分新增:
1
2
3
4
5
|
- name: 🎶 网易音乐
type: select
proxies:
- 🎶 网易代理
- DIRECT
|
rules:
部分新增(各地IP可能是不一样的,我们将在 本系列第(七)篇 用定时任务来自动生成它,将其刷新为你本地的解析IP):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- DOMAIN-SUFFIX,music.163.com,🎶 网易音乐
- DOMAIN-SUFFIX,music.163.com.163jiasu.com,🎶 网易音乐
- IP-CIDR,39.105.63.80/32,🎶 网易音乐,no-resolve
- IP-CIDR,39.105.175.128/32,🎶 网易音乐,no-resolve
- IP-CIDR,45.127.129.53/32,🎶 网易音乐,no-resolve
- IP-CIDR,47.100.127.239/32,🎶 网易音乐,no-resolve
- IP-CIDR,59.111.19.33/32,🎶 网易音乐,no-resolve
- IP-CIDR,59.111.19.99/32,🎶 网易音乐,no-resolve
- IP-CIDR,59.111.160.195/32,🎶 网易音乐,no-resolve
- IP-CIDR,112.47.51.30/32,🎶 网易音乐,no-resolve
- IP-CIDR,114.80.149.72/30,🎶 网易音乐,no-resolve
- IP-CIDR,115.238.119.67/32,🎶 网易音乐,no-resolve
- IP-CIDR,115.238.119.68/31,🎶 网易音乐,no-resolve
- IP-CIDR,118.24.63.156/32,🎶 网易音乐,no-resolve
- IP-CIDR,121.228.190.68/30,🎶 网易音乐,no-resolve
- IP-CIDR,122.225.83.106/32,🎶 网易音乐,no-resolve
- IP-CIDR,122.225.83.109/32,🎶 网易音乐,no-resolve
- IP-CIDR,122.225.83.110/32,🎶 网易音乐,no-resolve
- IP-CIDR,180.163.200.96/30,🎶 网易音乐,no-resolve
- IP-CIDR,182.92.170.253/32,🎶 网易音乐,no-resolve
- IP-CIDR,183.134.34.248/31,🎶 网易音乐,no-resolve
- IP-CIDR,183.136.182.18/31,🎶 网易音乐,no-resolve
- IP-CIDR,183.136.182.20/32,🎶 网易音乐,no-resolve
- IP-CIDR,193.112.159.225/32,🎶 网易音乐,no-resolve
|
网易云音乐IP只允许解析IPv4
因为我们的透明代理只代理 IPv4
流量,所以我们不能让网易云音乐客户端解析出 IPv6
地址。有好几种方式可以实现,既可以在 mosdns
中实现,也可以在 adguardhome
中实现,但后者有 webui
要方便些,并且 adguardhome
是第一级,它有可能会切换到后备服务器而不向 mosdns
发起请求,所以我们就选后者吧。
在 adguardhome
中实现也有两种方式,其一是将 “设置 -> DNS设置 -> 上游DNS服务器” 设置为下面这样(这种方式不会计入“被拦截域名”中,但是如若 adguardhome
在 clash
遇到故障会切换到后备,对后备是不生效的),直接将网易云音乐的解析发到 clash
去解析,因为我们关闭了 clash
的DNS模块的 IPv6
解析。
1
2
|
127.0.0.1:5335
[/music.163.com/music.ntes53.netease.com/music.163.com.163jiasu.com/music.163.com.bsclink.cn/uz99.v.bsclink.cn/]127.0.0.1:7874
|
其二是在 “过滤器 -> 自定义过滤规则” 中添加规则如下(这种方式会计入“被拦截域名”中,但是对包括后备在内的全部上游DNS服务器都有效)。
1
2
3
4
5
6
7
|
||music.163.com^$dnstype=AAAA
||music.ntes53.netease.com^$dnstype=AAAA
||music.163.com.163jiasu.com^$dnstype=AAAA
||music.163.com.bsclink.cn^$dnstype=AAAA
||music.163.com.c.vedcdnlb.com^$dnstype=AAAA
||s.bdsa.cdnbuild.net^$dnstype=AAAA
||uz99.v.bsclink.cn^$dnstype=AAAA
|
只能保证目前有效。上述两种方式,都由于 CNAME
域名的存在,光处理 music.163.com
和 music.163.com.163jiasu.com
不行,还要处理它们背后的 CNAME
域名。可能有望在未来得以改进,详见 Hosts-Blocklists#dnstype。
启用服务
完全配置好以后,我们可以设置 /etc/systemd/system/unblocknem.service
为开启自动启动,并立即启动起来。如果这个时候 clash
还没有启动起来,那么 unblocknem
服务就还不可用。都启动好后,unblocknem
将会监听在 8080
和 8081
端口上。
1
|
systemctl enable --now unblocknem.service
|
后续如想查看日志,我们直接使用Debian自带的工具来查看:
1
|
journalctl -efu unblocknem.service
|
如果想要重启:
1
|
systemctl restart unblocknem.service
|
客户端
安卓系统不支持。
Windows
安装网易云音乐客户端后,创建一个快捷方式,然后在该快捷方式的属性中的“目标”增加 --ignore-certificate-errors
,注意有个空格。
ArchLinux系
将刚刚生成的 /var/lib/unblocknem/ca.crt
下载下来,然后运行:
1
|
sudo trust anchor --store ca.crt
|
在启动命令行后面添加 --ignore-certificate-errors
,然后启动即可。
Debian系
将刚刚生成的 /var/lib/unblocknem/ca.crt
下载下来,放在 /usr/local/share/ca-certificates
下,然后运行:
1
|
sudo update-ca-certificates
|
在启动命令行后面添加 --ignore-certificate-errors
,然后启动即可。
最后
打开 clash
的 webui
:http://10.0.0.2:9090/ui/xd/#/proxies ,选择 网易音乐
为 网易代理
;你再打开网易云音乐客户端后,在 http://10.0.0.2:9090/ui/xd/#/conns 就能看到许多连接都接管到 UnblockNeteaseMusic
了。
从 unblocknem.service
的日志中也能看到它的作用,这些灰色歌曲都被接管了。
系列