Przeglądaj źródła

server: replace client metadata with IP address in registry (#5118)

fatedier 4 dni temu
rodzic
commit
1245f8804e

Plik diff jest za duży
+ 0 - 0
assets/frps/static/index-Cl4R6mJh.css


Plik diff jest za duży
+ 0 - 0
assets/frps/static/index-r9B2t7lx.js


+ 2 - 2
assets/frps/static/index.html

@@ -4,8 +4,8 @@
 <head>
 <head>
     <meta charset="utf-8">
     <meta charset="utf-8">
     <title>frp server</title>
     <title>frp server</title>
-  <script type="module" crossorigin src="./index-BUrDiw1t.js"></script>
-  <link rel="stylesheet" crossorigin href="./index-D4KRVvIu.css">
+  <script type="module" crossorigin src="./index-r9B2t7lx.js"></script>
+  <link rel="stylesheet" crossorigin href="./index-Cl4R6mJh.css">
 </head>
 </head>
 
 
 <body>
 <body>

+ 5 - 10
server/client_registry.go

@@ -2,7 +2,6 @@ package server
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"maps"
 	"sync"
 	"sync"
 	"time"
 	"time"
 )
 )
@@ -14,7 +13,7 @@ type ClientInfo struct {
 	ClientID         string
 	ClientID         string
 	RunID            string
 	RunID            string
 	Hostname         string
 	Hostname         string
-	Metas            map[string]string
+	IP               string
 	FirstConnectedAt time.Time
 	FirstConnectedAt time.Time
 	LastConnectedAt  time.Time
 	LastConnectedAt  time.Time
 	DisconnectedAt   time.Time
 	DisconnectedAt   time.Time
@@ -37,7 +36,7 @@ func NewClientRegistry() *ClientRegistry {
 }
 }
 
 
 // Register stores/updates metadata for a client and returns the registry key plus whether it conflicts with an online client.
 // Register stores/updates metadata for a client and returns the registry key plus whether it conflicts with an online client.
