fix: remote agent exec url_path_prefix error
This commit is contained in:
@@ -10,6 +10,7 @@ baihu
|
|||||||
|
|
||||||
# Data & Logs
|
# Data & Logs
|
||||||
data/
|
data/
|
||||||
|
agent/logs/
|
||||||
!data/agent/
|
!data/agent/
|
||||||
data/agent/*
|
data/agent/*
|
||||||
!data/agent/version.txt
|
!data/agent/version.txt
|
||||||
|
|||||||
+11
-1
@@ -202,9 +202,19 @@ func (a *Agent) connectWS() error {
|
|||||||
wsURL = strings.Replace(wsURL, "https://", "wss://", 1)
|
wsURL = strings.Replace(wsURL, "https://", "wss://", 1)
|
||||||
wsURL = fmt.Sprintf("%s/api/agent/ws?token=%s&machine_id=%s", wsURL, url.QueryEscape(a.config.Token), url.QueryEscape(a.machineID))
|
wsURL = fmt.Sprintf("%s/api/agent/ws?token=%s&machine_id=%s", wsURL, url.QueryEscape(a.config.Token), url.QueryEscape(a.machineID))
|
||||||
|
|
||||||
|
log.Infof("正在连接 WebSocket: %s", wsURL)
|
||||||
|
log.Infof("Token: %s..., MachineID: %s...", a.config.Token[:8], a.machineID[:16])
|
||||||
|
|
||||||
dialer := websocket.Dialer{HandshakeTimeout: 10 * time.Second}
|
dialer := websocket.Dialer{HandshakeTimeout: 10 * time.Second}
|
||||||
conn, _, err := dialer.Dial(wsURL, nil)
|
conn, resp, err := dialer.Dial(wsURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if resp != nil {
|
||||||
|
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||||
|
log.Errorf("WebSocket 握手失败: HTTP %d, Body: %s", resp.StatusCode, string(bodyBytes))
|
||||||
|
resp.Body.Close()
|
||||||
|
} else {
|
||||||
|
log.Errorf("WebSocket 连接失败: %v", err)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
[agent]
|
[agent]
|
||||||
# 主服务器地址(http/https,Agent 会自动转换为 WebSocket 连接)
|
# 主服务器地址(http/https,Agent 会自动转换为 WebSocket 连接)
|
||||||
|
# 如果主服务配置了url_prefix, 这里要也要加上路径
|
||||||
server_url = http://192.168.1.100:8052
|
server_url = http://192.168.1.100:8052
|
||||||
|
# 比如 url_prefix=/baihu
|
||||||
|
; server_url = http://192.168.1.100:8052/baihu
|
||||||
|
|
||||||
# Agent 名称(留空则使用主机名)
|
# Agent 名称(留空则使用主机名)
|
||||||
name =
|
name =
|
||||||
# 注册令牌(首次注册时填写,注册成功后会自动替换为认证 Token)
|
# 注册令牌(首次注册时填写,注册成功后会自动替换为认证 Token)
|
||||||
|
|||||||
@@ -337,8 +337,19 @@ func (c *AgentController) ForceUpdate(ctx *gin.Context) {
|
|||||||
|
|
||||||
// WSConnect Agent WebSocket 连接
|
// WSConnect Agent WebSocket 连接
|
||||||
func (c *AgentController) WSConnect(ctx *gin.Context) {
|
func (c *AgentController) WSConnect(ctx *gin.Context) {
|
||||||
|
// 添加 panic 恢复
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
logger.Errorf("[AgentWS] WSConnect panic: %v", r)
|
||||||
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "服务器内部错误"})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
ip := ctx.ClientIP()
|
ip := ctx.ClientIP()
|
||||||
|
|
||||||
|
// 打印请求信息用于调试
|
||||||
|
logger.Infof("[AgentWS] 收到连接请求: IP=%s, URL=%s", ip, ctx.Request.URL.String())
|
||||||
|
|
||||||
// 检查 IP 限流
|
// 检查 IP 限流
|
||||||
if allowed, reason := c.wsManager.CheckRateLimit(ip); !allowed {
|
if allowed, reason := c.wsManager.CheckRateLimit(ip); !allowed {
|
||||||
logger.Warnf("[AgentWS] IP %s 被限流: %s", ip, reason)
|
logger.Warnf("[AgentWS] IP %s 被限流: %s", ip, reason)
|
||||||
@@ -349,36 +360,45 @@ func (c *AgentController) WSConnect(ctx *gin.Context) {
|
|||||||
token := ctx.Query("token")
|
token := ctx.Query("token")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
c.wsManager.RecordConnectFail(ip)
|
c.wsManager.RecordConnectFail(ip)
|
||||||
|
logger.Warnf("[AgentWS] 连接失败: 缺少 token, IP=%s", ip)
|
||||||
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "缺少 token"})
|
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "缺少 token"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
machineID := ctx.Query("machine_id")
|
machineID := ctx.Query("machine_id")
|
||||||
|
logger.Infof("[AgentWS] Token: %s..., MachineID: %s...", token[:8], machineID[:16])
|
||||||
|
|
||||||
isNewAgent := false
|
isNewAgent := false
|
||||||
|
|
||||||
// 先尝试用 token 查找已有 Agent
|
// 先尝试用 token 查找已有 Agent
|
||||||
agent := c.agentService.GetByToken(token)
|
agent := c.agentService.GetByToken(token)
|
||||||
|
logger.Infof("[AgentWS] GetByToken 结果: agent=%v", agent != nil)
|
||||||
|
|
||||||
// 如果没找到,尝试用令牌注册(会检查 machine_id 是否已存在)
|
// 如果没找到,尝试用令牌注册(会检查 machine_id 是否已存在)
|
||||||
if agent == nil {
|
if agent == nil {
|
||||||
|
logger.Infof("[AgentWS] 尝试注册新 Agent")
|
||||||
var err error
|
var err error
|
||||||
agent, isNewAgent, err = c.agentService.RegisterByToken(token, machineID, ip)
|
agent, isNewAgent, err = c.agentService.RegisterByToken(token, machineID, ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.wsManager.RecordConnectFail(ip)
|
c.wsManager.RecordConnectFail(ip)
|
||||||
|
logger.Warnf("[AgentWS] 注册失败: %v, IP=%s, token=%s", err, ip, token[:8]+"...")
|
||||||
ctx.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
ctx.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
logger.Infof("[AgentWS] 注册成功: Agent #%d, isNew=%v", agent.ID, isNewAgent)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !agent.Enabled {
|
if !agent.Enabled {
|
||||||
c.wsManager.RecordConnectFail(ip)
|
c.wsManager.RecordConnectFail(ip)
|
||||||
|
logger.Warnf("[AgentWS] Agent #%d 已禁用, IP=%s", agent.ID, ip)
|
||||||
ctx.JSON(http.StatusForbidden, gin.H{"error": "Agent 已禁用"})
|
ctx.JSON(http.StatusForbidden, gin.H{"error": "Agent 已禁用"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.Infof("[AgentWS] 准备升级连接: Agent #%d, IP=%s", agent.ID, ip)
|
||||||
conn, err := agentUpgrader.Upgrade(ctx.Writer, ctx.Request, nil)
|
conn, err := agentUpgrader.Upgrade(ctx.Writer, ctx.Request, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("[AgentWS] 升级连接失败: %v", err)
|
logger.Errorf("[AgentWS] 升级连接失败: %v, Agent #%d, IP=%s", err, agent.ID, ip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,6 +419,8 @@ func (c *AgentController) WSConnect(ctx *gin.Context) {
|
|||||||
"machine_id": machineID,
|
"machine_id": machineID,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
logger.Infof("[AgentWS] Agent #%d 连接成功", agent.ID)
|
||||||
|
|
||||||
// 启动读写协程
|
// 启动读写协程
|
||||||
go c.wsWritePump(ac)
|
go c.wsWritePump(ac)
|
||||||
go c.wsReadPump(ac, agent)
|
go c.wsReadPump(ac, agent)
|
||||||
|
|||||||
@@ -217,16 +217,16 @@ func Setup(c *Controllers) *gin.Engine {
|
|||||||
agents.DELETE("/tokens/:id", c.Agent.DeleteToken)
|
agents.DELETE("/tokens/:id", c.Agent.DeleteToken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Agent API(供远程 Agent 调用)
|
// Agent API(供远程 Agent 调用,不使用 /v1 版本号)
|
||||||
agentAPI := api.Group("/agent")
|
agentAPI := root.Group("/api/agent")
|
||||||
{
|
{
|
||||||
agentAPI.POST("/heartbeat", c.Agent.Heartbeat)
|
agentAPI.POST("/heartbeat", c.Agent.Heartbeat)
|
||||||
agentAPI.GET("/tasks", c.Agent.GetTasks)
|
agentAPI.GET("/tasks", c.Agent.GetTasks)
|
||||||
agentAPI.POST("/report", c.Agent.ReportResult)
|
agentAPI.POST("/report", c.Agent.ReportResult)
|
||||||
agentAPI.GET("/download", c.Agent.Download)
|
agentAPI.GET("/download", c.Agent.Download)
|
||||||
agentAPI.GET("/ws", c.Agent.WSConnect) // WebSocket 连接
|
agentAPI.GET("/ws", c.Agent.WSConnect) // WebSocket 连接
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPA fallback - serve index.html (no cache for HTML)
|
// SPA fallback - serve index.html (no cache for HTML)
|
||||||
|
|||||||
Reference in New Issue
Block a user