Provider 服务提供者
你可以在 provider
目录内看到两个已经写好的 Provider,它们分别是订阅地址和自己维护的节点列表。
需要注意的是文件名即为该 Provider 的名称,后面在定义 Artifact 时会用到。
Surgio 内置了 defineXxxProvider
方法,Xxx
对应下面所列的类型,可以让 IDE 智能提示配置项,不过你也可以不使用这样的语法糖。下面两种写法都是可以的。
const { defineClashProvider } = require('surgio');
module.exports = defineClashProvider({
url: 'https://example.com/clash.yaml',
// ...
});
module.exports = {
type: 'clash',
// ...
};
支持异步函数
为了满足更多定制化的场景,支持通过异步函数的模式挂载 Provider
const { defineCustomProvider } = require('surgio');
module.exports = defineCustomProvider(async function() {
const myNodeList = await someAsyncFunction();
return {
nodeList: myNodeList,
};
});
订阅类型
目前 Surgio 支持两种 Provider 类型:
类型 | 描述 | 备注 |
---|---|---|
custom 推荐 | 自己维护的节点 | 支持 Shadowsocks, Shadowsocksr, Snell, HTTPS, HTTP, Vmess, Socks5, Tuic |
clash 推荐 | Clash 配置 | 支持 Shadowsocks, Shadowsocksr, Snell, HTTPS, HTTP, Vmess, Socks5, Tuic |
trojan | Trojan 订阅 | Shadowrocket 支持的 Trojan 订阅格式 |
shadowsocks_json_subscribe | 针对 Windows 客户端的 Shadowsocks 订阅地址 | 通常命名为 gui-config.json |
shadowsocks_subscribe | 通用的 Shadowsocks 订阅地址 | |
shadowsocksr_subscribe | 通用的 Shadowsocksr 订阅地址 | |
v2rayn_subscribe | V2rayN 订阅地址 | 支持 V2Ray, Shadowsocks, 协议 |
ssd | SSD 订阅 | 支持 Shadowsocks |
推荐
Clash 订阅注意
- Surgio 支持读取
obfs-local
和v2ray-plugin
两种 SIP003 插件配置; - 仅支持
v2ray-plugin
的 WebSocket 模式;
url
- 类型:
string
- 必须
udpRelay
- 类型:
boolean
- 默认值:
false
我们发现部分机场的 Clash 订阅并没有设定 udp
,所以你可以通过配置这个属性来强制设定节点的 UDP 转发支持情况。如果订阅节点中包含 udp
字段,则该配置无效。
tls13
- 类型:
boolean
- 默认值:
false
强制开启节点的 TLS 1.3。
推荐
Custom 自定义节点由自己维护的节点列表。
普通模式
const { defineCustomProvider } = require('surgio');
module.exports = defineCustomProvider({
nodeList: [
{
type: 'shadowsocks',
// ...
},
],
});
异步模式
Surgio v3.0.0
Gateway: v2.0.0
异步模式下,Gateway 的 /get-artifact
请求参数会被传入到 nodeList
函数中。这样可以实现动态的节点列表。
customParams
是一个对象,包含了所有在 Artifact 和全局定义的自定义参数。假如你使用了 Gateway,则里面还包含所有请求 URL 中的参数。需要注意的是,URL 参数中所有的值都是字符串类型,例如 mobile=true
,那么 customParams.mobile
的值就是 'true'
。
customParams
默认会包含 requestUserAgent
,方便你根据不同的客户端返回不同的节点列表。
const { defineCustomProvider } = require('surgio');
module.exports = defineCustomProvider({
nodeList: async (customParams) => {
if (customParams.mobile === 'true') {
return [
{
type: 'shadowsocks',
// ...
},
];
} else {
return [
{
type: 'trojan',
// ...
},
];
}
},
});
Shadowsocks
{
type: 'shadowsocks',
nodeName: '🇺🇸US',
hostname: 'us.example.com',
port: 10000,
method: 'chacha20-ietf-poly1305',
password: 'password',
obfs: 'tls', // tls, http, ws, wss
obfsHost: 'gateway-carry.icloud.com',
obfsUri: '/', // 当 obfs 为 ws 或 wss 时可配置
udpRelay: true,
tfo: false, // TCP Fast Open
tls13: false, // TLS 1.3,适用于 v2ray-plugin
mux: false, // 目前仅 Clash + Shadowsocks + v2ray-plugin 可用
}
注意
ws
和wss
是通过服务端 v2ray-plugin 支持的;- TLS 1.3 需要服务端支持
Shadowsocksr
{
type: 'shadowsocksr',
nodeName: '🇭🇰HK',
hostname: 'hk.example.com',
port: 10000,
method: 'chacha20-ietf',
password: 'password',
obfs: 'tls1.2_ticket_auth',
obfsparam: 'music.163.com',
protocol: 'auth_aes128_md5',
protoparam: '',
udpRelay: true,
tfo: false, // TCP Fast Open
}
Vmess
{
nodeName: '🇭🇰HK',
type: 'vmess',
hostname: 'hk.example.com',
method: 'auto', // 仅支持 auto/aes-128-gcm/chacha20-ietf-poly1305/none
network: 'ws', // 仅支持 tcp/ws
alterId: '64',
path: '/',
port: 8080,
tls: false,
host: 'example.com', // 此属性相当于 wsHeaders.host,但推荐配置在 wsHeaders.host 上
uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
tfo: false, // TCP Fast Open
tls13: false, // TLS 1.3, TLS 开启时有效
udpRelay: true, // 开启 UDP 转发
wsHeaders: {
key: 'value',
},
}
Snell
{
type: 'snell',
nodeName: '🇭🇰HK',
hostname: 'hk.example.com',
port: 10000,
psk: 'RjEJRhNPps3DrYBcEQrcMe3q9NzFLMP',
obfs: 'tls', // tls 或 http 或不传
obfsHost: 'gateway-carry.icloud.com', // 可选
version: 4, // 可选,默认不传以 Surge 为准
reuse: true, // 可选,默认 false
}
HTTPS
{
type: 'https',
nodeName: '🇭🇰HK',
hostname: 'hk.example.com',
port: 443,
username: 'username',
password: 'password',
tls13: false, // TLS 1.3
}
HTTP
{
type: 'http',
nodeName: '🇭🇰HK',
hostname: 'hk.example.com',
port: 8080,
username: 'username',
password: 'password',
}
Trojan
{
type: 'trojan',
nodeName: '🇭🇰HK',
hostname: 'hk.example.com',
port: 443,
password: 'password',
sni: 'example.com', // 可选
alpn: ['http/1.1'], // 可选
skipCertVerify: true, // 可选
udpRelay: true, // 可选
tls13: false, // TLS 1.3
network: 'ws', // 可不填
wsPath: '/', // 可选
wsHeaders: {}, // 可选
}
Socks5
{
type: 'socks5',
nodeName: '🇭🇰HK',
hostname: 'hk.example.com',
port: 80,
username: 'username', // 可选
password: 'password', // 可选
tls: true, // 可选
skipCertVerify: true, // 可选
udpRelay: false, // 可选, 仅 Clash 支持
sni: 'example.com', // 可选, 仅 Surge 支持
tfo: true, // 可选, 仅 Surge 支持
clientCert: 'item' // 可选, 仅 Surge 支持
}
clientCert
仅 Surge 支持, 参考 文档 进行配置。
Wireguard
理论上你可以设置多个 Peer,但是目前仅 Surge 支持多个 Peer 的配置,其它客户端需要自行分拆成多个相互独立的配置。
{
type: 'wireguard',
nodeName: 'Wireguard',
selfIp: '172.16.0.2',
privateKey: 'eOyyaXrwVTHwo62x98Is6v5Fo=',
peers: [
{
publicKey: 'eOyyaXrwVTHwo62x98Is6v5Fo=',
endpoint: 'wg.example.com:54321',
allowedIps: '172.16.0.0/24', // 可选
keepalive: 25, // 可选
presharedKey: 'eOyyaXrwVTHwo62x98Is6v5Fo=', // 可选
reservedBits: [16], // 可选
}
],
selfIpV6: '2001:0db8:85a3:0000:0000:8a2e:0370:7334', // 可选
preferIpv6: false, // 可选
mtu: 1420, // 可选
dnsServers: ['1.1.1.1'], // 可选
reservedBits: [16], // 可选
}
Tuic
V5
Surgio v3.0.0
{
type: 'tuic',
nodeName: 'Tuic',
hostname: 'tuic.example.com',
port: 443,
password: 'password',
uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
version: 5,
sni: 'sni.example.com', // 可选
skipCertVerify: true, // 可选
alpn: ['h3'], // 可选,Stash 不支持空值
udpRelay: false, // 可选, 仅 Clash 支持更改,Surge 默认开启
}
老版本协议
{
type: 'tuic',
nodeName: 'Tuic',
hostname: 'tuic.example.com',
port: 443,
token: 'password',
sni: 'sni.example.com', // 可选
skipCertVerify: true, // 可选
alpn: ['h3'], // 可选,Stash 不支持空值
udpRelay: false, // 可选, 仅 Clash 支持更改,Surge 默认开启
}
Hysteria
Surgio v3.1.0
Surgio 只支持 Hysteria v2 协议。请注意,Hysteria v2 协议和 v1 协议完全不兼容。当前可以为 Clash 和 Surge 生成此节点。
Clash 需要在配置中开启 clashConfig.enableHysteria2
。
{
type: 'hysteria2',
nodeName: 'Hysteria',
hostname: 'hysteria.example.com',
port: 443,
password: 'password',
sni: 'sni.example.com', // 可选
skipCertVerify: true, // 可选
alpn: ['h3'], // 可选,Stash 不支持空值
udpRelay: false, // 可选, 仅 Clash 支持更改,Surge 默认开启
}
SSD 订阅
module.exports = {
type: 'ssd',
url: '',
udpRelay: true,
};
注意
- Surgio 支持读取
simple-obfs
和v2ray-plugin
两种 SIP003 插件配置; - 仅支持
v2ray-plugin
的 WebSocket 模式;
url
- 类型:
string
- 必须
udpRelay
- 类型:
boolean
- 默认值:
false
你可以通过配置这个属性来强制设定节点的 UDP 转发支持情况。
Shddowsocks JSON 订阅
module.exports = {
type: 'shadowsocks_json_subscribe',
url: '',
udpRelay: true,
};
url
- 类型:
string
- 必须
若机场没有提供这种订阅地址,推荐使用 Fndroid 的 接口 进行转换。
注意
- 如果你正在使用 DlerCloud,可以使用 Surge 的托管订阅地址,然后使用
surge2sswin
转换
udpRelay
- 类型:
boolean
- 默认值:
false
由于这种订阅协议不支持定义 UDP 转发的支持情况,所以单独出来进行配置。UDP 转发可以应用在 Surge 中。
Shadowsocks 订阅
module.exports = {
type: 'shadowsocks_subscribe',
url: '',
udpRelay: true,
};
注意
- Surgio 支持读取
obfs-local
和v2ray-plugin
两种 SIP003 插件配置; - 仅支持
v2ray-plugin
的 WebSocket 模式;
url
- 类型:
string
- 必须
注意
- 如果你正在使用 DlerCloud,可以使用 SS 订阅地址
udpRelay
- 类型:
boolean
- 默认值:
false
由于这种订阅协议不支持定义 UDP 转发的支持情况,所以单独出来进行配置。UDP 转发可以应用在 Surge 中。
Shadowsocksr 订阅
module.exports = {
type: 'shadowsocksr_subscribe',
url: '',
};
url
- 类型:
string
- 必须
V2rayn 订阅
module.exports = {
type: 'v2rayn_subscribe',
url: '',
};
url
- 类型:
string
- 必须
注意
- Quantumult 的订阅格式和 V2rayN 的订阅格式有差异,不可以混用;
- 如果你正在使用 DlerCloud,可以使用「通用」类型的订阅地址;
- 订阅中的 V2Ray 和 Shadowsocks 节点会被读取;
compatibleMode
- 类型:
boolean
- 默认值:
false
部分机场提供的订阅地址不符合标准,提供一个兼容模式进行解析。
udpRelay
- 类型:
boolean
- 默认值:
false
由于这种订阅协议不支持定义 UDP 转发的支持情况,所以单独出来进行配置。
skipCertVerify
- 类型:
boolean
- 默认值:
false
由于这种订阅协议不支持定义跳过证书验证,所以单独出来进行配置。
tls13
- 类型:
boolean
- 默认值:
false
强制开启节点的 TLS 1.3。
Trojan 订阅
module.exports = {
type: 'trojan',
url: '',
};
注意
该订阅方式仅支持标准的 Trojan 协议,不支持 WebSocket 和 GRPC
url
- 类型:
string
- 必须
udpRelay
- 类型:
boolean
- 默认值:
false
强制开启节点的 UDP 转发。
tls13
- 类型:
boolean
- 默认值:
false
强制开启节点的 TLS 1.3。
公共属性
提示
- 公共属性可以定义在任何一种 Provider 中;
- 请务必注意下面
nodeConfig
指的是custom
类型内的每个节点,provider
指的是 Provider;
nodeConfig.enable
- 类型:
boolean
- 默认值:
true
单独关闭某个节点输出到配置中。若没有 enable
属性则默认打开。
{
enable: false,
type: 'shadowsocks',
nodeName: '🇺🇸US',
hostname: 'us.example.com',
port: 10000,
method: 'chacha20-ietf-poly1305',
password: 'password',
}
nodeConfig.tfo
- 类型:
boolean
- 默认值:
false
是否为该节点开启 TFO(TCP Fast Open)。
nodeConfig.mptcp
- 类型:
boolean
- 默认值:
false
是否为该节点开启 Multipath TCP。目前仅 Surge 支持这一特性。
nodeConfig.shadowTls
- 类型:
object
- 默认值:
undefined
目前仅 Surge 和 Stash 支持这一特性。
nodeConfig.shadowTls.password
- 类型:
string
- 必须
nodeConfig.shadowTls.sni
- 类型:
string
- 必须
nodeConfig.shadowTls.version
- 类型:
number
- 默认值:
undefined
nodeConfig.tls13
- 类型:
boolean
- 默认值:
false
为 TLS 节点开启 TLS 1.3 支持。
注意
- TLS 1.3 需要服务端支持;
- 支持 TLS 的节点类型有 Shadowsocks with v2ray-plugin(tls), Vmess(tls), HTTPS;
nodeConfig.skipCertVerify
- 类型:
boolean
- 默认值:
false
关闭 TLS 节点的证书检查。
注意
- 支持 TLS 的节点类型有 Shadowsocks with v2ray-plugin(tls), Vmess(tls), HTTPS;
- 请不要随意将证书检查关闭;
nodeConfig.underlyingProxy
- 类型:
string
- 默认值:
undefined
可以通过一个代理跳板使用另一个代理,可以无限嵌套使用。目前仅 Surge 支持该特性。
注意
Surgio 不会验证名称是否有效
nodeConfig.testUrl
- 类型:
string
- 默认值:
undefined
在新版的 Surge 中支持针对某个 Proxy 设置测试的地址。你可以通过这个参数来设置改地址。
注意
- Surgio 不会验证名称是否有效;
- 目前仅 Surge 支持该特性;
nodeConfig.serverCertFingerprintSha256
- 类型:
string
- 默认值:
undefined
用于验证服务器证书的 SHA256 指纹。目前仅 Surge 支持该特性。
nodeConfig.ecn
- 类型:
boolean
- 默认值:
false
是否为该节点开启 ECN(Explicit Congestion Notification)。目前仅 Surge 支持这一特性。
provider.nodeFilter
- 类型:
Function
- 入参:
NodeConfig
- 返回值:
boolean
有一些俗称「外贸机场」的服务商提供很多诸如马来西亚、土耳其的节点,不需要这些国家节点的朋友每次都要在数十个节点中寻找自己想要的。我们可以用这个方法把这些节点过滤掉。
const { utils } = require('surgio');
module.exports = {
// 过滤出名字中包含土耳其和马来西亚的节点
nodeFilter: utils.useKeywords(['土耳其', '马来西亚']),
};
提示
关于过滤器的自定义和其它进阶使用方法,请阅读 「自定义过滤器」。
provider.netflixFilter
- 类型:
Function
- 入参:
NodeConfig
- 返回值:
boolean
该方法会覆盖 Surgio 内置的 netflixFilter
。用于过滤出支持 Netflix 的节点。对于那些每一个节点都解锁流媒体的机场,也可以单独过滤出部分你喜欢的节点。
module.exports = {
// 过滤出名字中包含 HK(大小写不敏感)的节点
netflixFilter: utils.useKeywords(['hk', 'HK']),
};
provider.youtubePremiumFilter
- 类型:
Function
- 入参:
NodeConfig
- 返回值:
boolean
该方法会覆盖 Surgio 内置的 youtubePremiumFilter
。用于过滤出支持 Youtube Premium 的节点。
provider.customFilters
- 类型:
object
- 默认值:
undefined
自定义 Filter。关于自定义 Filter 的用法,请阅读 进阶 - 自定义 Filter。
提示
你现在可以定义 全局的过滤器 了!
provider.startPort
- 类型:
number
在调用 getSurgeNodes
时会强制要求设置该值。建议大于 10000。
在生成 Surge 的 Shadowsocksr 和 Vmess 配置文件时,本地监听端口会根据此配置递增。这样做的好处是切换配置文件时不会遇到端口冲突。同一个 Provider 被用在不同的 Artifact 中也会进行递增。
provider.addFlag
- 类型:
boolean
- 默认值:
false
在节点名称前加国旗 Emoji。需要注意的是,Surgio 是根据有限的节点名关键词判断位置的,如果无法匹配则会保留原节点名。你可以在所有的过滤器中检索国旗 Emoji。
provider.removeExistingFlag
- 类型:
boolean
- 默认值:
false
去除订阅中的国旗 Emoji。可以在不开启 addFlag
时使用,这时会输出没有 Emoji 的节点名称。
provider.tfo
- 类型:
boolean
- 默认值:
false
是否为该订阅强制开启 TFO(TCP Fast Open)。部分机场虽然支持 TFO 但是没有在订阅中开启,你可以通过这个配置强制打开。
provider.underlyingProxy
- 类型:
string
- 默认值:
undefined
是否对当前 Provider 中所有节点使用自定义 Underlying Proxy。在 CustomProvider
中也可以使用,但是优先级低于 nodeConfig.underlyingProxy
。
目前仅 Surge 支持该特性。
注意
Surgio 不会验证名称是否有效
provider.mptcp
- 类型:
boolean
- 默认值:
false
是否为该订阅强制开启 Multipath TCP。目前仅 Surge 支持这一特性。
provider.renameNode
- 类型:
Function
- 默认值:
undefined
更改节点名。如果你对机场的奇葩命名有意见,可以在这里把他们替换掉。
module.exports = {
renameNode: name => {
if (name === '社会主义') {
return '资本主义';
}
return name;
},
};
注意
nodeFilter
只对原始名称有效;- 其它内置过滤器和自定义过滤器仅对新名称有效;
- 如果你开启了
addFlag
,那国家地区判定仅对新名称有效; - 这个方法不一定要在末尾
return
内容,如果没有返回内容则保留原名称;
provider.relayUrl
- 类型:
Boolean|String
- 默认值:
undefined
开启订阅地址转发。由于部分机场禁止 AWS 等公有云服务器访问,所以面板无法获取订阅内容。开启后会使用一个免费并且安全的转发服务进行获取。
从 v2.4.0 开始,你可以指定一个字符串来自定义转发服务。设置的方法如下:
- URL 中插入原始的订阅连接:
module.exports = {
relayUrl: 'https://proxy.example.com/%URL%',
};
- URL 中插入 URL encoded 后的订阅连接:
module.exports = {
relayUrl: 'https://proxy.example.com/?url=%%URL%%',
};
如果 relayUrl
是一个布尔值,则使用内置的服务进行转发。
provider.requestUserAgent
- 类型:
string
- 默认值: undefined
指定订阅请求头中的 User-Agent 字段。若不指定则使用内置的默认值 surgio/<版本号>
。
钩子函数 (hooks)
钩子函数是 Surgio v3 新增的特性,用于在获取远程订阅内容时执行一些操作。你可以在所有类型的 Provider 中定义钩子函数。所有的钩子函数都会在 renameNode
, addFlag
, removeExistingFlag
, nodeFilter
等原有用来修改节点的方法之前执行。
hooks.afterNodeListResponse
async afterNodeListResponse(nodeList: NodeConfig[], customParams: {}): Promise<NodeConfig[]>
该钩子函数会在成功获取到远程订阅内容后执行。你可以自由修改节点的内容,甚至是像维护自定义类型 Provider 那样追加自己的节点。
这个方法要求最后需要返回一个 NodeConfig[]
,否则你的操作可能不会生效。
customParams
是一个对象,包含了所有在 Artifact 和全局定义的自定义参数。假如你使用了 Gateway,则里面还包含所有请求 URL 中的参数和 requestUserAgent
,方便你根据不同的客户端返回不同的节点列表。
const { defineClashProvider } = require('surgio');
module.exports = defineClashProvider({
url: 'https://example.com/clash.yaml',
hooks: {
afterNodeListResponse: async (nodeList, customParams) => {
// nodeList: NodeConfig[]
// customerParams: {}
return nodeList;
},
},
}
})
hooks.onError
async onError(error: Error): Promise<NodeConfig[] | undefined>
该钩子函数会在获取远程订阅内容失败时执行。你可以在这里进行错误处理,或者返回一个 NodeConfig[]
以继续执行,格式类似 CustomProvider
里的节点列表。
const { defineClashProvider } = require('surgio');
module.exports = defineClashProvider({
url: 'https://example.com/clash.yaml',
hooks: {
onError: async error => {
// error: Error
return [
{
nodeName: 'Fallback',
type: 'shadowsocks',
hostname: 'fallback.example.com',
port: 443,
method: 'chacha20-ietf-poly1305',
password: 'password',
},
];
},
},
}
})