feat(node): Add protocol

This commit is contained in:
web@ppanel 2024-12-11 13:37:10 +07:00
parent 1c619669a6
commit 301b635326
10 changed files with 8765 additions and 4100 deletions

View File

@ -0,0 +1,98 @@
import { z } from '@shadcn/ui/lib/zod';
export const protocols = ['shadowsocks', 'vmess', 'vless', 'trojan', 'hysteria2', 'tuic'];
const nullableString = z.string().nullish();
const portSchema = z.number().min(1).max(65535);
const securityConfigSchema = z
.object({
sni: nullableString,
allow_insecure: z.boolean().nullable().default(false),
fingerprint: nullableString,
reality_private_key: nullableString,
reality_public_key: nullableString,
reality_short_id: nullableString,
})
.nullish();
const transportConfigSchema = z
.object({
path: nullableString,
host: nullableString,
server_name: nullableString,
})
.nullish();
const baseProtocolSchema = z.object({
port: portSchema,
transport: z.string(),
transport_config: transportConfigSchema,
security: z.string(),
security_config: securityConfigSchema,
});
const shadowsocksSchema = z.object({
method: z.string(),
port: portSchema,
});
const vmessSchema = baseProtocolSchema;
const vlessSchema = baseProtocolSchema.extend({
flow: nullableString,
});
const trojanSchema = baseProtocolSchema;
const hysteria2Schema = z.object({
port: portSchema,
hop_ports: nullableString,
hop_interval: z.number().nullish(),
obfs_password: nullableString,
security_config: securityConfigSchema,
});
const tuicSchema = z.object({
port: portSchema,
security_config: securityConfigSchema,
});
const protocolConfigSchema = z.discriminatedUnion('protocol', [
z.object({
protocol: z.literal('shadowsocks'),
config: shadowsocksSchema,
}),
z.object({
protocol: z.literal('vmess'),
config: vmessSchema,
}),
z.object({
protocol: z.literal('vless'),
config: vlessSchema,
}),
z.object({
protocol: z.literal('trojan'),
config: trojanSchema,
}),
z.object({
protocol: z.literal('hysteria2'),
config: hysteria2Schema,
}),
z.object({
protocol: z.literal('tuic'),
config: tuicSchema,
}),
]);
const baseFormSchema = z.object({
name: z.string(),
server_addr: z.string(),
speed_limit: z.number().nullish(),
traffic_ratio: z.number().default(1),
group_id: z.number().nullish(),
enable_relay: z.boolean().nullish().default(false),
relay_host: nullableString,
relay_port: z.number().nullish(),
});
export const formSchema = z.intersection(baseFormSchema, protocolConfigSchema);

File diff suppressed because it is too large Load Diff

View File

@ -78,6 +78,8 @@ export default function NodeTable() {
'bg-rose-500': row.original.protocol === 'vmess', 'bg-rose-500': row.original.protocol === 'vmess',
'bg-blue-500': row.original.protocol === 'vless', 'bg-blue-500': row.original.protocol === 'vless',
'bg-yellow-500': row.original.protocol === 'trojan', 'bg-yellow-500': row.original.protocol === 'trojan',
'bg-purple-500': row.original.protocol === 'hysteria2',
'bg-cyan-500': row.original.protocol === 'tuic',
})} })}
> >
{row.getValue('id')} {row.getValue('id')}

View File

