diff --git a/apps/admin/src/sections/servers/form-schema/defaults.ts b/apps/admin/src/sections/servers/form-schema/defaults.ts
index 6b6f93a..828ba96 100644
--- a/apps/admin/src/sections/servers/form-schema/defaults.ts
+++ b/apps/admin/src/sections/servers/form-schema/defaults.ts
@@ -31,6 +31,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
path: null,
service_name: null,
sni: null,
+ ech_enable: null,
+ ech_server_name: null,
allow_insecure: null,
fingerprint: "chrome",
cert_mode: "none",
@@ -50,6 +52,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
path: null,
service_name: null,
sni: null,
+ ech_enable: null,
+ ech_server_name: null,
allow_insecure: null,
fingerprint: "chrome",
reality_server_addr: null,
@@ -83,6 +87,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
path: null,
service_name: null,
sni: null,
+ ech_enable: null,
+ ech_server_name: null,
allow_insecure: null,
fingerprint: "chrome",
cert_mode: "none",
@@ -103,6 +109,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
up_mbps: null,
down_mbps: null,
sni: null,
+ ech_enable: null,
+ ech_server_name: null,
allow_insecure: null,
fingerprint: "chrome",
cert_mode: "none",
@@ -121,6 +129,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
congestion_controller: "bbr",
security: "tls",
sni: null,
+ ech_enable: null,
+ ech_server_name: null,
allow_insecure: false,
fingerprint: "chrome",
cert_mode: "none",
@@ -142,6 +152,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
port: null,
security: "none",
sni: null,
+ ech_enable: null,
+ ech_server_name: null,
allow_insecure: null,
fingerprint: "chrome",
cert_mode: "none",
@@ -156,6 +168,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
port: null,
security: "none",
sni: null,
+ ech_enable: null,
+ ech_server_name: null,
allow_insecure: null,
fingerprint: "chrome",
cert_mode: "none",
@@ -179,6 +193,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
security: "tls",
padding_scheme: null,
sni: null,
+ ech_enable: null,
+ ech_server_name: null,
allow_insecure: false,
fingerprint: "chrome",
cert_mode: "none",
diff --git a/apps/admin/src/sections/servers/form-schema/schemas.ts b/apps/admin/src/sections/servers/form-schema/schemas.ts
index f54515a..354c98b 100644
--- a/apps/admin/src/sections/servers/form-schema/schemas.ts
+++ b/apps/admin/src/sections/servers/form-schema/schemas.ts
@@ -50,6 +50,8 @@ const vmess = z.object({
cert_mode: z.enum(CERT_MODES).nullish(),
cert_dns_provider: nullableString,
cert_dns_env: nullableString,
+ ech_enable: z.boolean().nullish(),
+ ech_server_name: nullableString,
});
const vless = z.object({
@@ -84,6 +86,8 @@ const vless = z.object({
cert_mode: z.enum(CERT_MODES).nullish(),
cert_dns_provider: nullableString,
cert_dns_env: nullableString,
+ ech_enable: z.boolean().nullish(),
+ ech_server_name: nullableString,
});
const trojan = z.object({
@@ -102,6 +106,8 @@ const trojan = z.object({
cert_mode: z.enum(CERT_MODES).nullish(),
cert_dns_provider: nullableString,
cert_dns_env: nullableString,
+ ech_enable: z.boolean().nullish(),
+ ech_server_name: nullableString,
});
const hysteria = z.object({
@@ -122,6 +128,8 @@ const hysteria = z.object({
cert_mode: z.enum(CERT_MODES).nullish(),
cert_dns_provider: nullableString,
cert_dns_env: nullableString,
+ ech_enable: z.boolean().nullish(),
+ ech_server_name: nullableString,
});
const tuic = z.object({
@@ -141,6 +149,8 @@ const tuic = z.object({
cert_mode: z.enum(CERT_MODES).nullish(),
cert_dns_provider: nullableString,
cert_dns_env: nullableString,
+ ech_enable: z.boolean().nullish(),
+ ech_server_name: nullableString,
});
const anytls = z.object({
@@ -156,6 +166,8 @@ const anytls = z.object({
cert_mode: z.enum(CERT_MODES).nullish(),
cert_dns_provider: nullableString,
cert_dns_env: nullableString,
+ ech_enable: z.boolean().nullish(),
+ ech_server_name: nullableString,
reality_server_addr: nullableString,
reality_server_port: nullablePort,
reality_private_key: nullableString,
@@ -182,6 +194,8 @@ const naive = z.object({
cert_mode: z.enum(CERT_MODES).nullish(),
cert_dns_provider: nullableString,
cert_dns_env: nullableString,
+ ech_enable: z.boolean().nullish(),
+ ech_server_name: nullableString,
});
const http = z.object({
@@ -196,6 +210,8 @@ const http = z.object({
cert_mode: z.enum(CERT_MODES).nullish(),
cert_dns_provider: nullableString,
cert_dns_env: nullableString,
+ ech_enable: z.boolean().nullish(),
+ ech_server_name: nullableString,
});
const mieru = z.object({
diff --git a/apps/admin/src/sections/servers/form-schema/useProtocolFields.ts b/apps/admin/src/sections/servers/form-schema/useProtocolFields.ts
index 9319b0f..c1da2b2 100644
--- a/apps/admin/src/sections/servers/form-schema/useProtocolFields.ts
+++ b/apps/admin/src/sections/servers/form-schema/useProtocolFields.ts
@@ -246,6 +246,23 @@ export function useProtocolFields() {
group: "security",
condition: (p) => p.security === "tls" && p.cert_mode === "dns",
},
+ {
+ name: "ech_enable",
+ type: "select",
+ label: t("ech_enable", "ECH Enable"),
+ options: ["false", "true"],
+ defaultValue: "false",
+ group: "security",
+ condition: (p) => p.security === "tls",
+ },
+ {
+ name: "ech_server_name",
+ type: "input",
+ label: t("ech_server_name", "ECH Server Name"),
+ placeholder: "e.g. cloudflare-ech.com",
+ group: "security",
+ condition: (p) => p.security === "tls" && p.ech_enable === true,
+ },
],
vless: [
{
@@ -539,6 +556,23 @@ export function useProtocolFields() {
group: "security",
condition: (p) => p.security === "tls" && p.cert_mode === "dns",
},
+ {
+ name: "ech_enable",
+ type: "select",
+ label: t("ech_enable", "ECH Enable"),
+ options: ["false", "true"],
+ defaultValue: "false",
+ group: "security",
+ condition: (p) => p.security === "tls",
+ },
+ {
+ name: "ech_server_name",
+ type: "input",
+ label: t("ech_server_name", "ECH Server Name"),
+ placeholder: "e.g. cloudflare-ech.com",
+ group: "security",
+ condition: (p) => p.security === "tls" && p.ech_enable === true,
+ },
],
trojan: [
{
@@ -650,6 +684,23 @@ export function useProtocolFields() {
group: "security",
condition: (p) => p.security === "tls" && p.cert_mode === "dns",
},
+ {
+ name: "ech_enable",
+ type: "select",
+ label: t("ech_enable", "ECH Enable"),
+ options: ["false", "true"],
+ defaultValue: "false",
+ group: "security",
+ condition: (p) => p.security === "tls",
+ },
+ {
+ name: "ech_server_name",
+ type: "input",
+ label: t("ech_server_name", "ECH Server Name"),
+ placeholder: "e.g. cloudflare-ech.com",
+ group: "security",
+ condition: (p) => p.security === "tls" && p.ech_enable === true,
+ },
],
hysteria: [
{
@@ -971,6 +1022,23 @@ export function useProtocolFields() {
group: "security",
condition: (p) => p.security === "tls" && p.cert_mode === "dns",
},
+ {
+ name: "ech_enable",
+ type: "select",
+ label: t("ech_enable", "ECH Enable"),
+ options: ["false", "true"],
+ defaultValue: "false",
+ group: "security",
+ condition: (p) => p.security === "tls",
+ },
+ {
+ name: "ech_server_name",
+ type: "input",
+ label: t("ech_server_name", "ECH Server Name"),
+ placeholder: "e.g. cloudflare-ech.com",
+ group: "security",
+ condition: (p) => p.security === "tls" && p.ech_enable === true,
+ },
],
http: [
{
diff --git a/apps/admin/src/sections/servers/server-form.tsx b/apps/admin/src/sections/servers/server-form.tsx
index 3332b1a..93c83ad 100644
--- a/apps/admin/src/sections/servers/server-form.tsx
+++ b/apps/admin/src/sections/servers/server-form.tsx
@@ -234,8 +234,19 @@ function DynamicField({
{getFieldLabel(field)}