mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-07 02:37:14 +00:00
feat(amneziawg): add a button to randomize obfuscation parameters
Mirrors the existing key-regenerate button next to the private key field. Client-side randomization matches the ranges/constraints of GenerateObfuscation20's "default" preset (internal/amneziawg/params.go) closely enough for a form suggestion — the user can still hand-edit any field afterward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -332,6 +332,58 @@ export default function InboundFormModal({
|
||||
setV('settings.server.publicKey', kp.publicKey);
|
||||
};
|
||||
|
||||
// Randomizes the AmneziaWG 2.0 obfuscation set client-side, mirroring the
|
||||
// ranges/constraints of the Go backend's amneziawg.GenerateObfuscation20
|
||||
// "default" preset (internal/amneziawg/params.go) closely enough for a form
|
||||
// suggestion — exact parity isn't required since the user can still edit
|
||||
// any field afterward, and a fresh, non-crypto-grade random value here is
|
||||
// no weaker than what the backend would have generated on first save.
|
||||
const regenInboundAwgObfuscation = () => {
|
||||
const randInt = (min: number, max: number) => min + Math.floor(Math.random() * (max - min + 1));
|
||||
|
||||
const jc = randInt(3, 6);
|
||||
const jmin = randInt(40, 89);
|
||||
const jmax = jmin + randInt(50, 250);
|
||||
|
||||
const s1 = randInt(15, 150);
|
||||
let s2 = randInt(15, 150);
|
||||
while (s1 + 56 === s2) {
|
||||
s2 = randInt(15, 150);
|
||||
}
|
||||
const s3 = randInt(8, 55);
|
||||
const s4 = randInt(4, 27);
|
||||
|
||||
// Four non-overlapping "low-high" ranges for H1-H4: split the space into
|
||||
// four bands and take a random sub-range from each (>= 1000 wide, low
|
||||
// bound >= 5 since 1-4 are reserved for vanilla WireGuard message types).
|
||||
const hMax = 2147483647;
|
||||
const hMinWidth = 1000;
|
||||
const lo = 5;
|
||||
const bandSize = Math.floor((hMax - lo + 1) / 4);
|
||||
const hRanges = Array.from({ length: 4 }, (_, i) => {
|
||||
const bandLo = lo + i * bandSize;
|
||||
const bandHi = bandLo + bandSize - 1;
|
||||
const start = randInt(bandLo, bandHi - hMinWidth - 1);
|
||||
const end = randInt(start + hMinWidth, bandHi - 1);
|
||||
return `${start}-${end}`;
|
||||
});
|
||||
|
||||
const i1 = `<r ${randInt(32, 256)}>`;
|
||||
|
||||
setV('settings.server.jc', jc);
|
||||
setV('settings.server.jmin', jmin);
|
||||
setV('settings.server.jmax', jmax);
|
||||
setV('settings.server.s1', s1);
|
||||
setV('settings.server.s2', s2);
|
||||
setV('settings.server.s3', s3);
|
||||
setV('settings.server.s4', s4);
|
||||
setV('settings.server.h1', hRanges[0]);
|
||||
setV('settings.server.h2', hRanges[1]);
|
||||
setV('settings.server.h3', hRanges[2]);
|
||||
setV('settings.server.h4', hRanges[3]);
|
||||
setV('settings.server.i1', i1);
|
||||
};
|
||||
|
||||
const matchesVlessAuth = (
|
||||
block: { id?: string; label?: string } | undefined | null,
|
||||
authId: string,
|
||||
@@ -676,7 +728,13 @@ export default function InboundFormModal({
|
||||
<>
|
||||
{protocol === Protocols.WIREGUARD && <WireguardFields wgPubKey={wgPubKey} regenInboundWg={regenInboundWg} />}
|
||||
|
||||
{protocol === Protocols.AMNEZIAWG && <AmneziawgFields awgPubKey={awgPubKey} regenInboundAwg={regenInboundAwg} />}
|
||||
{protocol === Protocols.AMNEZIAWG && (
|
||||
<AmneziawgFields
|
||||
awgPubKey={awgPubKey}
|
||||
regenInboundAwg={regenInboundAwg}
|
||||
regenInboundAwgObfuscation={regenInboundAwgObfuscation}
|
||||
/>
|
||||
)}
|
||||
|
||||
{protocol === Protocols.TUN && <TunFields />}
|
||||
|
||||
|
||||
@@ -7,9 +7,10 @@ import { FormField } from '@/components/form/rhf';
|
||||
interface AmneziawgFieldsProps {
|
||||
awgPubKey: string;
|
||||
regenInboundAwg: () => void;
|
||||
regenInboundAwgObfuscation: () => void;
|
||||
}
|
||||
|
||||
export default function AmneziawgFields({ awgPubKey, regenInboundAwg }: AmneziawgFieldsProps) {
|
||||
export default function AmneziawgFields({ awgPubKey, regenInboundAwg, regenInboundAwgObfuscation }: AmneziawgFieldsProps) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
@@ -46,6 +47,11 @@ export default function AmneziawgFields({ awgPubKey, regenInboundAwg }: Amneziaw
|
||||
>
|
||||
<Input placeholder="eth0" />
|
||||
</FormField>
|
||||
<Form.Item label={t('pages.xray.amneziawg.obfuscation')}>
|
||||
<Button icon={<ReloadOutlined />} onClick={regenInboundAwgObfuscation}>
|
||||
{t('pages.xray.amneziawg.regenerateObfuscation')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<FormField name={['settings', 'server', 'jc']} label={t('pages.xray.amneziawg.jc')}>
|
||||
<InputNumber min={0} style={{ width: '100%' }} />
|
||||
</FormField>
|
||||
|
||||
@@ -1933,6 +1933,8 @@
|
||||
"secondaryDns": "Secondary DNS",
|
||||
"externalInterface": "External Interface",
|
||||
"externalInterfaceHint": "Host NIC for NAT (PostUp/PostDown). Leave empty to auto-detect.",
|
||||
"obfuscation": "Obfuscation parameters",
|
||||
"regenerateObfuscation": "Regenerate",
|
||||
"jc": "Jc (junk packet count)",
|
||||
"jmin": "Jmin (junk packet min size)",
|
||||
"jmax": "Jmax (junk packet max size)",
|
||||
|
||||
@@ -1816,6 +1816,8 @@
|
||||
"secondaryDns": "Резервный DNS",
|
||||
"externalInterface": "Внешний интерфейс",
|
||||
"externalInterfaceHint": "Сетевой интерфейс хоста для NAT (PostUp/PostDown). Оставьте пустым для автоопределения.",
|
||||
"obfuscation": "Параметры обфускации",
|
||||
"regenerateObfuscation": "Сгенерировать заново",
|
||||
"jc": "Jc (кол-во мусорных пакетов)",
|
||||
"jmin": "Jmin (мин. размер мусорного пакета)",
|
||||
"jmax": "Jmax (макс. размер мусорного пакета)",
|
||||
|
||||
Reference in New Issue
Block a user