Просмотр исходного кода

feat(wireguard): per-peer comments for identifying devices (#5168)

WG peers were only identifiable by their keys. Add an optional panel-side
comment per peer: editable in the inbound form (echoed next to "Peer N"
in the section header), stored in the settings JSON alongside the
panel-only privateKey (xray-core ignores unknown peer fields), and
appended to the share link / .conf remark so the device is identifiable
in client apps too.
MHSanaei 3 дней назад
Родитель
Сommit
d04cb10971

+ 11 - 4
frontend/src/lib/xray/inbound-link.ts

@@ -1079,11 +1079,11 @@ export function genWireguardLinks(input: GenWireguardFanoutInput): string {
   const addr = resolveAddr(inbound, hostOverride, fallbackHostname);
   const sep = remarkModel.charAt(0);
   return inbound.settings.peers
-    .map((_p, i) => genWireguardLink({
+    .map((p, i) => genWireguardLink({
       settings: inbound.settings as WireguardInboundSettings,
       address: addr,
       port: inbound.port,
-      remark: `${remark}${sep}${i + 1}`,
+      remark: `${remark}${sep}${i + 1}${wgPeerCommentSuffix(p)}`,
       peerIndex: i,
     }))
     .join('\r\n');
@@ -1095,16 +1095,23 @@ export function genWireguardConfigs(input: GenWireguardFanoutInput): string {
   const addr = resolveAddr(inbound, hostOverride, fallbackHostname);
   const sep = remarkModel.charAt(0);
   return inbound.settings.peers
-    .map((_p, i) => genWireguardConfig({
+    .map((p, i) => genWireguardConfig({
       settings: inbound.settings as WireguardInboundSettings,
       address: addr,
       port: inbound.port,
-      remark: `${remark}${sep}${i + 1}`,
+      remark: `${remark}${sep}${i + 1}${wgPeerCommentSuffix(p)}`,
       peerIndex: i,
     }))
     .join('\r\n');
 }
 
+// Peer comments (#5168) are panel-side annotations; when present they ride
+// along in the share remark so the device is identifiable in client apps.
+function wgPeerCommentSuffix(peer: unknown): string {
+  const comment = (peer as { comment?: unknown })?.comment;
+  return typeof comment === 'string' && comment.trim() !== '' ? ` (${comment.trim()})` : '';
+}
+
 export function isPostQuantumLink(link: string): boolean {
   if (/[?&]pqv=/.test(link)) return true;
   if (link.includes('mlkem768') || link.includes('mldsa65')) return true;

+ 9 - 0
frontend/src/pages/inbounds/form/protocols/wireguard.tsx

@@ -102,6 +102,12 @@ export default function WireguardFields({ wgPubKey, regenInboundWg, regenWgPeerK
                 <Divider titlePlacement="center">
                   <Space>
                     <span>{t('pages.inbounds.info.peerNumber', { n: idx + 1 })}</span>
+                    <Form.Item noStyle shouldUpdate>
+                      {() => {
+                        const comment = form.getFieldValue(['settings', 'peers', field.name, 'comment']) as string | undefined;
+                        return comment ? <span style={{ opacity: 0.65 }}>— {comment}</span> : null;
+                      }}
+                    </Form.Item>
                     {fields.length > 1 && (
                       <Button
                         size="small"
@@ -112,6 +118,9 @@ export default function WireguardFields({ wgPubKey, regenInboundWg, regenWgPeerK
                     )}
                   </Space>
                 </Divider>
+                <Form.Item name={[field.name, 'comment']} label={t('comment')}>
+                  <Input placeholder="e.g. Alice's laptop" />
+                </Form.Item>
                 <Form.Item label={t('pages.xray.wireguard.secretKey')}>
                   <Space.Compact block>
                     <Form.Item name={[field.name, 'privateKey']} noStyle>

+ 4 - 0
frontend/src/schemas/protocols/inbound/wireguard.ts

@@ -26,6 +26,10 @@ export const WireguardInboundPeerSchema = z.object({
   preSharedKey: z.string().optional(),
   allowedIPs: z.array(z.string()).default([]),
   keepAlive: optionalClearedInt(z.number().int().min(0)),
+  // Panel-only annotation (#5168): which client/device this peer belongs to.
+  // Rides along in the settings JSON like privateKey does; xray-core ignores
+  // unknown peer fields.
+  comment: z.string().optional(),
 });
 export type WireguardInboundPeer = z.infer<typeof WireguardInboundPeerSchema>;