diff --git a/internal/models/ssh_login.go b/internal/models/ssh_login.go index 8ce70e7..de77a18 100644 --- a/internal/models/ssh_login.go +++ b/internal/models/ssh_login.go @@ -2,16 +2,17 @@ package models // SSHLoginEvent SSH登录事件 type SSHLoginEvent struct { - ID string `gorm:"primaryKey" json:"id"` // 事件ID (UUID) - AgentID string `gorm:"index;not null" json:"agentId"` // 探针ID - Username string `gorm:"index" json:"username"` // 用户名 - IP string `gorm:"index" json:"ip"` // 来源IP - Port string `json:"port,omitempty"` // 来源端口 - Status string `gorm:"index" json:"status"` // 状态: success - TTY string `json:"tty,omitempty"` // 终端 - SessionID string `json:"sessionId,omitempty"` // 会话ID - Timestamp int64 `gorm:"index" json:"timestamp"` // 登录时间(毫秒时间戳) - CreatedAt int64 `json:"createdAt"` // 记录创建时间(毫秒) + ID string `gorm:"primaryKey" json:"id"` // 事件ID (UUID) + AgentID string `gorm:"index;not null" json:"agentId"` // 探针ID + Username string `gorm:"index" json:"username"` // 用户名 + IP string `gorm:"index" json:"ip"` // 来源IP + IPLocation string `gorm:"index" json:"ipLocation,omitempty"` // IP归属地 + Port string `json:"port,omitempty"` // 来源端口 + Status string `gorm:"index" json:"status"` // 状态: success + TTY string `json:"tty,omitempty"` // 终端 + SessionID string `json:"sessionId,omitempty"` // 会话ID + Timestamp int64 `gorm:"index" json:"timestamp"` // 登录时间(毫秒时间戳) + CreatedAt int64 `json:"createdAt"` // 记录创建时间(毫秒) } func (SSHLoginEvent) TableName() string { diff --git a/internal/service/ssh_login_service.go b/internal/service/ssh_login_service.go index 242038b..8860ddf 100644 --- a/internal/service/ssh_login_service.go +++ b/internal/service/ssh_login_service.go @@ -137,18 +137,24 @@ func (s *SSHLoginService) HandleEvent(ctx context.Context, agentID string, event return nil } + ipLocation := "" + if s.geoIPSvc != nil && eventData.IP != "" { + ipLocation = s.geoIPSvc.LookupIP(eventData.IP) + } + // 保存事件到数据库 event := &models.SSHLoginEvent{ - ID: uuid.NewString(), - AgentID: agentID, - Username: eventData.Username, - IP: eventData.IP, - Port: eventData.Port, - Status: eventData.Status, - TTY: eventData.TTY, - SessionID: eventData.SessionID, - Timestamp: eventData.Timestamp, - CreatedAt: time.Now().UnixMilli(), + ID: uuid.NewString(), + AgentID: agentID, + Username: eventData.Username, + IP: eventData.IP, + IPLocation: ipLocation, + Port: eventData.Port, + Status: eventData.Status, + TTY: eventData.TTY, + SessionID: eventData.SessionID, + Timestamp: eventData.Timestamp, + CreatedAt: time.Now().UnixMilli(), } if err := s.SSHLoginEventRepo.Create(ctx, event); err != nil { @@ -166,12 +172,12 @@ func (s *SSHLoginService) HandleEvent(ctx context.Context, agentID string, event s.logger.Info("IP在白名单中,忽略事件", zap.String("agentId", agentID), zap.String("ip", eventData.IP)) return nil } - s.sendLoginSuccessNotification(agentID, eventData) + s.sendLoginSuccessNotification(agentID, eventData, ipLocation) return nil } -func (s *SSHLoginService) sendLoginSuccessNotification(agentID string, eventData protocol.SSHLoginEvent) { +func (s *SSHLoginService) sendLoginSuccessNotification(agentID string, eventData protocol.SSHLoginEvent, ipLocation string) { if s.notificationSvc == nil { return } @@ -199,11 +205,16 @@ func (s *SSHLoginService) sendLoginSuccessNotification(agentID string, eventData sourceAddr = fmt.Sprintf("%s:%s", sourceIP, eventData.Port) } + locationText := ipLocation + if locationText == "" { + locationText = "未知" + } + record := &models.AlertRecord{ AgentID: agentID, AgentName: agent.Name, AlertType: "ssh_login", - Message: fmt.Sprintf("SSH登录成功:用户 %s,来源 %s,终端 %s,会话 %s", eventData.Username, sourceAddr, eventData.TTY, eventData.SessionID), + Message: fmt.Sprintf("SSH登录成功:用户 %s,来源 %s,归属地 %s,终端 %s,会话 %s", eventData.Username, sourceAddr, locationText, eventData.TTY, eventData.SessionID), Threshold: 0, ActualValue: 0, Level: "warning", diff --git a/web/src/admin/pages/Agents/SSHLoginEvents.tsx b/web/src/admin/pages/Agents/SSHLoginEvents.tsx index 460ef67..c549b48 100644 --- a/web/src/admin/pages/Agents/SSHLoginEvents.tsx +++ b/web/src/admin/pages/Agents/SSHLoginEvents.tsx @@ -65,6 +65,13 @@ const SSHLoginEvents: React.FC = ({agentId}) => { {record.ip} ), }, + { + title: '归属地', + dataIndex: 'ipLocation', + key: 'ipLocation', + width: 140, + render: (_, record) => record.ipLocation || '-', + }, { title: '端口', dataIndex: 'port', diff --git a/web/src/types/index.ts b/web/src/types/index.ts index c470fca..de52823 100644 --- a/web/src/types/index.ts +++ b/web/src/types/index.ts @@ -549,6 +549,7 @@ export interface SSHLoginEvent { agentId: string; username: string; ip: string; + ipLocation?: string; port?: string; status: 'success' | 'failed'; method?: string;