-func (cr *ClientRegistry) Register(user, clientID, runID, hostname string, metas map[string]string) (key string, conflict bool) {
+func (cr *ClientRegistry) Register(user, clientID, runID, hostname, remoteAddr string) (key string, conflict bool) {
 	if runID == "" {
 	if runID == "" {
 		return "", false
 		return "", false
 	}
 	}
@@ -72,7 +71,7 @@ func (cr *ClientRegistry) Register(user, clientID, runID, hostname string, metas
 
 
 	info.RunID = runID
 	info.RunID = runID
 	info.Hostname = hostname
 	info.Hostname = hostname
-	info.Metas = metas
+	info.IP = remoteAddr
 	if info.FirstConnectedAt.IsZero() {
 	if info.FirstConnectedAt.IsZero() {
 		info.FirstConnectedAt = now
 		info.FirstConnectedAt = now
 	}
 	}
@@ -113,9 +112,7 @@ func (cr *ClientRegistry) List() []ClientInfo {
 
 
 	result := make([]ClientInfo, 0, len(cr.clients))
 	result := make([]ClientInfo, 0, len(cr.clients))
 	for _, info := range cr.clients {
 	for _, info := range cr.clients {
-		cp := *info
-		cp.Metas = maps.Clone(info.Metas)
-		result = append(result, cp)
+		result = append(result, *info)
 	}
 	}
 	return result
 	return result
 }
 }
@@ -129,9 +126,7 @@ func (cr *ClientRegistry) GetByKey(key string) (ClientInfo, bool) {
 	if !ok {
 	if !ok {
 		return ClientInfo{}, false
 		return ClientInfo{}, false
 	}
 	}
-	cp := *info
-	cp.Metas = maps.Clone(info.Metas)
-	return cp, true
+	return *info, true
 }
 }
 
 
 func (cr *ClientRegistry) composeClientKey(user, id string) string {
 func (cr *ClientRegistry) composeClientKey(user, id string) string {

+ 11 - 11
server/dashboard_api.go

@@ -94,16 +94,16 @@ type serverInfoResp struct {
 }
 }
 
 
 type clientInfoResp struct {
 type clientInfoResp struct {
-	Key              string            `json:"key"`
-	User             string            `json:"user"`
-	ClientID         string            `json:"clientId"`
-	RunID            string            `json:"runId"`
-	Hostname         string            `json:"hostname"`
-	Metas            map[string]string `json:"metas,omitempty"`
-	FirstConnectedAt int64             `json:"firstConnectedAt"`
-	LastConnectedAt  int64             `json:"lastConnectedAt"`
-	DisconnectedAt   int64             `json:"disconnectedAt,omitempty"`
-	Online           bool              `json:"online"`
+	Key              string `json:"key"`
+	User             string `json:"user"`
+	ClientID         string `json:"clientID"`
+	RunID            string `json:"runID"`
+	Hostname         string `json:"hostname"`
+	ClientIP         string `json:"clientIP,omitempty"`
+	FirstConnectedAt int64  `json:"firstConnectedAt"`
+	LastConnectedAt  int64  `json:"lastConnectedAt"`
+	DisconnectedAt   int64  `json:"disconnectedAt,omitempty"`
+	Online           bool   `json:"online"`
 }
 }
 
 
 // /healthz
 // /healthz
@@ -531,7 +531,7 @@ func buildClientInfoResp(info ClientInfo) clientInfoResp {
 		ClientID:         info.ClientID,
 		ClientID:         info.ClientID,
 		RunID:            info.RunID,
 		RunID:            info.RunID,
 		Hostname:         info.Hostname,
 		Hostname:         info.Hostname,
-		Metas:            info.Metas,
+		ClientIP:         info.IP,
 		FirstConnectedAt: toUnix(info.FirstConnectedAt),
 		FirstConnectedAt: toUnix(info.FirstConnectedAt),
 		LastConnectedAt:  toUnix(info.LastConnectedAt),
 		LastConnectedAt:  toUnix(info.LastConnectedAt),
 		Online:           info.Online,
 		Online:           info.Online,

+ 5 - 1
server/service.go

@@ -615,7 +615,11 @@ func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login, inter
 		oldCtl.WaitClosed()
 		oldCtl.WaitClosed()
 	}
 	}
 
 
-	_, conflict := svr.clientRegistry.Register(loginMsg.User, loginMsg.ClientID, loginMsg.RunID, loginMsg.Hostname, loginMsg.Metas)
+	remoteAddr := ctlConn.RemoteAddr().String()
+	if host, _, err := net.SplitHostPort(remoteAddr); err == nil {
+		remoteAddr = host
+	}
+	_, conflict := svr.clientRegistry.Register(loginMsg.User, loginMsg.ClientID, loginMsg.RunID, loginMsg.Hostname, remoteAddr)
 	if conflict {
 	if conflict {
 		svr.ctlManager.Del(loginMsg.RunID, ctl)
 		svr.ctlManager.Del(loginMsg.RunID, ctl)
 		ctl.Close()
 		ctl.Close()

+ 8 - 47
web/frps/src/components/ClientCard.vue

@@ -17,6 +17,12 @@
         <span class="info-value">{{ client.hostname || 'N/A' }}</span>
         <span class="info-value">{{ client.hostname || 'N/A' }}</span>
       </div>
       </div>
 
 
+      <div class="info-row" v-if="client.ip">
+        <el-icon class="info-icon"><Connection /></el-icon>
+        <span class="info-label">IP:</span>
+        <span class="info-value monospace">{{ client.ip }}</span>
+      </div>
+
       <div class="info-row" v-if="client.user">
       <div class="info-row" v-if="client.user">
         <el-icon class="info-icon"><User /></el-icon>
         <el-icon class="info-icon"><User /></el-icon>
         <span class="info-label">User:</span>
         <span class="info-label">User:</span>
@@ -26,7 +32,7 @@
       <div class="info-row">
       <div class="info-row">
         <el-icon class="info-icon"><Key /></el-icon>
         <el-icon class="info-icon"><Key /></el-icon>
         <span class="info-label">Run ID:</span>
         <span class="info-label">Run ID:</span>
-        <span class="info-value monospace">{{ client.runId }}</span>
+        <span class="info-value monospace">{{ client.runID }}</span>
       </div>
       </div>
 
 
       <div class="info-row" v-if="client.firstConnectedAt">
       <div class="info-row" v-if="client.firstConnectedAt">
@@ -48,26 +54,12 @@
       </div>
       </div>
     </div>
     </div>
 
 
-    <div class="client-metas" v-if="client.metasArray.length > 0">
-      <div class="metas-label">Metadata:</div>
-      <div class="metas-tags">
-        <el-tag
-          v-for="meta in client.metasArray"
-          :key="meta.key"
-          size="small"
-          type="info"
-          class="meta-tag"
-        >
-          {{ meta.key }}: {{ meta.value }}
-        </el-tag>
-      </div>
-    </div>
   </el-card>
   </el-card>
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
 import { computed } from 'vue'
 import { computed } from 'vue'
-import { Monitor, User, Key, Clock, CircleClose } from '@element-plus/icons-vue'
+import { Monitor, User, Key, Clock, CircleClose, Connection } from '@element-plus/icons-vue'
 import type { Client } from '../utils/client'
 import type { Client } from '../utils/client'
 
 
 interface Props {
 interface Props {
@@ -190,37 +182,6 @@ html.dark .info-value {
   color: #d1d5db;
   color: #d1d5db;
 }
 }
 
 
-.client-metas {
-  margin-bottom: 16px;
-  padding-top: 12px;
-  border-top: 1px solid #e4e7ed;
-}
-
-html.dark .client-metas {
-  border-top-color: #3a3d5c;
-}
-
-.metas-label {
-  font-size: 13px;
-  color: #909399;
-  font-weight: 500;
-  margin-bottom: 8px;
-}
-
-html.dark .metas-label {
-  color: #9ca3af;
-}
-
-.metas-tags {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 6px;
-}
-
-.meta-tag {
-  font-size: 12px;
-}
-
 .monospace {
 .monospace {
   font-family: 'Courier New', Courier, monospace;
   font-family: 'Courier New', Courier, monospace;
   font-size: 12px;
   font-size: 12px;

+ 3 - 2
web/frps/src/types/client.ts

@@ -1,9 +1,10 @@
 export interface ClientInfoData {
 export interface ClientInfoData {
   key: string
   key: string
   user: string
   user: string
-  clientId: string
-  runId: string
+  clientID: string
+  runID: string
   hostname: string
   hostname: string
+  clientIP?: string
   metas?: Record<string, string>
   metas?: Record<string, string>
   firstConnectedAt: number
   firstConnectedAt: number
   lastConnectedAt: number
   lastConnectedAt: number

+ 12 - 10
web/frps/src/utils/client.ts

@@ -4,9 +4,10 @@ import type { ClientInfoData } from '../types/client'
 export class Client {
 export class Client {
   key: string
   key: string
   user: string
   user: string
-  clientId: string
-  runId: string
+  clientID: string
+  runID: string
   hostname: string
   hostname: string
+  ip: string
   metas: Map<string, string>
   metas: Map<string, string>
   firstConnectedAt: Date
   firstConnectedAt: Date
   lastConnectedAt: Date
   lastConnectedAt: Date
@@ -16,9 +17,10 @@ export class Client {
   constructor(data: ClientInfoData) {
   constructor(data: ClientInfoData) {
     this.key = data.key
     this.key = data.key
     this.user = data.user
     this.user = data.user
-    this.clientId = data.clientId
-    this.runId = data.runId
+    this.clientID = data.clientID
+    this.runID = data.runID
     this.hostname = data.hostname
     this.hostname = data.hostname
+    this.ip = data.clientIP || ''
     this.metas = new Map<string, string>()
     this.metas = new Map<string, string>()
     if (data.metas) {
     if (data.metas) {
       for (const [key, value] of Object.entries(data.metas)) {
       for (const [key, value] of Object.entries(data.metas)) {
@@ -34,14 +36,14 @@ export class Client {
   }
   }
 
 
   get displayName(): string {
   get displayName(): string {
-    if (this.clientId) {
-      return this.user ? `${this.user}.${this.clientId}` : this.clientId
+    if (this.clientID) {
+      return this.user ? `${this.user}.${this.clientID}` : this.clientID
     }
     }
-    return this.runId
+    return this.runID
   }
   }
 
 
   get shortRunId(): string {
   get shortRunId(): string {
-    return this.runId.substring(0, 8)
+    return this.runID.substring(0, 8)
   }
   }
 
 
   get firstConnectedAgo(): string {
   get firstConnectedAgo(): string {
@@ -74,8 +76,8 @@ export class Client {
     return (
     return (
       this.key.toLowerCase().includes(search) ||
       this.key.toLowerCase().includes(search) ||
       this.user.toLowerCase().includes(search) ||
       this.user.toLowerCase().includes(search) ||
-      this.clientId.toLowerCase().includes(search) ||
-      this.runId.toLowerCase().includes(search) ||
+      this.clientID.toLowerCase().includes(search) ||
+      this.runID.toLowerCase().includes(search) ||
       this.hostname.toLowerCase().includes(search)
       this.hostname.toLowerCase().includes(search)
     )
     )
   }
   }

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików