文章

订阅转换服务的搭建 (Docker)

所使用的订阅链接无法直接添加到 ClashX,一般需要订阅转换服务。最近发现一直在用的订阅转换网站的后端崩了,导致 ClashX 无法下载转换的订阅文件。等了两天也没有修复,求人不如求己,看到该网站上有前端项目的 GitHub 链接,点进去发现后端也有相应的开源项目,那么干脆自己搭建一个完整的订阅转换服务吧。

准备工作

前端项目 sub-web 主要由 Vue 写成,需要安装 NodeYarn 来安装依赖与打包发布。后端项目 subconverter 则由 C++ 写成,该项目未直接给出具体的编译、运行程序的步骤,但是给出了使用 Docker 镜像安装的具体步骤。

对于前端项目,如果我们采用非 Docker 的方式,就需要手动安装 NodeYarn,且当我们不需要该项目时,软件和相关依赖的清除工作也会变得很麻烦。因此我们都采用 Docker 来安装、发布前后端项目,组成完整的订阅转换系统。正好之前也没有接触过 Docker,这篇文章也用来记录一下 Docker 的安装以及基本命令的使用。

安装 Docker

本节简要地给出在 Ubuntu 22.04 系统下 Docker 的安装步骤。其他系统下 Docker 的安装方式见该链接

  1. 首先更新 apt 程序包索引,并安装程序包以允许 apt 通过 HTTPS 使用存储库:

    1
    2
    3
    4
    5
    6
    7
    
     sudo apt update
    
     sudo apt install \
         ca-certificates \
         curl \
         gnupg \
         lsb-release
    
  2. 接着添加 Docker 的官方 GPG 密钥:

    1
    2
    
     sudo mkdir -p /etc/apt/keyrings
     curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    
  3. 使用以下命令设置 Docker 使用稳定版本 (stable) 的库:

    1
    2
    3
    
     echo \
     "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
     $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
  4. 安装 Docker 引擎:

    1
    2
    
     sudo apt update
     sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
    

验证 Docker 是否安装成功

docker 的所有命令都需要 sudo 权限,如果不想在 docker 命令前加上 sudo ,可以创建一个名为 docker 的Unix组,并将用户加入其中。具体参考官方文档

我们安装一个测试镜像来验证 Docker 是否安装成功:

1
sudo docker run hello-world

此命令下载测试镜像并在容器中运行。当容器运行时,其会打印一条信息并消息并退出:

hello-from-Docker

此容器开始运行后,打印一条信息,然后程序结束,容器停止。此时我们删除该测试程序,由于该容器已经停止,因此我们需要接着删除容器 (Container),再删除镜像 (Image)。这一顺序不能交换,如果我们直接删除镜像,会报错 Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container XXX is using its referenced image XXX

首先我们可以使用以下命令列出所有容器,--all 参数指定列出本机所有容器,包括终止运行的容器。

1
docker container ls --all

可以看到 hello-world 容器 ID、容器对应的镜像等。使用以下命令删除容器:

1
docker rm [ContainerID/Names]

如果没有为 hello-world 容器指定 Names,就使用 ContainerID。

然后删除相应的镜像:

1
docker image rm hello-world

Docker 已经安装完成,接下来我们安装订阅转换项目的前后端。

后端项目安装与配置

安装

我们使用默认的订阅转换配置即可,因此安装后端服务非常简单。使用以下命令安装后端项目:

1
docker run -d --restart=always -p 25500:25500 tindy2013/subconverter:latest

因为该后端程序需要在计算机后台一直运行,因此采用了 -d 选项,并将容器将内部端口 25500 转发到主机端口 25500。25500:25500 前者是主机端口,后者为容器内部端口。安装结束后,我们使用以下命令验证安装是否成功:

1
curl http://localhost:25500/version

如果出现 subconverter vx.x.x backend 则说明容器已经成功运行。

subconverter

配置域名

注意到,后端项目其实是一个完整的程序,其监听 25500 端口。我们也可以直接访问该程序,从而实现订阅的转换。其最简单的访问接口为:

1
http://127.0.0.1:25500/sub?target=%TARGET%&url=%URL%&config=%CONFIG%

