mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-03 17:07:15 +00:00
feat(wireguard): client config UX, collapsible config card, configurable DNS
Land the WireGuard client-config UX work on main (the upstream PR #5642 branch could not be pushed to). - Reusable collapsible ConfigBlock (copy/download/QR, actions aligned right) for the client .conf, used by client info and the public sub page. - Correct .conf: canonical PresharedKey casing and DNS sourced from the inbound (configurable per-inbound, default 1.1.1.1, 1.0.0.1). - Configurable per-inbound DNS for WireGuard (schema + form + backend hint via InboundOption.WgDns); inert at the Xray layer. - Public sub page now shows the WireGuard config, rebuilt from the share link; the Go wireguard:// link carries dns/presharedkey/keepalive for completeness. - QR enabled for the wireguard:// link; link rows are compact like other protocols. - Client information order is subscription, copy URL, WireGuard config; the redundant config tab is removed from the add/edit client modal. - Drop the Inbound Information and QR Code row actions for WireGuard inbounds.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { formatInboundLabel } from '@/lib/inbounds/label';
|
||||
import { preferPublicHost } from '@/lib/xray/inbound-link';
|
||||
import type { ClientRecord, InboundOption } from '@/hooks/useClients';
|
||||
|
||||
export function isWireguardClient(client: ClientRecord | null | undefined): boolean {
|
||||
if (!client) return false;
|
||||
return !!(client.privateKey || client.publicKey || client.allowedIPs || client.preSharedKey || client.keepAlive);
|
||||
}
|
||||
|
||||
export function findWireguardInbound(
|
||||
client: ClientRecord | null | undefined,
|
||||
inboundsById: Record<number, InboundOption>,
|
||||
): InboundOption | undefined {
|
||||
return (client?.inboundIds || [])
|
||||
.map((id) => inboundsById[id])
|
||||
.find((ib) => ib?.protocol === 'wireguard');
|
||||
}
|
||||
|
||||
export function buildWireguardClientConfig(
|
||||
client: ClientRecord,
|
||||
inbound: InboundOption | undefined,
|
||||
host = window.location.hostname,
|
||||
publicHost = '',
|
||||
): string {
|
||||
const endpointHost = preferPublicHost(host, publicHost);
|
||||
const address = client.allowedIPs || '10.0.0.2/32';
|
||||
const endpoint = `${endpointHost}:${inbound?.port || ''}`;
|
||||
const inboundName = inbound ? formatInboundLabel(inbound.tag, inbound.remark) : '';
|
||||
const remark = [inboundName, client.email, client.comment].filter(Boolean).join(' - ');
|
||||
const lines = [
|
||||
'[Interface]',
|
||||
`PrivateKey = ${client.privateKey || client.password || ''}`,
|
||||
`Address = ${address}`,
|
||||
`DNS = ${inbound?.wgDns || '1.1.1.1, 1.0.0.1'}`,
|
||||
];
|
||||
if (inbound?.wgMtu && inbound.wgMtu > 0) lines.push(`MTU = ${inbound.wgMtu}`);
|
||||
lines.push('');
|
||||
if (remark) lines.push(`# ${remark}`);
|
||||
lines.push('[Peer]', `PublicKey = ${inbound?.wgPublicKey || ''}`);
|
||||
if (client.preSharedKey) lines.push(`PresharedKey = ${client.preSharedKey}`);
|
||||
lines.push('AllowedIPs = 0.0.0.0/0, ::/0', `Endpoint = ${endpoint}`);
|
||||
if (client.keepAlive && client.keepAlive > 0) lines.push(`PersistentKeepalive = ${client.keepAlive}`);
|
||||
return lines.join('\n');
|
||||
}
|
||||
Reference in New Issue
Block a user