@ -41,8 +41,6 @@
"editNode": "Edit Node", "editNode": "Edit Node",
"enable": "Enable", "enable": "Enable",
"form": { "form": {
"Address or IP": "Address or IP",
"Host Name": "Host Name",
"allowInsecure": "Allow Insecure", "allowInsecure": "Allow Insecure",
"cancel": "Cancel", "cancel": "Cancel",
"confirm": "Confirm", "confirm": "Confirm",
@ -50,19 +48,24 @@
"editSecurity": "Edit Security Configuration", "editSecurity": "Edit Security Configuration",
"enableRelay": "Enable Relay", "enableRelay": "Enable Relay",
"enableTLS": "Enable TLS", "enableTLS": "Enable TLS",
"enableTls": "TLS",
"encryptionMethod": "Encryption Method", "encryptionMethod": "Encryption Method",
"flow": "Flow Control Algorithm",
"hopInterval": "Hop Interval",
"hopPorts": "Hop Ports",
"hopPortsPlaceholder": "Separate multiple ports with commas",
"name": "Name", "name": "Name",
"networkType": "Transport Protocol",
"nodeGroupId": "Node Group ID", "nodeGroupId": "Node Group ID",
"password": "Password", "obfsPassword": "Obfuscation Password",
"obfsPasswordPlaceholder": "Leave blank for no obfuscation",
"path": "Path", "path": "Path",
"pleaseSelect": "Please Select",
"port": "Server Port", "port": "Server Port",
"protocol": "Protocol", "protocol": "Protocol",
"relayHost": "Relay Host", "relayHost": "Relay Host",
"relayPort": "Relay Port", "relayPort": "Relay Port",
"remarks": "Remarks", "remarks": "Remarks",
"security": "Security", "security": "Security",
"securityConfig": "Security Configuration",
"security_config": { "security_config": {
"fingerprint": "Fingerprint", "fingerprint": "Fingerprint",
"privateKey": "Private Key", "privateKey": "Private Key",
@ -77,20 +80,22 @@
"serverPort": "Server Port", "serverPort": "Server Port",
"serverPortPlaceholder": "REALITY target port, default 443", "serverPortPlaceholder": "REALITY target port, default 443",
"shortId": "Short ID", "shortId": "Short ID",
"shortIdPlaceholder": "Leave blank for auto-generation" "shortIdPlaceholder": "Leave blank for auto-generation",
"sni": "Server Name Indication (SNI)"
}, },
"selectEncryptionMethod": "Select Encryption Method", "selectEncryptionMethod": "Select Encryption Method",
"selectNodeGroup": "Select Node Group", "selectNodeGroup": "Select Node Group",
"selectProtocol": "Select Protocol", "selectProtocol": "Select Protocol",
"serverAddr": "Server IP", "serverAddr": "Server IP",
"serverName": "Service Name", "serverName": "Service Name",
"serviceName": "Service Name",
"sni": "Server Name Indication (SNI)",
"speedLimit": "Speed Limit", "speedLimit": "Speed Limit",
"speedLimitPlaceholder": "Unlimited", "speedLimitPlaceholder": "Unlimited",
"trafficRatio": "Traffic Rate", "trafficRatio": "Traffic Rate",
"transport": "Transport Protocol Configuration", "transport": "Transport Protocol Configuration",
"xtls": "XTLS Flow Control Algorithm" "transportConfig": "Transport Protocol Configuration",
"transportHost": "Transport Server Address",
"transportPath": "Transport Path",
"transportServerName": "Transport Server Name"
}, },
"name": "Name", "name": "Name",
"node": "Node", "node": "Node",

View File

