Surgio上手教程——妥善管理你的机场订阅

February 06, 2021

前言

有的时候下载 BitTorrent 会发现被拦截,查看了 Clash 的日志会发现,流量按照分流规则走了机场代理,但是机场是禁止 BT 下载 的,所以需要在 Clash 配置文件中加入一条使 BitTorrent 不走代理(即直连)的规则,但是目前 Clash 的配置文件中节点规则以及配置是严重耦合在一起的,那么就需要一个工具来帮助我们实现这个需求,研究了一下发现 Surgio 可以胜任。


需求

现有多个机场订阅以及节点信息:

  • Clash(V2Ray)
  • Clash(SSR)
  • Vmess

想将其合并成一个 Clash 配置文件,并且自定义一些分流规则。


Surgio

Surgio 就是一个可以实现(包括但不仅限于)上述需求的好帮手。

关于 Surgio 的详细介绍,还请看 Surgio官方文档 ,文档写的较为全面,对于我这样的小白来说,初次上手确实有些摸不着头脑,网上相关的教程也较少(可能大佬看一看就明白了吧,觉得没啥可以分享的)。

就这样,反反复复研究了小两天,整理出了以下内容,来解决上述需求。


Surgio 环境配置

  • 以 ’$’ 开头的内容是需要输入至终端的,本教程基于 macOS Catalina 环境,其他平台请参照 Surgio 快速上手

安装 Node.js

$ brew install node

若提示 Command not found 'brew',请安装 Homebrew后再次执行该命令安装 Node.js

# 安装 Homebrew
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

下载 ssr-local 二进制文件

Surgio 导出 SSR 配置时需要 ssr-local 的支持,否则后面执行命令时会报错。 (后期可以通过配置 binPath 或者删除冗余的 SSR 导出配置等内容来优化)

# 该命令的作用是下载 ssr-local 到指定位置,并为其添加执行权限。
$ curl -L https://github.com/tindy2013/shadowsocks-static-binaries/raw/master/shadowsocksr-libev/macos/ssr-local -o /usr/local/bin/ssr-local && chmod +x /usr/local/bin/ssr-local

安装 Surgio

# 安装
$ npm init surgio-store my-rule-store

# 或使用国内镜像安装
$ npm init surgio-store my-rule-store --use-cnpm

# 切换到仓库目录
$ cd my-rule-store

my-rule-store 目录如下:

.
├── node_modules
├── package-lock.json
├── package.json
├── provider
├── surgio.conf.js
└── template

当前你只需要关注三个东西,他们的作用大致如下:

  1. provider - 里面包含你的机场订阅和节点信息
  2. template - 里面包含输出文件的格式与配置
  3. surgio.conf.js - 里面是你所需要的规则和机场订阅的组合方式等等配置

添加机场订阅和节点信息

第一步,先将多个机场订阅和一些单独的节点添加到 Surgio 中。


添加机场订阅

进入 provider 文件夹

$ cd provider

你能看到以下内容:

.
├── README.md
├── demo.js
├── ssr_subscribe_demo.js
├── subscribe_demo.js
└── v2ray_subscribe_demo.js

首先对 subscribe_demo.js 进行修改,将 url 中的内容替换成你的机场订阅。

module.exports = {
- url: 'https://gist.githubusercontent.com/geekdada/34353d6ae23abd48f6e200b00747a87e/raw',
+ url: 'https://example.com/clash_v2.yaml',
  type: 'clash',
  // 定义所有的节点都支持 udpRelay
  udpRelay: true,
  // 添加国旗 emoji
  addFlag: true,
};

如果你有多个机场订阅的话,则根据 subscribe_demo.js 格式在当前目录下多创建几个文件,以我上面(两个 Clash 订阅链接)的需求为例:

# 拷贝出一份新的文件
$ cp subscribe_demo.js subscribe_demo_1.js

subscribe_demo_1.js 的内容进行修改:

module.exports = {
- url: 'https://example.com/clash_v2.yaml',
+ url: 'https://example.com/clash_ssr.yaml',
  type: 'clash',
  // 定义所有的节点都支持 udpRelay
  udpRelay: true,
  // 添加国旗 emoji
  addFlag: true,
};

这样 subscribe_demo.jssubscribe_demo_1.js 中就分别保存了 Clash(V2Ray)和 Clash(SSR) 的订阅地址。


添加节点信息

接下来我们在 demo.js 中可以看到一些节点信息填写的模板:

'use strict';

module.exports = {
  type: 'custom',
  nodeList: [
    {
      nodeName: '🇺🇸US',
      type: 'shadowsocks',
      hostname: 'us.example.com',
      port: '10000',
      method: 'chacha20-ietf-poly1305',
      password: 'password',
      obfs: 'tls',
      'obfs-host': 'gateway-carry.icloud.com',
      'udp-relay': true,
    },
    {
      nodeName: '🇭🇰HK(Netflix)',
      type: 'shadowsocks',
      hostname: 'hk.example.com',
      port: '10000',
      method: 'chacha20-ietf-poly1305',
      password: 'password',
      'udp-relay': true,
    },
  ],
};

只需稍作修改即可,结构可参考 官方文档:Provider - custom

到此为止,我们已经将多个机场的订阅信息和一些节点的信息就添加到了 Surgio 的配置中。

接下来添加一些我们所需要的分流规则。


配置分流规则

官方文档 中,我们可以了解到 Surgio 支持符合 Surge Ruleset 标准,我们就以添加 surge-rules 中的 RULE-SET: 广告域名列表 reject.txt 规则为例,在生成的 Clash 文件中拦截该规则下的域名。


添加规则

my-rule-store 文件夹下的 surgio.conf.js 进行修改:

