diff --git a/frontend/src/lib/xray/inbound-link.ts b/frontend/src/lib/xray/inbound-link.ts index 005edd075..638af5314 100644 --- a/frontend/src/lib/xray/inbound-link.ts +++ b/frontend/src/lib/xray/inbound-link.ts @@ -1,6 +1,7 @@ import { Base64, Wireguard } from '@/utils'; import type { Inbound } from '@/schemas/api/inbound'; +import type { AmneziawgInboundSettings } from '@/schemas/protocols/inbound/amneziawg'; import type { VlessClient } from '@/schemas/protocols/inbound/vless'; import type { VmessSecurity } from '@/schemas/protocols/shared/vmess'; import type { @@ -869,6 +870,134 @@ export function genWireguardConfig(input: GenWireguardLinkInput): string { return txt; } +// Shared input shape for both the per-client amneziawg:// link and .conf +// builders below — settings.clients (not a peers array; unlike WireGuard, +// AmneziaWG was multi-client from day one, so there's no legacy format). +export interface GenAmneziaWGLinkInput { + settings: AmneziawgInboundSettings; + address: string; + port: number; + remark?: string; + peerIndex: number; +} + +function amneziaWGHLine(key: string, value: string | undefined, fallback: string): string { + return `${key} = ${value && value.trim() !== '' ? value : fallback}`; +} + +// AmneziaWG share link: amneziawg://@: +// ?publickey=&address=&mtu=# +// Unlike WireGuard, the server's publicKey is a real persisted field (not +// derived from a secretKey at call time), so this just reads it straight off +// settings.server. Mirrors genWireguardLink. +export function genAmneziaWGLink(input: GenAmneziaWGLinkInput): string { + const { settings, address, port, remark = '', peerIndex } = input; + const client = settings.clients[peerIndex]; + if (!client) return ''; + const server = settings.server; + + const url = new URL(`amneziawg://${formatUrlHost(address)}:${port}`); + url.username = client.privateKey ?? ''; + + if (server.publicKey.length > 0) url.searchParams.set('publickey', server.publicKey); + if ((client.allowedIPs ?? []).length > 0) { + url.searchParams.set('address', client.allowedIPs.join(',')); + } + if (typeof server.mtu === 'number' && server.mtu > 0) { + url.searchParams.set('mtu', String(server.mtu)); + } + + url.hash = encodeURIComponent(remark); + return url.toString(); +} + +// Plain-text AmneziaWG client config (.conf format). Mirrors +// genWireguardConfig, plus the obfuscation lines every AmneziaWG client must +// share with the server (see internal/amneziawg.writeObfuscation on the Go +// side). +export function genAmneziaWGConfig(input: GenAmneziaWGLinkInput): string { + const { settings, address, port, remark = '', peerIndex } = input; + const client = settings.clients[peerIndex]; + if (!client) return ''; + const server = settings.server; + + let txt = `[Interface]\n`; + txt += `PrivateKey = ${client.privateKey ?? ''}\n`; + txt += `Address = ${(client.allowedIPs ?? []).join(', ')}\n`; + const dns = [server.primaryDns, server.secondaryDns].filter((v) => !!v && v.trim() !== ''); + if (dns.length > 0) txt += `DNS = ${dns.join(', ')}\n`; + if (typeof server.mtu === 'number' && server.mtu > 0) { + txt += `MTU = ${server.mtu}\n`; + } + txt += `Jc = ${server.jc}\n`; + txt += `Jmin = ${server.jmin}\n`; + txt += `Jmax = ${server.jmax}\n`; + txt += `S1 = ${server.s1}\n`; + txt += `S2 = ${server.s2}\n`; + if (server.s3) txt += `S3 = ${server.s3}\n`; + if (server.s4) txt += `S4 = ${server.s4}\n`; + txt += `${amneziaWGHLine('H1', server.h1, '1')}\n`; + txt += `${amneziaWGHLine('H2', server.h2, '2')}\n`; + txt += `${amneziaWGHLine('H3', server.h3, '3')}\n`; + txt += `${amneziaWGHLine('H4', server.h4, '4')}\n`; + if (server.i1) txt += `I1 = ${server.i1}\n`; + txt += `\n# ${remark}\n`; + txt += `[Peer]\n`; + txt += `PublicKey = ${server.publicKey ?? ''}\n`; + txt += `AllowedIPs = 0.0.0.0/0, ::/0\n`; + txt += `Endpoint = ${address}:${port}`; + if (client.preSharedKey && client.preSharedKey.length > 0) { + txt += `\nPresharedKey = ${client.preSharedKey}`; + } + if (typeof client.keepAlive === 'number' && client.keepAlive > 0) { + txt += `\nPersistentKeepalive = ${client.keepAlive}\n`; + } + return txt; +} + +export interface GenAmneziaWGFanoutInput { + inbound: Inbound; + remark?: string; + hostOverride?: string; + fallbackHostname: string; +} + +export function genAmneziaWGLinks(input: GenAmneziaWGFanoutInput): string { + const { inbound, remark = '', hostOverride = '', fallbackHostname } = input; + if (inbound.protocol !== 'amneziawg') return ''; + const addr = resolveAddr(inbound, hostOverride, fallbackHostname); + const sep = '-'; + const settings = inbound.settings as AmneziawgInboundSettings; + const clients = settings.clients ?? []; + return clients + .map((c, i) => genAmneziaWGLink({ + settings, + address: addr, + port: inbound.port, + remark: `${remark}${sep}${i + 1}${wgPeerCommentSuffix(c)}`, + peerIndex: i, + })) + .join('\r\n'); +} + +export function genAmneziaWGConfigs(input: GenAmneziaWGFanoutInput): string { + const { inbound, remark = '', hostOverride = '', fallbackHostname } = input; + if (inbound.protocol !== 'amneziawg') return ''; + const addr = resolveAddr(inbound, hostOverride, fallbackHostname); + const sep = '-'; + const settings = inbound.settings as AmneziawgInboundSettings; + const clients = settings.clients ?? []; + return clients + .map((c, i) => genAmneziaWGConfig({ + settings, + address: addr, + port: inbound.port, + remark: `${remark}${sep}${i + 1}${wgPeerCommentSuffix(c)}`, + peerIndex: i, + })) + .join('\r\n'); +} + export function wireguardConfigFromLink(link: string, fallbackRemark = ''): string { let url: URL; try { @@ -1201,7 +1330,7 @@ export interface GenInboundLinksInput { // Top-level entrypoint that produces the full \r\n-joined block a user // pastes into a client. Iterates per-client for protocols with clients, // falls back to a single SS link for single-user 2022-blake3-chacha20, -// and emits per-peer .conf blocks for wireguard. Returns '' for the +// and emits per-peer .conf blocks for wireguard and amneziawg. Returns '' for the // other clientless protocols (http, mixed, tunnel). export function genInboundLinks(input: GenInboundLinksInput): string { const { @@ -1226,6 +1355,9 @@ export function genInboundLinks(input: GenInboundLinksInput): string { if (inbound.protocol === 'wireguard') { return genWireguardConfigs({ inbound, remark, hostOverride, fallbackHostname }); } + if (inbound.protocol === 'amneziawg') { + return genAmneziaWGConfigs({ inbound, remark, hostOverride, fallbackHostname }); + } return ''; } diff --git a/frontend/src/lib/xray/inbound-tag.ts b/frontend/src/lib/xray/inbound-tag.ts index 8f4901ae8..8da1f0324 100644 --- a/frontend/src/lib/xray/inbound-tag.ts +++ b/frontend/src/lib/xray/inbound-tag.ts @@ -14,7 +14,7 @@ function inboundTransports( streamSettings: Record | undefined, settings: Record | undefined, ): TransportBits { - if (protocol === 'hysteria' || protocol === 'wireguard') return UDP; + if (protocol === 'hysteria' || protocol === 'wireguard' || protocol === 'amneziawg') return UDP; let bits: TransportBits = 0; const network = asString(streamSettings?.network); diff --git a/frontend/src/pages/clients/BulkAttachInboundsModal.tsx b/frontend/src/pages/clients/BulkAttachInboundsModal.tsx index 81730f9d4..efb9ebfa9 100644 --- a/frontend/src/pages/clients/BulkAttachInboundsModal.tsx +++ b/frontend/src/pages/clients/BulkAttachInboundsModal.tsx @@ -7,7 +7,7 @@ import type { InboundOption } from '@/hooks/useClients'; import { formatInboundLabel } from '@/lib/inbounds/label'; import type { BulkAttachResult } from '@/schemas/client'; -const MULTI_USER_PROTOCOLS = new Set(['vmess', 'vless', 'trojan', 'hysteria', 'shadowsocks', 'wireguard', 'mtproto']); +const MULTI_USER_PROTOCOLS = new Set(['vmess', 'vless', 'trojan', 'hysteria', 'shadowsocks', 'wireguard', 'mtproto', 'amneziawg']); interface BulkAttachInboundsModalProps { open: boolean; diff --git a/frontend/src/pages/clients/BulkDetachInboundsModal.tsx b/frontend/src/pages/clients/BulkDetachInboundsModal.tsx index 0cdcabe6f..35a2c78fe 100644 --- a/frontend/src/pages/clients/BulkDetachInboundsModal.tsx +++ b/frontend/src/pages/clients/BulkDetachInboundsModal.tsx @@ -7,7 +7,7 @@ import type { InboundOption } from '@/hooks/useClients'; import { formatInboundLabel } from '@/lib/inbounds/label'; import type { BulkDetachResult } from '@/schemas/client'; -const MULTI_USER_PROTOCOLS = new Set(['vmess', 'vless', 'trojan', 'hysteria', 'shadowsocks', 'wireguard', 'mtproto']); +const MULTI_USER_PROTOCOLS = new Set(['vmess', 'vless', 'trojan', 'hysteria', 'shadowsocks', 'wireguard', 'mtproto', 'amneziawg']); interface BulkDetachInboundsModalProps { open: boolean; diff --git a/frontend/src/pages/clients/ClientBulkAddModal.tsx b/frontend/src/pages/clients/ClientBulkAddModal.tsx index 6f5083cc3..fe1e0517b 100644 --- a/frontend/src/pages/clients/ClientBulkAddModal.tsx +++ b/frontend/src/pages/clients/ClientBulkAddModal.tsx @@ -18,7 +18,7 @@ import { ClientBulkAddFormSchema, type ClientBulkAddFormValues } from '@/schemas const FLOW_OPTIONS = Object.values(TLS_FLOW_CONTROL); const MULTI_CLIENT_PROTOCOLS = new Set([ - 'shadowsocks', 'vless', 'vmess', 'trojan', 'hysteria', 'wireguard', + 'shadowsocks', 'vless', 'vmess', 'trojan', 'hysteria', 'wireguard', 'amneziawg', ]); const EMPTY: ClientBulkAddFormValues = { diff --git a/frontend/src/pages/clients/ClientInfoModal.tsx b/frontend/src/pages/clients/ClientInfoModal.tsx index d09c9990c..e190978cd 100644 --- a/frontend/src/pages/clients/ClientInfoModal.tsx +++ b/frontend/src/pages/clients/ClientInfoModal.tsx @@ -13,6 +13,7 @@ import { LinkTags, linkMetaText, parseLinkParts } from '@/lib/xray/link-label'; import { QrPanel } from '@/pages/inbounds/qr'; import ConfigBlock from '@/components/clients/ConfigBlock'; import { buildWireguardClientConfig, findWireguardInbound, isWireguardClient } from './wireguardConfig'; +import { buildAmneziaWGClientConfig, findAmneziaWGInbound, isAmneziaWGClient } from './amneziawgConfig'; import './ClientInfoModal.css'; const INBOUND_PROTOCOL_COLORS: Record = { @@ -23,6 +24,7 @@ const INBOUND_PROTOCOL_COLORS: Record = { hysteria: 'cyan', hysteria2: 'green', wireguard: 'gold', + amneziawg: 'yellow', http: 'purple', mixed: 'lime', tunnel: 'orange', @@ -149,6 +151,12 @@ export default function ClientInfoModal({ return buildWireguardClientConfig(client, wgInbound, window.location.hostname, subSettings?.publicHost ?? ''); }, [client, wgInbound, subSettings?.publicHost]); + const awgInbound = useMemo(() => findAmneziaWGInbound(client, inboundsById), [client, inboundsById]); + const awgConfigText = useMemo(() => { + if (!client || !awgInbound || !isAmneziaWGClient(client)) return ''; + return buildAmneziaWGClientConfig(client, awgInbound, window.location.hostname, subSettings?.publicHost ?? ''); + }, [client, awgInbound, subSettings?.publicHost]); + async function copyValue(text: string) { if (!text) return; const ok = await ClipboardManager.copyText(String(text)); @@ -538,6 +546,18 @@ export default function ClientInfoModal({ /> )} + + {awgConfigText && client && ( + <> + {t('pages.clients.amneziaWgConfig')} + + + )} )} diff --git a/frontend/src/pages/inbounds/InboundsPage.tsx b/frontend/src/pages/inbounds/InboundsPage.tsx index 6ba19630a..a79f4cafc 100644 --- a/frontend/src/pages/inbounds/InboundsPage.tsx +++ b/frontend/src/pages/inbounds/InboundsPage.tsx @@ -24,8 +24,9 @@ import { import { HttpUtil, SizeFormatter, RandomUtil } from '@/utils'; import { createDefaultInboundSettings } from '@/lib/xray/inbound-defaults'; -import { genInboundLinks, genWireguardLinks, preferPublicHost } from '@/lib/xray/inbound-link'; +import { genAmneziaWGLinks, genInboundLinks, genWireguardLinks, preferPublicHost } from '@/lib/xray/inbound-link'; import { inboundFromDb } from '@/lib/xray/inbound-from-db'; +import { Protocols } from '@/schemas/primitives'; import { coerceInboundJsonField, type DBInbound } from '@/models/dbinbound'; import { useTheme } from '@/hooks/useTheme'; import { useMediaQuery } from '@/hooks/useMediaQuery'; @@ -274,7 +275,12 @@ export default function InboundsPage() { { key: 'config', label: t('pages.clients.config'), content }, { key: 'links', label: t('pages.clients.tabLinks'), content: genWireguardLinks(genInput) }, ] - : undefined; + : projected.protocol === Protocols.AMNEZIAWG + ? [ + { key: 'config', label: t('pages.clients.config'), content }, + { key: 'links', label: t('pages.clients.tabLinks'), content: genAmneziaWGLinks(genInput) }, + ] + : undefined; openText({ title: t('pages.inbounds.exportLinksTitle'), content, diff --git a/frontend/src/pages/inbounds/info/InboundInfoModal.tsx b/frontend/src/pages/inbounds/info/InboundInfoModal.tsx index db2d5f5e9..97e3ed207 100644 --- a/frontend/src/pages/inbounds/info/InboundInfoModal.tsx +++ b/frontend/src/pages/inbounds/info/InboundInfoModal.tsx @@ -10,6 +10,8 @@ import { InfinityIcon } from '@/components/ui'; import { useDatepicker } from '@/hooks/useDatepicker'; import { genAllLinks, + genAmneziaWGConfigs, + genAmneziaWGLinks, genWireguardConfigs, genWireguardLinks, preferPublicHost, @@ -49,6 +51,8 @@ export default function InboundInfoModal({ const [links, setLinks] = useState<{ remark?: string; link: string }[]>([]); const [wireguardConfigs, setWireguardConfigs] = useState([]); const [wireguardLinks, setWireguardLinks] = useState([]); + const [amneziawgConfigs, setAmneziawgConfigs] = useState([]); + const [amneziawgLinks, setAmneziawgLinks] = useState([]); const [subLink, setSubLink] = useState(''); const [subJsonLink, setSubJsonLink] = useState(''); const [refreshing, setRefreshing] = useState(false); @@ -132,6 +136,28 @@ export default function InboundInfoModal({ fallbackHostname, }).split('\r\n'), ); + setAmneziawgConfigs([]); + setAmneziawgLinks([]); + setLinks([]); + } else if (info.protocol === Protocols.AMNEZIAWG) { + setAmneziawgConfigs( + genAmneziaWGConfigs({ + inbound: inboundForLinks, + remark: dbInbound.remark, + hostOverride: nodeAddress, + fallbackHostname, + }).split('\r\n'), + ); + setAmneziawgLinks( + genAmneziaWGLinks({ + inbound: inboundForLinks, + remark: dbInbound.remark, + hostOverride: nodeAddress, + fallbackHostname, + }).split('\r\n'), + ); + setWireguardConfigs([]); + setWireguardLinks([]); setLinks([]); } else { setLinks( @@ -145,6 +171,8 @@ export default function InboundInfoModal({ ); setWireguardConfigs([]); setWireguardLinks([]); + setAmneziawgConfigs([]); + setAmneziawgLinks([]); } if (clientSet?.subId) { @@ -851,6 +879,41 @@ export default function InboundInfoModal({ )} + {inbound?.protocol === Protocols.AMNEZIAWG && amneziawgConfigs.length > 0 && ( + <> + {t('pages.inbounds.copyLink')} + {amneziawgConfigs.map((cfg, idx) => ( + + {cfg && ( +
+
+ {t('pages.inbounds.info.peerNumberConfig', { n: idx + 1 })} + +
+ {cfg} +
+ )} + {amneziawgLinks[idx] && ( +
+
+ Peer {idx + 1} link + +
+ {amneziawgLinks[idx]} +
+ )} +
+ ))} + + )} + {dbInbound.isSS && !inbound.isSSMultiUser && links.length > 0 && ( <> {t('pages.inbounds.copyLink')} diff --git a/frontend/src/pages/inbounds/qr/QrCodeModal.tsx b/frontend/src/pages/inbounds/qr/QrCodeModal.tsx index e8025f7bd..ca5e558f5 100644 --- a/frontend/src/pages/inbounds/qr/QrCodeModal.tsx +++ b/frontend/src/pages/inbounds/qr/QrCodeModal.tsx @@ -6,6 +6,8 @@ import type { CollapseProps } from 'antd'; import { Protocols } from '@/schemas/primitives'; import { genAllLinks, + genAmneziaWGConfigs, + genAmneziaWGLinks, genWireguardConfigs, genWireguardLinks, isPostQuantumLink, @@ -50,6 +52,8 @@ export default function QrCodeModal({ const [links, setLinks] = useState<{ remark?: string; link: string }[]>([]); const [wireguardConfigs, setWireguardConfigs] = useState([]); const [wireguardLinks, setWireguardLinks] = useState([]); + const [amneziawgConfigs, setAmneziawgConfigs] = useState([]); + const [amneziawgLinks, setAmneziawgLinks] = useState([]); const [subLink, setSubLink] = useState(''); const [subJsonLink, setSubJsonLink] = useState(''); const [activeKey, setActiveKey] = useState([]); @@ -78,6 +82,31 @@ export default function QrCodeModal({ fallbackHostname, }).split('\r\n'), ); + setAmneziawgConfigs([]); + setAmneziawgLinks([]); + setLinks([]); + } else if (inbound.protocol === Protocols.AMNEZIAWG) { + const peerRemark = client?.email + ? `${dbInbound.remark}-${client.email}` + : dbInbound.remark || ''; + setAmneziawgConfigs( + genAmneziaWGConfigs({ + inbound, + remark: peerRemark, + hostOverride: nodeAddress, + fallbackHostname, + }).split('\r\n'), + ); + setAmneziawgLinks( + genAmneziaWGLinks({ + inbound, + remark: peerRemark, + hostOverride: nodeAddress, + fallbackHostname, + }).split('\r\n'), + ); + setWireguardConfigs([]); + setWireguardLinks([]); setLinks([]); } else { setLinks( @@ -91,6 +120,8 @@ export default function QrCodeModal({ ); setWireguardConfigs([]); setWireguardLinks([]); + setAmneziawgConfigs([]); + setAmneziawgLinks([]); } const subId = client?.subId; @@ -126,8 +157,19 @@ export default function QrCodeModal({ items.push({ key: `wl${idx}`, header: `Peer ${idx + 1} link`, value: wireguardLinks[idx], showQr: false }); } }); + amneziawgConfigs.forEach((cfg, idx) => { + items.push({ + key: `ac${idx}`, + header: `Peer ${idx + 1} config`, + value: cfg, + downloadName: `peer-${idx + 1}.conf`, + }); + if (amneziawgLinks[idx]) { + items.push({ key: `al${idx}`, header: `Peer ${idx + 1} link`, value: amneziawgLinks[idx], showQr: false }); + } + }); return items; - }, [subLink, subJsonLink, links, wireguardConfigs, wireguardLinks, t]); + }, [subLink, subJsonLink, links, wireguardConfigs, wireguardLinks, amneziawgConfigs, amneziawgLinks, t]); const collapseItems: CollapseProps['items'] = useMemo( () => qrItems.map((item) => ({ diff --git a/frontend/src/pages/inbounds/useInbounds.ts b/frontend/src/pages/inbounds/useInbounds.ts index dc2f35cb9..84e2ef0d1 100644 --- a/frontend/src/pages/inbounds/useInbounds.ts +++ b/frontend/src/pages/inbounds/useInbounds.ts @@ -62,6 +62,7 @@ const TRACKED_PROTOCOLS: readonly string[] = [ Protocols.HYSTERIA, Protocols.WIREGUARD, Protocols.MTPROTO, + Protocols.AMNEZIAWG, ]; async function fetchSlimInbounds(): Promise { diff --git a/frontend/src/schemas/api/inbound.ts b/frontend/src/schemas/api/inbound.ts index 5200f433e..aaa114d93 100644 --- a/frontend/src/schemas/api/inbound.ts +++ b/frontend/src/schemas/api/inbound.ts @@ -7,7 +7,7 @@ import { NetworkSettingsSchema, StreamExtrasSchema } from '@/schemas/protocols/s // Top-level inbound shape on the wire. Composes: // - Per-protocol settings via the InboundSettingsSchema discriminated -// union (10 protocols, tagged-wrapper {protocol, settings}). +// union (11 protocols, tagged-wrapper {protocol, settings}). // - StreamSettings as an intersection of the network DU (6 branches), // security DU (3 branches), and the orthogonal extras (finalmask, // sockopt, externalProxy). Zod 4 supports DU intersection — each diff --git a/internal/web/translation/ar-EG.json b/internal/web/translation/ar-EG.json index 14731e50a..3b517c564 100644 --- a/internal/web/translation/ar-EG.json +++ b/internal/web/translation/ar-EG.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "مفتاح وايرغارد المشترك مسبقًا", "wireguardAllowedIPs": "عناوين IP المسموحة لوايرغارد", "wireguardAllowedIPsHint": "اتركه فارغًا للتعيين التلقائي؛ افصل بين الإدخالات بفواصل", + "amneziaWgPrivateKey": "مفتاح AmneziaWG الخاص", + "amneziaWgPublicKey": "مفتاح AmneziaWG العام", + "amneziaWgPreSharedKey": "مفتاح AmneziaWG المشترك مسبقًا", + "amneziaWgAllowedIPs": "عناوين IP المسموحة لـ AmneziaWG", + "amneziaWgAllowedIPsHint": "اتركه فارغًا للتعيين التلقائي؛ افصل بين الإدخالات بفواصل", + "amneziaWgConfig": "إعدادات AmneziaWG", "mtprotoSecret": "سر MTProto", "mtprotoSecretHint": "سر FakeTLS الخاص بالعميل. أعد التوليد لتغييره.", "mtprotoAdTag": "علامة إعلانية (قناة مموّلة)", @@ -1800,6 +1806,31 @@ "psk": "المفتاح المشترك", "domainStrategy": "استراتيجية الدومين" }, + "amneziawg": { + "privateKey": "المفتاح الخاص", + "publicKey": "المفتاح العام", + "subnetIp": "الشبكة الفرعية", + "subnetCidr": "بادئة الشبكة الفرعية (CIDR)", + "mtu": "الحد الأقصى لوحدة النقل (MTU)", + "primaryDns": "DNS الأساسي", + "secondaryDns": "DNS الثانوي", + "externalInterface": "الواجهة الخارجية", + "externalInterfaceHint": "واجهة الشبكة على الخادم المستخدمة لـ NAT (PostUp/PostDown). اتركها فارغة للاكتشاف التلقائي.", + "jc": "Jc (عدد الحزم العشوائية)", + "jmin": "Jmin (الحد الأدنى لحجم الحزمة العشوائية)", + "jmax": "Jmax (الحد الأقصى لحجم الحزمة العشوائية)", + "s1": "S1 (حجم حشو حزمة init)", + "s2": "S2 (حجم حشو حزمة response)", + "s3": "S3 (حشو رد الكوكي، 2.0)", + "s4": "S4 (حشو حزمة النقل، 2.0)", + "h1": "H1 (رأس سحري)", + "h2": "H2 (رأس سحري)", + "h3": "H3 (رأس سحري)", + "h4": "H4 (رأس سحري)", + "hHint": "رقم واحد أو نطاق. اتركه فارغًا للقيم الافتراضية الكلاسيكية 1/2/3/4.", + "i1": "I1 (حزمة التوقيع، 2.0)", + "i1Hint": "خاص بـ AmneziaWG 2.0 فقط. اتركه فارغًا للتوافق مع الإصدار 1.x." + }, "tun": { "nameDesc": "اسم واجهة TUN. القيمة الافتراضية هي 'xray0'", "mtuDesc": "وحدة النقل الأقصى. الحد الأقصى لحجم حزم البيانات. القيمة الافتراضية هي 1500", diff --git a/internal/web/translation/es-ES.json b/internal/web/translation/es-ES.json index 73ed5196d..f1df7c26e 100644 --- a/internal/web/translation/es-ES.json +++ b/internal/web/translation/es-ES.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "Clave precompartida de WireGuard", "wireguardAllowedIPs": "IP permitidas de WireGuard", "wireguardAllowedIPsHint": "Déjalo vacío para asignar automáticamente; separa las entradas con comas", + "amneziaWgPrivateKey": "Clave privada de AmneziaWG", + "amneziaWgPublicKey": "Clave pública de AmneziaWG", + "amneziaWgPreSharedKey": "Clave precompartida de AmneziaWG", + "amneziaWgAllowedIPs": "IP permitidas de AmneziaWG", + "amneziaWgAllowedIPsHint": "Déjalo vacío para asignar automáticamente; separa las entradas con comas", + "amneziaWgConfig": "Configuración de AmneziaWG", "mtprotoSecret": "Secreto MTProto", "mtprotoSecretHint": "El secreto FakeTLS del cliente. Vuelve a generarlo para cambiarlo.", "mtprotoAdTag": "Ad-tag (canal patrocinado)", @@ -1800,6 +1806,31 @@ "psk": "Clave precompartida", "domainStrategy": "Estrategia de dominio" }, + "amneziawg": { + "privateKey": "Clave privada", + "publicKey": "Clave pública", + "subnetIp": "Subred", + "subnetCidr": "CIDR de la subred", + "mtu": "MTU", + "primaryDns": "DNS primario", + "secondaryDns": "DNS secundario", + "externalInterface": "Interfaz externa", + "externalInterfaceHint": "Interfaz de red del host para NAT (PostUp/PostDown). Déjalo vacío para autodetectar.", + "jc": "Jc (cantidad de paquetes basura)", + "jmin": "Jmin (tamaño mínimo de paquete basura)", + "jmax": "Jmax (tamaño máximo de paquete basura)", + "s1": "S1 (relleno del paquete init)", + "s2": "S2 (relleno del paquete response)", + "s3": "S3 (relleno de cookie reply, 2.0)", + "s4": "S4 (relleno del paquete de transporte, 2.0)", + "h1": "H1 (cabecera mágica)", + "h2": "H2 (cabecera mágica)", + "h3": "H3 (cabecera mágica)", + "h4": "H4 (cabecera mágica)", + "hHint": "Un número entero o un rango. Déjalo vacío para los valores clásicos 1/2/3/4.", + "i1": "I1 (paquete de firma, 2.0)", + "i1Hint": "Solo para AmneziaWG 2.0. Déjalo vacío para compatibilidad con 1.x." + }, "tun": { "nameDesc": "El nombre de la interfaz TUN. El valor predeterminado es 'xray0'", "mtuDesc": "Unidad Máxima de Transmisión. El tamaño máximo de los paquetes de datos. El valor predeterminado es 1500", diff --git a/internal/web/translation/fa-IR.json b/internal/web/translation/fa-IR.json index 968773746..e18c263c8 100644 --- a/internal/web/translation/fa-IR.json +++ b/internal/web/translation/fa-IR.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "کلید پیش‌اشتراکی وایرگارد", "wireguardAllowedIPs": "آی‌پی‌های مجاز وایرگارد", "wireguardAllowedIPsHint": "برای تخصیص خودکار خالی بگذارید؛ ورودی‌ها را با کاما جدا کنید", + "amneziaWgPrivateKey": "کلید خصوصی AmneziaWG", + "amneziaWgPublicKey": "کلید عمومی AmneziaWG", + "amneziaWgPreSharedKey": "کلید پیش‌اشتراکی AmneziaWG", + "amneziaWgAllowedIPs": "آی‌پی‌های مجاز AmneziaWG", + "amneziaWgAllowedIPsHint": "برای تخصیص خودکار خالی بگذارید؛ ورودی‌ها را با کاما جدا کنید", + "amneziaWgConfig": "پیکربندی AmneziaWG", "mtprotoSecret": "سکرت MTProto", "mtprotoSecretHint": "سکرت FakeTLS این کلاینت. برای تعویض، دوباره تولید کنید.", "mtprotoAdTag": "برچسب تبلیغاتی (کانال حامی)", @@ -1800,6 +1806,31 @@ "psk": "کلید مشترک", "domainStrategy": "استراتژی حل دامنه" }, + "amneziawg": { + "privateKey": "کلید خصوصی", + "publicKey": "کلید عمومی", + "subnetIp": "زیرشبکه", + "subnetCidr": "پیشوند زیرشبکه (CIDR)", + "mtu": "MTU", + "primaryDns": "DNS اصلی", + "secondaryDns": "DNS ثانویه", + "externalInterface": "رابط خارجی", + "externalInterfaceHint": "رابط شبکه میزبان برای NAT (PostUp/PostDown). برای تشخیص خودکار خالی بگذارید.", + "jc": "Jc (تعداد بسته‌های زباله)", + "jmin": "Jmin (حداقل اندازه بسته زباله)", + "jmax": "Jmax (حداکثر اندازه بسته زباله)", + "s1": "S1 (اندازه پرکننده بسته init)", + "s2": "S2 (اندازه پرکننده بسته response)", + "s3": "S3 (پرکننده cookie reply، نسخه ۲.۰)", + "s4": "S4 (پرکننده بسته انتقال، نسخه ۲.۰)", + "h1": "H1 (سرصفحه جادویی)", + "h2": "H2 (سرصفحه جادویی)", + "h3": "H3 (سرصفحه جادویی)", + "h4": "H4 (سرصفحه جادویی)", + "hHint": "یک عدد صحیح یا یک بازه. برای مقادیر پیش‌فرض کلاسیک ۱/۲/۳/۴ خالی بگذارید.", + "i1": "I1 (بسته امضا، نسخه ۲.۰)", + "i1Hint": "فقط برای AmneziaWG 2.0. برای سازگاری با نسخه ۱.x خالی بگذارید." + }, "tun": { "nameDesc": "نام رابط TUN. مقدار پیش‌فرض 'xray0' است", "mtuDesc": "واحد انتقال حداکثر. بیشترین اندازه بسته‌های داده. مقدار پیش‌فرض 1500 است", diff --git a/internal/web/translation/id-ID.json b/internal/web/translation/id-ID.json index d785794bc..317203b6a 100644 --- a/internal/web/translation/id-ID.json +++ b/internal/web/translation/id-ID.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "Kunci Pra-Berbagi WireGuard", "wireguardAllowedIPs": "IP yang Diizinkan WireGuard", "wireguardAllowedIPsHint": "Biarkan kosong untuk penetapan otomatis; pisahkan entri dengan koma", + "amneziaWgPrivateKey": "Kunci Privat AmneziaWG", + "amneziaWgPublicKey": "Kunci Publik AmneziaWG", + "amneziaWgPreSharedKey": "Kunci Pra-Berbagi AmneziaWG", + "amneziaWgAllowedIPs": "IP yang Diizinkan AmneziaWG", + "amneziaWgAllowedIPsHint": "Biarkan kosong untuk penetapan otomatis; pisahkan entri dengan koma", + "amneziaWgConfig": "Konfigurasi AmneziaWG", "mtprotoSecret": "Secret MTProto", "mtprotoSecretHint": "Secret FakeTLS klien. Buat ulang untuk menggantinya.", "mtprotoAdTag": "Ad-tag (kanal bersponsor)", @@ -1800,6 +1806,31 @@ "psk": "Kunci Pra-Bagi", "domainStrategy": "Strategi Domain" }, + "amneziawg": { + "privateKey": "Kunci Privat", + "publicKey": "Kunci Publik", + "subnetIp": "Subnet", + "subnetCidr": "CIDR Subnet", + "mtu": "MTU", + "primaryDns": "DNS Utama", + "secondaryDns": "DNS Cadangan", + "externalInterface": "Antarmuka Eksternal", + "externalInterfaceHint": "NIC host untuk NAT (PostUp/PostDown). Biarkan kosong untuk deteksi otomatis.", + "jc": "Jc (jumlah paket sampah)", + "jmin": "Jmin (ukuran min paket sampah)", + "jmax": "Jmax (ukuran maks paket sampah)", + "s1": "S1 (padding paket init)", + "s2": "S2 (padding paket response)", + "s3": "S3 (padding cookie reply, 2.0)", + "s4": "S4 (padding paket transport, 2.0)", + "h1": "H1 (header ajaib)", + "h2": "H2 (header ajaib)", + "h3": "H3 (header ajaib)", + "h4": "H4 (header ajaib)", + "hHint": "Satu bilangan bulat atau rentang. Biarkan kosong untuk nilai klasik 1/2/3/4.", + "i1": "I1 (paket tanda tangan, 2.0)", + "i1Hint": "Hanya untuk AmneziaWG 2.0. Biarkan kosong untuk kompatibilitas dengan 1.x." + }, "tun": { "nameDesc": "Nama antarmuka TUN. Standar adalah 'xray0'", "mtuDesc": "Unit Transmisi Maksimum. Ukuran maksimum paket data. Standar adalah 1500", diff --git a/internal/web/translation/ja-JP.json b/internal/web/translation/ja-JP.json index 374b19331..2307f0a4a 100644 --- a/internal/web/translation/ja-JP.json +++ b/internal/web/translation/ja-JP.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "WireGuard 事前共有鍵", "wireguardAllowedIPs": "WireGuard 許可IP", "wireguardAllowedIPsHint": "空欄で自動割り当て。複数指定はカンマ区切り", + "amneziaWgPrivateKey": "AmneziaWG 秘密鍵", + "amneziaWgPublicKey": "AmneziaWG 公開鍵", + "amneziaWgPreSharedKey": "AmneziaWG 事前共有鍵", + "amneziaWgAllowedIPs": "AmneziaWG 許可IP", + "amneziaWgAllowedIPsHint": "空欄で自動割り当て。複数指定はカンマ区切り", + "amneziaWgConfig": "AmneziaWG 設定", "mtprotoSecret": "MTProto シークレット", "mtprotoSecretHint": "このクライアントの FakeTLS シークレット。変更するには再生成します。", "mtprotoAdTag": "広告タグ(スポンサーチャンネル)", @@ -1800,6 +1806,31 @@ "psk": "共有キー", "domainStrategy": "ドメイン戦略" }, + "amneziawg": { + "privateKey": "秘密鍵", + "publicKey": "公開鍵", + "subnetIp": "サブネット", + "subnetCidr": "サブネットCIDR", + "mtu": "MTU", + "primaryDns": "プライマリDNS", + "secondaryDns": "セカンダリDNS", + "externalInterface": "外部インターフェース", + "externalInterfaceHint": "NAT(PostUp/PostDown)に使用するホストのNIC。空欄で自動検出。", + "jc": "Jc(ジャンクパケット数)", + "jmin": "Jmin(ジャンクパケット最小サイズ)", + "jmax": "Jmax(ジャンクパケット最大サイズ)", + "s1": "S1(initパケットのパディングサイズ)", + "s2": "S2(responseパケットのパディングサイズ)", + "s3": "S3(cookie replyパディング、2.0)", + "s4": "S4(トランスポートパケットパディング、2.0)", + "h1": "H1(マジックヘッダー)", + "h2": "H2(マジックヘッダー)", + "h3": "H3(マジックヘッダー)", + "h4": "H4(マジックヘッダー)", + "hHint": "整数または範囲を指定。空欄の場合は従来の1/2/3/4がデフォルトになります。", + "i1": "I1(署名パケット、2.0)", + "i1Hint": "AmneziaWG 2.0専用。空欄で1.x互換の設定になります。" + }, "tun": { "nameDesc": "TUN インターフェースの名前。デフォルトは 'xray0' です", "mtuDesc": "最大伝送単位。データパケットの最大サイズ。デフォルトは 1500 です", diff --git a/internal/web/translation/pt-BR.json b/internal/web/translation/pt-BR.json index ccdedd656..0612bb2eb 100644 --- a/internal/web/translation/pt-BR.json +++ b/internal/web/translation/pt-BR.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "Chave pré-compartilhada do WireGuard", "wireguardAllowedIPs": "IPs permitidos do WireGuard", "wireguardAllowedIPsHint": "Deixe vazio para atribuir automaticamente; separe as entradas com vírgulas", + "amneziaWgPrivateKey": "Chave privada do AmneziaWG", + "amneziaWgPublicKey": "Chave pública do AmneziaWG", + "amneziaWgPreSharedKey": "Chave pré-compartilhada do AmneziaWG", + "amneziaWgAllowedIPs": "IPs permitidos do AmneziaWG", + "amneziaWgAllowedIPsHint": "Deixe vazio para atribuir automaticamente; separe as entradas com vírgulas", + "amneziaWgConfig": "Configuração do AmneziaWG", "mtprotoSecret": "Segredo MTProto", "mtprotoSecretHint": "O segredo FakeTLS do cliente. Gere novamente para trocá-lo.", "mtprotoAdTag": "Ad-tag (canal patrocinado)", @@ -1800,6 +1806,31 @@ "psk": "Chave Pré-Compartilhada", "domainStrategy": "Estratégia de Domínio" }, + "amneziawg": { + "privateKey": "Chave Privada", + "publicKey": "Chave Pública", + "subnetIp": "Sub-rede", + "subnetCidr": "CIDR da Sub-rede", + "mtu": "MTU", + "primaryDns": "DNS Primário", + "secondaryDns": "DNS Secundário", + "externalInterface": "Interface Externa", + "externalInterfaceHint": "Interface de rede do host para NAT (PostUp/PostDown). Deixe vazio para detecção automática.", + "jc": "Jc (quantidade de pacotes de lixo)", + "jmin": "Jmin (tamanho mínimo do pacote de lixo)", + "jmax": "Jmax (tamanho máximo do pacote de lixo)", + "s1": "S1 (preenchimento do pacote init)", + "s2": "S2 (preenchimento do pacote response)", + "s3": "S3 (preenchimento de cookie reply, 2.0)", + "s4": "S4 (preenchimento do pacote de transporte, 2.0)", + "h1": "H1 (cabeçalho mágico)", + "h2": "H2 (cabeçalho mágico)", + "h3": "H3 (cabeçalho mágico)", + "h4": "H4 (cabeçalho mágico)", + "hHint": "Um número inteiro ou um intervalo. Deixe vazio para os valores clássicos 1/2/3/4.", + "i1": "I1 (pacote de assinatura, 2.0)", + "i1Hint": "Somente para AmneziaWG 2.0. Deixe vazio para compatibilidade com 1.x." + }, "tun": { "nameDesc": "O nome da interface TUN. O padrão é 'xray0'", "mtuDesc": "Unidade Máxima de Transmissão. O tamanho máximo dos pacotes de dados. O padrão é 1500", diff --git a/internal/web/translation/tr-TR.json b/internal/web/translation/tr-TR.json index b519fb167..6548ba073 100644 --- a/internal/web/translation/tr-TR.json +++ b/internal/web/translation/tr-TR.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "WireGuard Ön Paylaşımlı Anahtar", "wireguardAllowedIPs": "WireGuard İzin Verilen IP'ler", "wireguardAllowedIPsHint": "Otomatik atama için boş bırakın; girişleri virgülle ayırın", + "amneziaWgPrivateKey": "AmneziaWG Özel Anahtarı", + "amneziaWgPublicKey": "AmneziaWG Genel Anahtarı", + "amneziaWgPreSharedKey": "AmneziaWG Ön Paylaşımlı Anahtar", + "amneziaWgAllowedIPs": "AmneziaWG İzin Verilen IP'ler", + "amneziaWgAllowedIPsHint": "Otomatik atama için boş bırakın; girişleri virgülle ayırın", + "amneziaWgConfig": "AmneziaWG Yapılandırması", "mtprotoSecret": "MTProto sırrı", "mtprotoSecretHint": "İstemcinin FakeTLS sırrı. Değiştirmek için yeniden oluşturun.", "mtprotoAdTag": "Reklam etiketi (sponsorlu kanal)", @@ -1800,6 +1806,31 @@ "psk": "Ön Paylaşılan Anahtar", "domainStrategy": "Alan Adı Stratejisi" }, + "amneziawg": { + "privateKey": "Özel Anahtar", + "publicKey": "Genel Anahtar", + "subnetIp": "Alt Ağ", + "subnetCidr": "Alt Ağ CIDR", + "mtu": "MTU", + "primaryDns": "Birincil DNS", + "secondaryDns": "İkincil DNS", + "externalInterface": "Harici Arayüz", + "externalInterfaceHint": "NAT (PostUp/PostDown) için sunucu ağ arayüzü. Otomatik algılama için boş bırakın.", + "jc": "Jc (gereksiz paket sayısı)", + "jmin": "Jmin (min gereksiz paket boyutu)", + "jmax": "Jmax (maks gereksiz paket boyutu)", + "s1": "S1 (init paketi dolgu boyutu)", + "s2": "S2 (response paketi dolgu boyutu)", + "s3": "S3 (cookie reply dolgusu, 2.0)", + "s4": "S4 (transport paketi dolgusu, 2.0)", + "h1": "H1 (sihirli başlık)", + "h2": "H2 (sihirli başlık)", + "h3": "H3 (sihirli başlık)", + "h4": "H4 (sihirli başlık)", + "hHint": "Tek bir tam sayı veya bir aralık. Klasik 1/2/3/4 varsayılanları için boş bırakın.", + "i1": "I1 (imza paketi, 2.0)", + "i1Hint": "Yalnızca AmneziaWG 2.0 için. 1.x uyumluluğu için boş bırakın." + }, "tun": { "nameDesc": "TUN arabiriminin adı. Varsayılan değer 'xray0'dır.", "mtuDesc": "Maksimum İletim Birimi. Veri paketlerinin maksimum boyutu. Varsayılan değer 1500'dür.", diff --git a/internal/web/translation/uk-UA.json b/internal/web/translation/uk-UA.json index ddb3f69c2..3409c2d20 100644 --- a/internal/web/translation/uk-UA.json +++ b/internal/web/translation/uk-UA.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "Спільний ключ WireGuard", "wireguardAllowedIPs": "Дозволені IP WireGuard", "wireguardAllowedIPsHint": "Залиште порожнім для автопризначення; розділяйте записи комами", + "amneziaWgPrivateKey": "Приватний ключ AmneziaWG", + "amneziaWgPublicKey": "Публічний ключ AmneziaWG", + "amneziaWgPreSharedKey": "Спільний ключ AmneziaWG", + "amneziaWgAllowedIPs": "Дозволені IP AmneziaWG", + "amneziaWgAllowedIPsHint": "Залиште порожнім для автопризначення; розділяйте записи комами", + "amneziaWgConfig": "Конфігурація AmneziaWG", "mtprotoSecret": "Секрет MTProto", "mtprotoSecretHint": "Секрет FakeTLS клієнта. Згенеруйте заново, щоб змінити.", "mtprotoAdTag": "Рекламний тег (спонсорський канал)", @@ -1800,6 +1806,31 @@ "psk": "Спільний ключ", "domainStrategy": "Стратегія домену" }, + "amneziawg": { + "privateKey": "Приватний ключ", + "publicKey": "Публічний ключ", + "subnetIp": "Підмережа", + "subnetCidr": "CIDR підмережі", + "mtu": "MTU", + "primaryDns": "Основний DNS", + "secondaryDns": "Резервний DNS", + "externalInterface": "Зовнішній інтерфейс", + "externalInterfaceHint": "Мережевий інтерфейс хоста для NAT (PostUp/PostDown). Залиште порожнім для автовизначення.", + "jc": "Jc (кількість сміттєвих пакетів)", + "jmin": "Jmin (мін. розмір сміттєвого пакета)", + "jmax": "Jmax (макс. розмір сміттєвого пакета)", + "s1": "S1 (заповнення пакета init)", + "s2": "S2 (заповнення пакета response)", + "s3": "S3 (заповнення cookie reply, 2.0)", + "s4": "S4 (заповнення транспортного пакета, 2.0)", + "h1": "H1 (магічний заголовок)", + "h2": "H2 (магічний заголовок)", + "h3": "H3 (магічний заголовок)", + "h4": "H4 (магічний заголовок)", + "hHint": "Ціле число або діапазон. Залиште порожнім для класичних значень 1/2/3/4.", + "i1": "I1 (пакет підпису, 2.0)", + "i1Hint": "Лише для AmneziaWG 2.0. Залиште порожнім для сумісності з 1.x." + }, "tun": { "nameDesc": "Назва інтерфейсу TUN. Значення за замовчуванням - 'xray0'", "mtuDesc": "Максимальна одиниця передачі. Максимальний розмір пакетів даних. Значення за замовчуванням - 1500", diff --git a/internal/web/translation/vi-VN.json b/internal/web/translation/vi-VN.json index 7984ec201..2d2930496 100644 --- a/internal/web/translation/vi-VN.json +++ b/internal/web/translation/vi-VN.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "Khóa chia sẻ trước WireGuard", "wireguardAllowedIPs": "IP được phép WireGuard", "wireguardAllowedIPsHint": "Để trống để tự động gán; phân tách các mục bằng dấu phẩy", + "amneziaWgPrivateKey": "Khóa riêng AmneziaWG", + "amneziaWgPublicKey": "Khóa công khai AmneziaWG", + "amneziaWgPreSharedKey": "Khóa chia sẻ trước AmneziaWG", + "amneziaWgAllowedIPs": "IP được phép AmneziaWG", + "amneziaWgAllowedIPsHint": "Để trống để tự động gán; phân tách các mục bằng dấu phẩy", + "amneziaWgConfig": "Cấu hình AmneziaWG", "mtprotoSecret": "Secret MTProto", "mtprotoSecretHint": "Secret FakeTLS của client. Tạo lại để thay đổi.", "mtprotoAdTag": "Ad-tag (kênh tài trợ)", @@ -1800,6 +1806,31 @@ "psk": "Khóa chia sẻ", "domainStrategy": "Chiến lược tên miền" }, + "amneziawg": { + "privateKey": "Khóa riêng", + "publicKey": "Khóa công khai", + "subnetIp": "Mạng con", + "subnetCidr": "CIDR mạng con", + "mtu": "MTU", + "primaryDns": "DNS chính", + "secondaryDns": "DNS phụ", + "externalInterface": "Giao diện ngoài", + "externalInterfaceHint": "Card mạng của host dùng cho NAT (PostUp/PostDown). Để trống để tự động phát hiện.", + "jc": "Jc (số lượng gói rác)", + "jmin": "Jmin (kích thước tối thiểu gói rác)", + "jmax": "Jmax (kích thước tối đa gói rác)", + "s1": "S1 (đệm gói init)", + "s2": "S2 (đệm gói response)", + "s3": "S3 (đệm cookie reply, 2.0)", + "s4": "S4 (đệm gói transport, 2.0)", + "h1": "H1 (tiêu đề ma thuật)", + "h2": "H2 (tiêu đề ma thuật)", + "h3": "H3 (tiêu đề ma thuật)", + "h4": "H4 (tiêu đề ma thuật)", + "hHint": "Một số nguyên hoặc một khoảng. Để trống để dùng giá trị mặc định cổ điển 1/2/3/4.", + "i1": "I1 (gói chữ ký, 2.0)", + "i1Hint": "Chỉ dành cho AmneziaWG 2.0. Để trống để tương thích với 1.x." + }, "tun": { "nameDesc": "Tên của giao diện TUN. Giá trị mặc định là 'xray0'", "mtuDesc": "Đơn vị Truyền Tối đa. Kích thước tối đa của các gói dữ liệu. Giá trị mặc định là 1500", diff --git a/internal/web/translation/zh-CN.json b/internal/web/translation/zh-CN.json index 9bcafa414..649548c30 100644 --- a/internal/web/translation/zh-CN.json +++ b/internal/web/translation/zh-CN.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "WireGuard 预共享密钥", "wireguardAllowedIPs": "WireGuard 允许的 IP", "wireguardAllowedIPsHint": "留空则自动分配;多个条目用逗号分隔", + "amneziaWgPrivateKey": "AmneziaWG 私钥", + "amneziaWgPublicKey": "AmneziaWG 公钥", + "amneziaWgPreSharedKey": "AmneziaWG 预共享密钥", + "amneziaWgAllowedIPs": "AmneziaWG 允许的 IP", + "amneziaWgAllowedIPsHint": "留空则自动分配;多个条目用逗号分隔", + "amneziaWgConfig": "AmneziaWG 配置", "mtprotoSecret": "MTProto 密钥", "mtprotoSecretHint": "该客户端的 FakeTLS 密钥。重新生成即可更换。", "mtprotoAdTag": "广告标签(赞助频道)", @@ -1800,6 +1806,31 @@ "psk": "共享密钥", "domainStrategy": "域策略" }, + "amneziawg": { + "privateKey": "私钥", + "publicKey": "公钥", + "subnetIp": "子网", + "subnetCidr": "子网 CIDR", + "mtu": "MTU", + "primaryDns": "主 DNS", + "secondaryDns": "备用 DNS", + "externalInterface": "外部网卡", + "externalInterfaceHint": "用于 NAT(PostUp/PostDown)的主机网卡。留空则自动检测。", + "jc": "Jc(垃圾包数量)", + "jmin": "Jmin(垃圾包最小大小)", + "jmax": "Jmax(垃圾包最大大小)", + "s1": "S1(init 包填充大小)", + "s2": "S2(response 包填充大小)", + "s3": "S3(cookie reply 填充,2.0)", + "s4": "S4(传输包填充,2.0)", + "h1": "H1(魔术头)", + "h2": "H2(魔术头)", + "h3": "H3(魔术头)", + "h4": "H4(魔术头)", + "hHint": "单个整数或范围。留空则使用经典默认值 1/2/3/4。", + "i1": "I1(签名包,2.0)", + "i1Hint": "仅适用于 AmneziaWG 2.0。留空则兼容 1.x。" + }, "tun": { "nameDesc": "TUN 接口的名称。默认值为 'xray0'", "mtuDesc": "最大传输单元。数据包的最大大小。默认值为 1500", diff --git a/internal/web/translation/zh-TW.json b/internal/web/translation/zh-TW.json index 72c519445..91bf19eb3 100644 --- a/internal/web/translation/zh-TW.json +++ b/internal/web/translation/zh-TW.json @@ -915,6 +915,12 @@ "wireguardPreSharedKey": "WireGuard 預共用金鑰", "wireguardAllowedIPs": "WireGuard 允許的 IP", "wireguardAllowedIPsHint": "留空則自動分配;多個條目用逗號分隔", + "amneziaWgPrivateKey": "AmneziaWG 私鑰", + "amneziaWgPublicKey": "AmneziaWG 公鑰", + "amneziaWgPreSharedKey": "AmneziaWG 預共用金鑰", + "amneziaWgAllowedIPs": "AmneziaWG 允許的 IP", + "amneziaWgAllowedIPsHint": "留空則自動分配;多個條目用逗號分隔", + "amneziaWgConfig": "AmneziaWG 設定", "mtprotoSecret": "MTProto 金鑰", "mtprotoSecretHint": "該用戶端的 FakeTLS 金鑰。重新產生即可更換。", "mtprotoAdTag": "廣告標籤(贊助頻道)", @@ -1800,6 +1806,31 @@ "psk": "共享金鑰", "domainStrategy": "域策略" }, + "amneziawg": { + "privateKey": "私鑰", + "publicKey": "公鑰", + "subnetIp": "子網路", + "subnetCidr": "子網路 CIDR", + "mtu": "MTU", + "primaryDns": "主要 DNS", + "secondaryDns": "次要 DNS", + "externalInterface": "外部網路介面", + "externalInterfaceHint": "用於 NAT(PostUp/PostDown)的主機網路介面。留空則自動偵測。", + "jc": "Jc(垃圾封包數量)", + "jmin": "Jmin(垃圾封包最小大小)", + "jmax": "Jmax(垃圾封包最大大小)", + "s1": "S1(init 封包填充大小)", + "s2": "S2(response 封包填充大小)", + "s3": "S3(cookie reply 填充,2.0)", + "s4": "S4(傳輸封包填充,2.0)", + "h1": "H1(魔術標頭)", + "h2": "H2(魔術標頭)", + "h3": "H3(魔術標頭)", + "h4": "H4(魔術標頭)", + "hHint": "單一整數或範圍。留空則使用經典預設值 1/2/3/4。", + "i1": "I1(簽章封包,2.0)", + "i1Hint": "僅適用於 AmneziaWG 2.0。留空則相容 1.x。" + }, "tun": { "nameDesc": "TUN 介面的名稱。預設值為 'xray0'", "mtuDesc": "最大傳輸單元。資料包的最大大小。預設值為 1500",