@ -41,8 +41,6 @@
"editNode": "编辑节点", "editNode": "编辑节点",
"enable": "启用", "enable": "启用",
"form": { "form": {
"Address or IP": "地址或IP",
"Host Name": "服务地址",
"allowInsecure": "允许不安全", "allowInsecure": "允许不安全",
"cancel": "取消", "cancel": "取消",
"confirm": "确认", "confirm": "确认",
@ -50,19 +48,24 @@
"editSecurity": "编辑安全性配置", "editSecurity": "编辑安全性配置",
"enableRelay": "启用中转", "enableRelay": "启用中转",
"enableTLS": "启用TLS", "enableTLS": "启用TLS",
"enableTls": "TLS",
"encryptionMethod": "加密方法", "encryptionMethod": "加密方法",
"flow": "流控算法",
"hopInterval": "中继间隔",
"hopPorts": "中继端口",
"hopPortsPlaceholder": "多个端口用逗号分隔",
"name": "名称", "name": "名称",
"networkType": "传输协议",
"nodeGroupId": "节点组ID", "nodeGroupId": "节点组ID",
"password": "密码", "obfsPassword": "混淆密码",
"obfsPasswordPlaceholder": "留空则不混淆",
"path": "路径", "path": "路径",
"pleaseSelect": "请选择",
"port": "服务端口", "port": "服务端口",
"protocol": "协议", "protocol": "协议",
"relayHost": "中转地址", "relayHost": "中转地址",
"relayPort": "中转端口", "relayPort": "中转端口",
"remarks": "备注", "remarks": "备注",
"security": "安全性", "security": "安全性",
"securityConfig": "安全性配置",
"security_config": { "security_config": {
"fingerprint": "FingerPrint", "fingerprint": "FingerPrint",
"privateKey": "Private Key", "privateKey": "Private Key",
@ -77,20 +80,22 @@
"serverPort": "Server Port", "serverPort": "Server Port",
"serverPortPlaceholder": "REALITY目标端口,默认443", "serverPortPlaceholder": "REALITY目标端口,默认443",
"shortId": "ShortId", "shortId": "ShortId",
"shortIdPlaceholder": "留空自动生成" "shortIdPlaceholder": "留空自动生成",
"sni": "服务器名称指示(sni)"
}, },
"selectEncryptionMethod": "选择加密方法", "selectEncryptionMethod": "选择加密方法",
"selectNodeGroup": "选择节点组", "selectNodeGroup": "选择节点组",
"selectProtocol": "选择协议", "selectProtocol": "选择协议",
"serverAddr": "服务器IP", "serverAddr": "服务器IP",
"serverName": "服务名称", "serverName": "服务名称",
"serviceName": "服务名称",
"sni": "服务器名称指示(sni)",
"speedLimit": "速度限制", "speedLimit": "速度限制",
"speedLimitPlaceholder": "无限制", "speedLimitPlaceholder": "无限制",
"trafficRatio": "流量速率", "trafficRatio": "流量速率",
"transport": "传输协议配置", "transport": "传输协议",
"xtls": "XTLS流控算法" "transportConfig": "传输协议配置",
"transportHost": "传输服务地址",
"transportPath": "传输路径",
"transportServerName": "传输服务名称"
}, },
"name": "名称", "name": "名称",
"node": "节点", "node": "节点",

View File

