feat: machine mode, ECH subscriptions, batch ops & security hardening

This commit is contained in:
xboard
2026-04-17 02:27:47 +08:00
parent edbd8de356
commit e297b5fe9f
25 changed files with 1564 additions and 343 deletions
+112 -28
View File
@@ -25,6 +25,22 @@ class ServerSave extends FormRequest
'multiplex.brutal.down_mbps' => 'nullable|integer',
];
private const ECH_RULES = [
'enabled' => 'nullable|boolean',
'config' => 'nullable|string',
'query_server_name' => 'nullable|string',
'key' => 'nullable|string',
];
private const REALITY_RULES = [
'reality_settings.allow_insecure' => 'nullable|boolean',
'reality_settings.server_name' => 'nullable|string',
'reality_settings.server_port' => 'nullable|integer',
'reality_settings.public_key' => 'nullable|string',
'reality_settings.private_key' => 'nullable|string',
'reality_settings.short_id' => 'nullable|string',
];
private const PROTOCOL_RULES = [
'shadowsocks' => [
'cipher' => 'required|string',
@@ -38,8 +54,6 @@ class ServerSave extends FormRequest
'tls' => 'required|integer',
'network' => 'required|string',
'network_settings' => 'nullable|array',
'tls_settings.server_name' => 'nullable|string',
'tls_settings.allow_insecure' => 'nullable|boolean',
],
'trojan' => [
'tls' => 'nullable|integer',
@@ -47,12 +61,6 @@ class ServerSave extends FormRequest
'network_settings' => 'nullable|array',
'server_name' => 'nullable|string',
'allow_insecure' => 'nullable|boolean',
'reality_settings.allow_insecure' => 'nullable|boolean',
'reality_settings.server_name' => 'nullable|string',
'reality_settings.server_port' => 'nullable|integer',
'reality_settings.public_key' => 'nullable|string',
'reality_settings.private_key' => 'nullable|string',
'reality_settings.short_id' => 'nullable|string',
],
'hysteria' => [
'version' => 'required|integer',
@@ -60,8 +68,6 @@ class ServerSave extends FormRequest
'obfs.open' => 'nullable|boolean',
'obfs.type' => 'string|nullable',
'obfs.password' => 'string|nullable',
'tls.server_name' => 'nullable|string',
'tls.allow_insecure' => 'nullable|boolean',
'bandwidth.up' => 'nullable|integer',
'bandwidth.down' => 'nullable|integer',
'hop_interval' => 'integer|nullable',
@@ -73,30 +79,21 @@ class ServerSave extends FormRequest
'flow' => 'nullable|string',
'encryption' => 'nullable|array',
'encryption.enabled' => 'nullable|boolean',
'encryption.encryption' => 'nullable|string',
'encryption.decryption' => 'nullable|string',
'tls_settings.server_name' => 'nullable|string',
'tls_settings.allow_insecure' => 'nullable|boolean',
'reality_settings.allow_insecure' => 'nullable|boolean',
'reality_settings.server_name' => 'nullable|string',
'reality_settings.server_port' => 'nullable|integer',
'reality_settings.public_key' => 'nullable|string',
'reality_settings.private_key' => 'nullable|string',
'reality_settings.short_id' => 'nullable|string',
'encryption.encryption' => 'nullable|string',
'encryption.decryption' => 'nullable|string',
],
'socks' => [
'tls' => 'nullable|integer',
],
'naive' => [
'tls' => 'required|integer',
'tls_settings' => 'nullable|array',
],
'http' => [
'tls' => 'required|integer',
'tls_settings' => 'nullable|array',
],
'mieru' => [
'transport' => 'required|string|in:TCP,UDP',
'traffic_pattern' => 'string'
'traffic_pattern' => 'string',
],
'anytls' => [
'tls' => 'nullable|array',
@@ -116,6 +113,8 @@ class ServerSave extends FormRequest
'group_ids' => 'nullable|array',
'route_ids' => 'nullable|array',
'parent_id' => 'nullable|integer',
'machine_id' => 'nullable|integer',
'enabled' => 'nullable|boolean',
'host' => 'required',
'port' => 'required',
'server_port' => 'required',
@@ -136,15 +135,91 @@ class ServerSave extends FormRequest
];
}
private function getProtocolRules(string $type): array
{
$rules = self::PROTOCOL_RULES[$type] ?? [];
return match ($type) {
'vmess' => array_merge(
$rules,
$this->buildTlsSettingsRules(),
self::MULTIPLEX_RULES,
self::UTLS_RULES,
),
'trojan' => array_merge(
$rules,
$this->buildTlsSettingsRules(includeRoot: true),
self::REALITY_RULES,
self::MULTIPLEX_RULES,
self::UTLS_RULES,
),
'hysteria' => array_merge(
$rules,
$this->buildTlsObjectRules(),
),
'tuic' => array_merge(
$rules,
$this->buildTlsObjectRules(),
),
'vless' => array_merge(
$rules,
$this->buildTlsSettingsRules(),
self::REALITY_RULES,
self::MULTIPLEX_RULES,
self::UTLS_RULES,
),
'socks', 'naive', 'http' => array_merge(
$rules,
$this->buildTlsSettingsRules(includeRoot: $type !== 'socks'),
),
'anytls' => array_merge(
$rules,
$this->buildTlsObjectRules(includeRoot: true),
),
default => $rules,
};
}
private function buildTlsSettingsRules(bool $includeRoot = false): array
{
return array_merge(
$includeRoot ? ['tls_settings' => 'nullable|array'] : [],
[
'tls_settings.server_name' => 'nullable|string',
'tls_settings.allow_insecure' => 'nullable|boolean',
'tls_settings.ech' => 'nullable|array',
],
$this->prefixRules('tls_settings.ech.', self::ECH_RULES),
);
}
private function buildTlsObjectRules(bool $includeRoot = false): array
{
return array_merge(
$includeRoot ? ['tls' => 'nullable|array'] : [],
[
'tls.server_name' => 'nullable|string',
'tls.allow_insecure' => 'nullable|boolean',
'tls.ech' => 'nullable|array',
],
$this->prefixRules('tls.ech.', self::ECH_RULES),
);
}
private function prefixRules(string $prefix, array $rules): array
{
$result = [];
foreach ($rules as $field => $rule) {
$result[$prefix . $field] = $rule;
}
return $result;
}
public function rules(): array
{
$type = $this->input('type');
$rules = $this->getBaseRules();
$protocolRules = self::PROTOCOL_RULES[$type] ?? [];
if (in_array($type, ['vmess', 'vless', 'trojan', 'mieru'])) {
$protocolRules = array_merge($protocolRules, self::MULTIPLEX_RULES, self::UTLS_RULES);
}
$protocolRules = $this->getProtocolRules($type);
foreach ($protocolRules as $field => $rule) {
$rules['protocol_settings.' . $field] = $rule;
@@ -177,6 +252,14 @@ class ServerSave extends FormRequest
'protocol_settings.multiplex.brutal.down_mbps' => 'Brutal下行速率',
'protocol_settings.utls.enabled' => 'uTLS',
'protocol_settings.utls.fingerprint' => 'uTLS指纹',
'protocol_settings.tls_settings.ech.enabled' => 'ECH',
'protocol_settings.tls_settings.ech.config' => 'ECH配置',
'protocol_settings.tls_settings.ech.query_server_name' => 'ECH查询域名',
'protocol_settings.tls_settings.ech.key' => 'ECH密钥',
'protocol_settings.tls.ech.enabled' => 'ECH',
'protocol_settings.tls.ech.config' => 'ECH配置',
'protocol_settings.tls.ech.query_server_name' => 'ECH查询域名',
'protocol_settings.tls.ech.key' => 'ECH密钥',
];
}
@@ -202,6 +285,7 @@ class ServerSave extends FormRequest
'tlsSettings.array' => 'tls配置有误',
'dnsSettings.array' => 'dns配置有误',
'protocol_settings.*.required' => ':attribute 不能为空',
'protocol_settings.*.required_if' => ':attribute 不能为空',
'protocol_settings.*.string' => ':attribute 必须是字符串',
'protocol_settings.*.integer' => ':attribute 必须是整数',
'protocol_settings.*.in' => ':attribute 的值不合法',