Skip to content

Commit

Permalink
feat: 在生成 surge 的 ssr 订阅时强制校验 startPort
Browse files Browse the repository at this point in the history
  • Loading branch information
geekdada committed Dec 11, 2020
1 parent 44eb42a commit 879080b
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 25 deletions.
5 changes: 3 additions & 2 deletions docs/guide/custom-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ module.exports = {
'udp-relay': false, // 可选, 仅 Clash 支持
sni: 'example.com', // 可选, 仅 Surge 支持
tfo: true, // 可选, 仅 Surge 支持
clientCert: 'item' // 可选, 仅 Surge 支持, 参考 https://github.com/Blankwonder/Surge-Manual/blob/master/release-note/surge-mac.md#version-250
clientCert: 'item' // 可选, 仅 Surge 支持, 参考 https://github.com/Blankwonder/Surge-Manual/blob/master/release-note/surge-mac.md#version-250
}
```

Expand Down Expand Up @@ -492,7 +492,8 @@ module.exports = {
### provider.startPort

- 类型: `Number`
- 默认值: `61100`

在调用 `getSurgeNodes` 时会强制要求设置该值。建议大于 10000。

在生成 Surge 的 Shadowsocksr 和 Vmess 配置文件时,本地监听端口会根据此配置递增。这样做的好处是切换配置文件时不会遇到端口冲突。同一个 Provider 被用在不同的 Artifact 中也会进行递增。

Expand Down
65 changes: 42 additions & 23 deletions lib/provider/Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import Joi from '@hapi/joi';
import {
ProviderConfig,
SupportProviderEnum,
PossibleNodeConfigType, SubscriptionUserinfo,
PossibleNodeConfigType,
SubscriptionUserinfo,
} from '../types';

let globalPort = 61100;

export default class Provider {
public readonly type: SupportProviderEnum;
public readonly nodeFilter?: ProviderConfig['nodeFilter'];
Expand All @@ -19,38 +18,56 @@ export default class Provider {
public readonly tfo?: boolean;
public readonly mptcp?: boolean;
public readonly renameNode?: ProviderConfig['renameNode'];
public readonly relayUrl?: boolean|string;
public readonly relayUrl?: boolean | string;
// 是否支持在订阅中获取用户流量信息
public supportGetSubscriptionUserInfo: boolean;

// External Provider 的起始端口,Surge 配置中使用
private startPort?: number;
public startPort?: number;

constructor(public name: string, config: ProviderConfig) {
const schema = Joi.object({
type: Joi.string()
.valid(...Object.values<string>(SupportProviderEnum))
.required(),
nodeFilter: Joi.any().allow(Joi.function(), Joi.object({ filter: Joi.function(), supportSort: Joi.boolean().strict() })),
netflixFilter: Joi.any().allow(Joi.function(), Joi.object({ filter: Joi.function(), supportSort: Joi.boolean().strict() })),
youtubePremiumFilter: Joi.any().allow(Joi.function(), Joi.object({ filter: Joi.function(), supportSort: Joi.boolean().strict() })),
customFilters: Joi.object()
.pattern(
Joi.string(),
Joi.any().allow(Joi.function(), Joi.object({ filter: Joi.function(), supportSort: Joi.boolean().strict() }))
),
nodeFilter: Joi.any().allow(
Joi.function(),
Joi.object({
filter: Joi.function(),
supportSort: Joi.boolean().strict(),
})
),
netflixFilter: Joi.any().allow(
Joi.function(),
Joi.object({
filter: Joi.function(),
supportSort: Joi.boolean().strict(),
})
),
youtubePremiumFilter: Joi.any().allow(
Joi.function(),
Joi.object({
filter: Joi.function(),
supportSort: Joi.boolean().strict(),
})
),
customFilters: Joi.object().pattern(
Joi.string(),
Joi.any().allow(
Joi.function(),
Joi.object({
filter: Joi.function(),
supportSort: Joi.boolean().strict(),
})
)
),
addFlag: Joi.boolean().strict(),
removeExistingFlag: Joi.boolean().strict(),
mptcp: Joi.boolean().strict(),
tfo: Joi.boolean().strict(),
startPort: Joi.number().integer().min(1024).max(65535),
relayUrl: [
Joi.boolean().strict(),
Joi.string(),
],
relayUrl: [Joi.boolean().strict(), Joi.string()],
renameNode: Joi.function(),
})
.unknown();
}).unknown();

const { error } = schema.validate(config);

Expand All @@ -74,7 +91,7 @@ export default class Provider {
'startPort',
'renameNode',
'relayUrl',
].forEach(key => {
].forEach((key) => {
this[key] = config[key];
});
}
Expand All @@ -83,11 +100,13 @@ export default class Provider {
if (this.startPort) {
return this.startPort++;
}
return globalPort++;
return 0;
}

// istanbul ignore next
public async getSubscriptionUserInfo(): Promise<SubscriptionUserinfo|undefined> {
public async getSubscriptionUserInfo(): Promise<
SubscriptionUserinfo | undefined
> {
throw new Error('此 Provider 不支持该功能');
}

Expand Down
12 changes: 12 additions & 0 deletions lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,12 @@ export const getSurgeNodes = function (
`local-port = ${config.localPort}`,
];

if (typeof config.provider?.startPort === 'undefined') {
throw new Error(
`为 Surge 生成 SSR 配置时必须为 Provider ${config.provider?.name} 设置 startPort`
);
}

if (config.hostnameIp && config.hostnameIp.length) {
configString.push(
...config.hostnameIp.map((item) => `addresses = ${item}`)
Expand Down Expand Up @@ -404,6 +410,12 @@ export const getSurgeNodes = function (
);
}

if (typeof config.provider?.startPort === 'undefined') {
throw new Error(
`为 Surge 生成 Vmess 配置时必须为 Provider ${config.provider?.name} 设置 startPort`
);
}

const jsonFileName = `v2ray_${config.localPort}_${config.hostname}_${config.port}.json`;
const jsonFilePath = join(ensureConfigFolder(), jsonFileName);
const jsonFile = formatV2rayConfig(
Expand Down

0 comments on commit 879080b

Please sign in to comment.