如果需要更为自定义的转换规则,则需要在该接口后面添加更多的参数,详细的参数列表请详见该项目的说明文档。由此看来手动设定参数其实是一个很麻烦的事,因此我们需要前端项目。使用前端项目,就可以通过可视化的网页界面来设定转换的规则。不过值得注意的是,前端项目只是一个订阅链接生成器,它会通过我们在界面上选定的相关配置来生成上面的接口链接。然后我们在 Clash 客户端中更新订阅时,实际请求的目标仍然是后端。

那么前端所需要配置的一个关键就是后端项目的地址(下一节会具体介绍配置步骤)。当然我们不能将 127.0.0.1:25500 输入到前端的配置文件,因为正如前面所述,前端项目会原封不动的将该地址作为转换后的链接地址,那么在 Clash 客户端中更新订阅时就会向 127.0.0.1:25500 发起请求(即用户本地)。但我们的项目是配置在服务器上的,因此应该输入服务器的公网IP地址。

但使用服务器 IP 有一个不好之处,其他人能够直接看到服务器的 IP 地址,且使用 HTTP 协议不够安全,我们最好还是为后端配置相应的域名和 SSL 证书。这里就不详细的介绍域名以及 SSL 证书的配置了,详细内容可参见这篇文章。不过我们可以不用购买新的域名,而是通过解析不同的二级域名的方式来区分前后端,例如 frontend.XXX.combackend.XXX.com

SSL 配置文件与以往有些不同,例如对于后端的域名,Apache 监听的仍然是 443 端口,但需要将该域名的相关请求转发到本机的 25500 端口。本篇文章以 back.niallapi.xyz 为后端地址,具体的 SSL Config 文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerAdmin webmaster@localhost
        ServerName back.niallapi.xyz
        DocumentRoot /var/www/html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        SSLEngine on
        SSLCertificateFile	/etc/apache2/ssl/back_niallapi_xyz/XXX.crt
        SSLCertificateKeyFile /etc/apache2/ssl/back_niallapi_xyz/XXX.key
        SSLCertificateChainFile /etc/apache2/ssl/back_niallapi_xyz/1_root_bundle.crt
        ProxyPreserveHost On
        ProxyPass "/" "http://127.0.0.1:25500/"
        ProxyPassReverse / http://127.0.0.1:25500/
        RequestHeader set X-Forwarded-Proto "https" 
        <FilesMatch "\.(cgi|shtml|phtml|php)$">
                SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory /usr/lib/cgi-bin>
                SSLOptions +StdEnvVars
        </Directory>
    </VirtualHost>
 </IfModule>

当然如果在本机运行的话,你也可以直接使用 IP地址+端口号 的形式来访问,从而不必配置域名以及 SSL 配置文件。

其它配置

如果想要修改后端配置,可以进入容器内修改:

1
sudo docker exec -it sub /bin/sh

由于默认文件使用的是 pref.toml ,编辑文件:

1
vi pref.toml

例如需要修改 managed_config_prefix 字段,输入 / 搜索 127.0.0.1 替换成自己的后端地址即可。

前端项目安装与配置

安装

我们需要下载前端项目,然后修改相应的配置文件(后端接口),构建并运行项目。首先下载项目:

1
git clone https://github.com/CareyWang/sub-web.git

然后进入该项目文件夹,修改 .env 文件的内容,即如下图所示:

sub-web

修改为你所配置的后端项目地址。如果采用 IP 地址的方式,则后端项目地址应为 http://XXX.XXX.XXX.XXX:25500 (即 IP 地址 + 端口号的形式)。

然后在项目主目录下,运行以下命令构建并运行该项目:

1
2
docker build -t subweb-local:latest .
docker run -d -p 58080:80 --restart always --name subweb subweb-local:latest

此时前端项目也就构建完成并成功运行了。上述 docker run 命令将容器的 80 端口映射到了主机的 58080 端口。因此可以直接通过 IP+端口号 的形式来访问前端了,端口号为 58080。

注意,对于使用 IP地址+端口号 形式,如果无法访问前端项目,请检查在服务器提供商控制台检查相应的端口是否开启,前端的端口 58080。如果后端也采用 IP地址+端口号 的形式,也需要开启 25500 端口。

配置域名

与后端项目一样,我们也可以为前端配置相应的域名,唯一所有区别的是的转发的端口为 58080。

大功告成

此时访问前端地址,我们就可以使用自己搭建的订阅转换服务器了!

result

本文由作者按照 CC BY 4.0 进行授权