module.exports = {
  remoteSnippets: [
    {
      name: 'apple', // 模板中对应 remoteSnippets.apple
      url: 'https://raw.githubusercontent.com/geekdada/surge-list/master/surgio-snippet/apple.tpl',
      surgioSnippet: true
    },

    // 省略一些规则

    {
      name: 'paypal', // 模板中对应 remoteSnippets.paypal
      url: 'https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/Extra/PayPal.list'
    },
+   // 添加广告域名列表规则
+   {
+     name: 'ad-reject',
+     url: 'https://raw.githubusercontent.com/Loyalsoldier/surge-rules/release/ruleset/reject.txt'
+   },
  ]
}

好,到此 Surgio 已经知道了该去哪里获取规则,接下来我们需要让 Surgio 知道这些规则该应用在哪里。


模板中应用规则

进入 template 文件夹,对其中的 clash.tpl 文件进行编辑:

rules:
+ {{ remoteSnippets.ad-reject.main('REJECT') | clash }}
{{ remoteSnippets.apple.main('🚀 Proxy', '🍎 Apple', '🍎 Apple CDN', 'DIRECT', 'US') | clash }}
{{ remoteSnippets.netflix.main('🎬 Netflix') | clash }}
{{ remoteSnippets.hbo.main('🚀 Proxy') | clash }}
{{ remoteSnippets.hulu.main('🚀 Proxy') | clash }}
{{ youtube_rules.main('🚀 Proxy') | clash }}
{{ us_rules.main('US') | clash }}
{{ remoteSnippets.telegram.main('🚀 Proxy') | clash }}
{{ blocked_rules.main('🚀 Proxy') | clash }}
{{ direct_rules.main('DIRECT') | clash }}

在该文件中,我们添加的内容代表,从 surgio.conf.js 文件中的 remoteSnippets 中找到名字为 ad-reject 的规则,将该规则设置为 拒绝(REJECT) 状态,这样符合该规则的请求就会被拦截,从而达到去除广告的效果。

最开始的需求基本配置完毕,接下来我们需要将多个机场订阅和一些单独的节点合并生成一个 Clash 配置文件,并且其中需要包含刚刚配置的规则。


导出配置

这一部分需要回到 surgio.conf.js 中进行修改:

artifacts: [
    // 省略一些内容

    /**
     * Clash
     */
    { 
+     // 该导出文件包含 Clash(V2Ray)
-     name: 'Clash.yaml',
+     name: 'clash_v2.yaml',
      template: 'clash',
      provider: 'subscribe_demo',   // 对应 provider 中的 subscribe_demo.js
    },
    { 
+     // 该导出文件包含 Clash(SSR)
-     name: 'Clash_custom_dns.yaml',
+     name: 'clash_ssr.yaml',
      template: 'clash',
      provider: 'subscribe_demo_1', // 对应 provider 中的 subscribe_demo_1.js
      customParams: {
        dns: true,
      }
    },
+   // 合并节点
+   { 
+     // 该导出文件包含 Vmess + Clash(V2Ray) + Clash(SSR)
+     name: 'clash_combine.yaml',
+     template: 'clash',
+     provider: 'demo',             // 对应 provider 中的 demo.js
+     combineProviders: ['subscribe_demo', 'subscribe_demo_1'],
+   },

    // 省略一些内容
  ],

输出代理配置文件

# 切换到项目根目录
$ cd my-rule-store

# 生成配置文件
$ npx surgio generate

执行成功后,会生成一个 dist 文件夹,其中应该包含:

  • clash_v2.yaml
  • clash_ssr.yaml
  • clash_combine.yaml

clash_combine.yaml 这个合并之后的 Clash 配置文件拷贝至 ClashX 的配置目录内,然后在 ClashX 中切换配置即可。


按照上面的配置,可以实现本文一开始的需求。

但是还是有以下可以优化的地方:

  • 每次修改规则配置后,需要重新拷贝配置文件至 ClashX 配置目录下。
  • 机场更新节点订阅后,需要重新生成配置文件。
  • 配置新机器的代理时,需要先在本地配置 Node 和 Surgio 环境。

参考了官方文档,发现可以将 Surgio 部署到 SaaS 平台上,例如 Vercel 和 Heroku。

那么就开始吧~


部署 Surgio API

本地直接部署至 Vercel 的方法请参考 官方文档:快速搭建托管 API

以下介绍的方法是我常用的流程,将本地项目提交至 GitHub,然后在 Vercel 引如 GitHub 项目并进行部署的方法,不过会略过一些常用操作。

该流程方便后期随时随地在 GitHub 上编辑配置文件,并且 Vercel 自动化部署,无需本地再次配置环境。

# 在项目根目录 `my-rule-store` 下安装 `Surgio Gateway`。
$ cd my-rule-store
$ npm i @surgio/gateway --save

# 创建 Vercel 配置文件
$ touch vercel.json

# 创建 Surgio Gateway 配置文件
$ touch gateway.js

vercel.json 文件中添加如下内容:

{
  "version": 2,
  "public": false,
  "builds": [
    { 
      "src": "/gateway.js",
      "use": "@vercel/node",
      "config": {
        "includeFiles": [
          "provider/**",
          "template/**",
          "*.js",
          "*.json"
        ]
      }
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "/gateway.js"
    }
  ]
}

gateway.js 文件中添加如下内容:

'use strict';

const gateway = require('@surgio/gateway');

module.exports = gateway.createHttpServer();

配置接口鉴权(安全考虑,务必配置)

surgio.conf.js 添加如下内容

module.exports = {
  gateway: {
    auth: true,
    accessToken: 'YOUR_PASSWORD',
  },
}

并将 YOUR_PASSWORD 进行随意替换。


提交至 GitHub


Vercel 部署


略略略:p