@ -112,15 +112,15 @@ declare namespace API {
type CreateNodeRequest = { type CreateNodeRequest = {
name: string; name: string;
server_addr: string; server_addr: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
speed_limit: number; speed_limit: number;
traffic_ratio: number; traffic_ratio: number;
groupId: number; group_id: number;
protocol: string; protocol: string;
config: Record<string, any>;
enable: boolean; enable: boolean;
vmess?: Vmess;
vless?: Vless;
trojan?: Trojan;
shadowsocks?: Shadowsocks;
}; };
type CreateOrderRequest = { type CreateOrderRequest = {
@ -467,6 +467,14 @@ declare namespace API {
list: User[]; list: User[];
}; };
type Hysteria2 = {
port: number;
hop_ports: string;
hop_interval: number;
obfs_password: string;
security_config: SecurityConfig;
};
type InviteConfig = { type InviteConfig = {
forced_invite: boolean; forced_invite: boolean;
referral_percentage: number; referral_percentage: number;
@ -559,29 +567,27 @@ declare namespace API {
}; };
type SecurityConfig = { type SecurityConfig = {
server_address?: string; sni: string;
server_name?: string; allow_insecure: boolean;
server_port?: number; fingerprint: string;
fingerprint?: string; reality_private_key: string;
private_key?: string; reality_public_key: string;
public_key?: string; reality_short_id: string;
short_id?: string;
allow_insecure?: boolean;
}; };
type Server = { type Server = {
id: number; id: number;
name: string; name: string;
server_addr: string; server_addr: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
speed_limit: number; speed_limit: number;
traffic_ratio: number; traffic_ratio: number;
groupId: number; group_id: number;
protocol: string; protocol: string;
config: Record<string, any>;
enable: boolean; enable: boolean;
vmess?: Vmess;
vless?: Vless;
trojan?: Trojan;
shadowsocks?: Shadowsocks;
created_at: number; created_at: number;
updated_at: number; updated_at: number;
last: Push; last: Push;
@ -598,9 +604,7 @@ declare namespace API {
type Shadowsocks = { type Shadowsocks = {
method: string; method: string;
port: number; port: number;
enable_relay: boolean; server_key: string;
relay_host: string;
relay_port: number;
}; };
type SiteConfig = { type SiteConfig = {
@ -676,25 +680,27 @@ declare namespace API {
updated_at: number; updated_at: number;
}; };
type TLSConfig = {
server_name?: string;
allow_insecure?: boolean;
};
type TosConfig = { type TosConfig = {
tos_content: string; tos_content: string;
}; };
type Trojan = { type TransportConfig = {
network: string; path: string;
port: number;
host: string; host: string;
sni: string; server_name: string;
allow_insecure: boolean; };
transport: Record<string, any>;
enable_relay: boolean; type Trojan = {
relay_host: string; port: number;
relay_port: number; transport: string;
transport_config: TransportConfig;
security: string;
security_config: SecurityConfig;
};
type Tuic = {
port: number;
security_config: SecurityConfig;
}; };
type UpdateAnnouncementEnableRequest = { type UpdateAnnouncementEnableRequest = {
@ -750,15 +756,15 @@ declare namespace API {
id: number; id: number;
name: string; name: string;
server_addr: string; server_addr: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
speed_limit: number; speed_limit: number;
traffic_ratio: number; traffic_ratio: number;
groupId: number; group_id: number;
protocol: string; protocol: string;
config: Record<string, any>;
enable: boolean; enable: boolean;
vmess?: Vmess;
vless?: Vless;
trojan?: Trojan;
shadowsocks?: Shadowsocks;
}; };
type UpdateOrderStatusRequest = { type UpdateOrderStatusRequest = {
@ -884,27 +890,19 @@ declare namespace API {
}; };
type Vless = { type Vless = {
host: string;
port: number; port: number;
network: string; flow: string;
transport: Record<string, any>; transport: string;
transport_config: TransportConfig;
security: string; security: string;
security_config: SecurityConfig; security_config: SecurityConfig;
xtls: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
}; };
type Vmess = { type Vmess = {
host: string;
port: number; port: number;
enable_tls: boolean; transport: string;
tls_config: TLSConfig; transport_config: TransportConfig;
network: string; security: string;
transport: Record<string, any>; security_config: SecurityConfig;
enable_relay: boolean;
relay_host: string;
relay_port: number;
}; };
} }

View File

@ -115,6 +115,14 @@ declare namespace API {
tos_content: string; tos_content: string;
}; };
type Hysteria2 = {
port: number;
hop_ports: string;
hop_interval: number;
obfs_password: string;
security_config: SecurityConfig;
};
type InviteConfig = { type InviteConfig = {
forced_invite: boolean; forced_invite: boolean;
referral_percentage: number; referral_percentage: number;
@ -218,14 +226,12 @@ declare namespace API {
}; };
type SecurityConfig = { type SecurityConfig = {
server_address?: string; sni: string;
server_name?: string; allow_insecure: boolean;
server_port?: number; fingerprint: string;
fingerprint?: string; reality_private_key: string;
private_key?: string; reality_public_key: string;
public_key?: string; reality_short_id: string;
short_id?: string;
allow_insecure?: boolean;
}; };
type SendCodeRequest = { type SendCodeRequest = {
@ -241,15 +247,15 @@ declare namespace API {
id: number; id: number;
name: string; name: string;
server_addr: string; server_addr: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
speed_limit: number; speed_limit: number;
traffic_ratio: number; traffic_ratio: number;
groupId: number; group_id: number;
protocol: string; protocol: string;
config: Record<string, any>;
enable: boolean; enable: boolean;
vmess?: Vmess;
vless?: Vless;
trojan?: Trojan;
shadowsocks?: Shadowsocks;
created_at: number; created_at: number;
updated_at: number; updated_at: number;
last: Push; last: Push;
@ -266,9 +272,7 @@ declare namespace API {
type Shadowsocks = { type Shadowsocks = {
method: string; method: string;
port: number; port: number;
enable_relay: boolean; server_key: string;
relay_host: string;
relay_port: number;
}; };
type SiteConfig = { type SiteConfig = {
@ -340,25 +344,27 @@ declare namespace API {
updated_at: number; updated_at: number;
}; };
type TLSConfig = {
server_name?: string;
allow_insecure?: boolean;
};
type TosConfig = { type TosConfig = {
tos_content: string; tos_content: string;
}; };
type Trojan = { type TransportConfig = {
network: string; path: string;
port: number;
host: string; host: string;
sni: string; server_name: string;
allow_insecure: boolean; };
transport: Record<string, any>;
enable_relay: boolean; type Trojan = {
relay_host: string; port: number;
relay_port: number; transport: string;
transport_config: TransportConfig;
security: string;
security_config: SecurityConfig;
};
type Tuic = {
port: number;
security_config: SecurityConfig;
}; };
type User = { type User = {
@ -448,27 +454,19 @@ declare namespace API {
}; };
type Vless = { type Vless = {
host: string;
port: number; port: number;
network: string; flow: string;
transport: Record<string, any>; transport: string;
transport_config: TransportConfig;
security: string; security: string;
security_config: SecurityConfig; security_config: SecurityConfig;
xtls: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
}; };
type Vmess = { type Vmess = {
host: string;
port: number; port: number;
enable_tls: boolean; transport: string;
tls_config: TLSConfig; transport_config: TransportConfig;
network: string; security: string;
transport: Record<string, any>; security_config: SecurityConfig;
enable_relay: boolean;
relay_host: string;
relay_port: number;
}; };
} }

View File

@ -115,6 +115,14 @@ declare namespace API {
tos_content: string; tos_content: string;
}; };
type Hysteria2 = {
port: number;
hop_ports: string;
hop_interval: number;
obfs_password: string;
security_config: SecurityConfig;
};
type InviteConfig = { type InviteConfig = {
forced_invite: boolean; forced_invite: boolean;
referral_percentage: number; referral_percentage: number;
@ -218,14 +226,12 @@ declare namespace API {
}; };
type SecurityConfig = { type SecurityConfig = {
server_address?: string; sni: string;
server_name?: string; allow_insecure: boolean;
server_port?: number; fingerprint: string;
fingerprint?: string; reality_private_key: string;
private_key?: string; reality_public_key: string;
public_key?: string; reality_short_id: string;
short_id?: string;
allow_insecure?: boolean;
}; };
type SendCodeRequest = { type SendCodeRequest = {
@ -241,15 +247,15 @@ declare namespace API {
id: number; id: number;
name: string; name: string;
server_addr: string; server_addr: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
speed_limit: number; speed_limit: number;
traffic_ratio: number; traffic_ratio: number;
groupId: number; group_id: number;
protocol: string; protocol: string;
config: Record<string, any>;
enable: boolean; enable: boolean;
vmess?: Vmess;
vless?: Vless;
trojan?: Trojan;
shadowsocks?: Shadowsocks;
created_at: number; created_at: number;
updated_at: number; updated_at: number;
last: Push; last: Push;
@ -266,9 +272,7 @@ declare namespace API {
type Shadowsocks = { type Shadowsocks = {
method: string; method: string;
port: number; port: number;
enable_relay: boolean; server_key: string;
relay_host: string;
relay_port: number;
}; };
type SiteConfig = { type SiteConfig = {
@ -340,25 +344,27 @@ declare namespace API {
updated_at: number; updated_at: number;
}; };
type TLSConfig = {
server_name?: string;
allow_insecure?: boolean;
};
type TosConfig = { type TosConfig = {
tos_content: string; tos_content: string;
}; };
type Trojan = { type TransportConfig = {
network: string; path: string;
port: number;
host: string; host: string;
sni: string; server_name: string;
allow_insecure: boolean; };
transport: Record<string, any>;
enable_relay: boolean; type Trojan = {
relay_host: string; port: number;
relay_port: number; transport: string;
transport_config: TransportConfig;
security: string;
security_config: SecurityConfig;
};
type Tuic = {
port: number;
security_config: SecurityConfig;
}; };
type User = { type User = {
@ -448,27 +454,19 @@ declare namespace API {
}; };
type Vless = { type Vless = {
host: string;
port: number; port: number;
network: string; flow: string;
transport: Record<string, any>; transport: string;
transport_config: TransportConfig;
security: string; security: string;
security_config: SecurityConfig; security_config: SecurityConfig;
xtls: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
}; };
type Vmess = { type Vmess = {
host: string;
port: number; port: number;
enable_tls: boolean; transport: string;
tls_config: TLSConfig; transport_config: TransportConfig;
network: string; security: string;
transport: Record<string, any>; security_config: SecurityConfig;
enable_relay: boolean;
relay_host: string;
relay_port: number;
}; };
} }

View File

@ -136,6 +136,14 @@ declare namespace API {
list: Ticket[]; list: Ticket[];
}; };
type Hysteria2 = {
port: number;
hop_ports: string;
hop_interval: number;
obfs_password: string;
security_config: SecurityConfig;
};
type InviteConfig = { type InviteConfig = {
forced_invite: boolean; forced_invite: boolean;
referral_percentage: number; referral_percentage: number;
@ -360,29 +368,27 @@ declare namespace API {
}; };
type SecurityConfig = { type SecurityConfig = {
server_address?: string; sni: string;
server_name?: string; allow_insecure: boolean;
server_port?: number; fingerprint: string;
fingerprint?: string; reality_private_key: string;
private_key?: string; reality_public_key: string;
public_key?: string; reality_short_id: string;
short_id?: string;
allow_insecure?: boolean;
}; };
type Server = { type Server = {
id: number; id: number;
name: string; name: string;
server_addr: string; server_addr: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
speed_limit: number; speed_limit: number;
traffic_ratio: number; traffic_ratio: number;
groupId: number; group_id: number;
protocol: string; protocol: string;
config: Record<string, any>;
enable: boolean; enable: boolean;
vmess?: Vmess;
vless?: Vless;
trojan?: Trojan;
shadowsocks?: Shadowsocks;
created_at: number; created_at: number;
updated_at: number; updated_at: number;
last: Push; last: Push;
@ -399,9 +405,7 @@ declare namespace API {
type Shadowsocks = { type Shadowsocks = {
method: string; method: string;
port: number; port: number;
enable_relay: boolean; server_key: string;
relay_host: string;
relay_port: number;
}; };
type SiteConfig = { type SiteConfig = {
@ -479,25 +483,27 @@ declare namespace API {
updated_at: number; updated_at: number;
}; };
type TLSConfig = {
server_name?: string;
allow_insecure?: boolean;
};
type TosConfig = { type TosConfig = {
tos_content: string; tos_content: string;
}; };
type Trojan = { type TransportConfig = {
network: string; path: string;
port: number;
host: string; host: string;
sni: string; server_name: string;
allow_insecure: boolean; };
transport: Record<string, any>;
enable_relay: boolean; type Trojan = {
relay_host: string; port: number;
relay_port: number; transport: string;
transport_config: TransportConfig;
security: string;
security_config: SecurityConfig;
};
type Tuic = {
port: number;
security_config: SecurityConfig;
}; };
type UpdateUserNotifyRequest = { type UpdateUserNotifyRequest = {
@ -588,27 +594,19 @@ declare namespace API {
}; };
type Vless = { type Vless = {
host: string;
port: number; port: number;
network: string; flow: string;
transport: Record<string, any>; transport: string;
transport_config: TransportConfig;
security: string; security: string;
security_config: SecurityConfig; security_config: SecurityConfig;
xtls: string;
enable_relay: boolean;
relay_host: string;
relay_port: number;
}; };
type Vmess = { type Vmess = {
host: string;
port: number; port: number;
enable_tls: boolean; transport: string;
tls_config: TLSConfig; transport_config: TransportConfig;
network: string; security: string;
transport: Record<string, any>; security_config: SecurityConfig;
enable_relay: boolean;
relay_host: string;
relay_port: number;
}; };
} }

10601
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff