150 lines
3.7 KiB
Go
150 lines
3.7 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
|
|
"wolsol-agent/auth"
|
|
"wolsol-agent/magicpacket"
|
|
"wolsol-agent/system"
|
|
|
|
"git.secnex.io/secnex/masterlog"
|
|
)
|
|
|
|
// UDPServer handles UDP connections for Magic Packets
|
|
type UDPServer struct {
|
|
port int
|
|
authenticator *auth.Authenticator
|
|
}
|
|
|
|
// NewUDPServer creates a new UDP server
|
|
func NewUDPServer(port int, authenticator *auth.Authenticator) *UDPServer {
|
|
return &UDPServer{
|
|
port: port,
|
|
authenticator: authenticator,
|
|
}
|
|
}
|
|
|
|
// Start starts the UDP server
|
|
func (s *UDPServer) Start(done chan bool) {
|
|
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", s.port))
|
|
if err != nil {
|
|
masterlog.Error("Failed to resolve UDP address", map[string]interface{}{
|
|
"error": err,
|
|
})
|
|
return
|
|
}
|
|
|
|
conn, err := net.ListenUDP("udp", addr)
|
|
if err != nil {
|
|
masterlog.Error("Failed to listen on UDP port", map[string]interface{}{
|
|
"error": err,
|
|
"port": s.port,
|
|
})
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
masterlog.Info("UDP server listening on port", map[string]interface{}{
|
|
"port": s.port,
|
|
})
|
|
|
|
buffer := make([]byte, 2048)
|
|
|
|
for {
|
|
select {
|
|
case <-done:
|
|
return
|
|
default:
|
|
conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
|
n, clientAddr, err := conn.ReadFromUDP(buffer)
|
|
if err != nil {
|
|
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
|
continue
|
|
}
|
|
masterlog.Error("Error reading UDP packet", map[string]interface{}{
|
|
"error": err,
|
|
})
|
|
continue
|
|
}
|
|
|
|
packetData := buffer[:n]
|
|
|
|
// Debug: Display packet content
|
|
hexDump := hex.EncodeToString(packetData)
|
|
// Also try to show as string (for auth part)
|
|
stringPreview := ""
|
|
if len(packetData) > 0 && packetData[0] < 128 {
|
|
// Only show string preview if it looks like printable ASCII
|
|
maxLen := len(packetData)
|
|
if maxLen > 100 {
|
|
maxLen = 100
|
|
}
|
|
stringPreview = string(packetData[:maxLen])
|
|
}
|
|
|
|
masterlog.Info("Received UDP packet", map[string]interface{}{
|
|
"bytes": n,
|
|
"address": clientAddr,
|
|
"hex": hexDump,
|
|
"string_preview": stringPreview,
|
|
})
|
|
|
|
// Check authentication and magic packet
|
|
if s.isValidAuthenticatedMagicPacket(packetData) {
|
|
masterlog.Info("Authenticated Magic Packet detected! Shutting down system...", map[string]interface{}{
|
|
"address": clientAddr,
|
|
})
|
|
system.Shutdown()
|
|
return
|
|
}
|
|
masterlog.Error("Invalid or unauthenticated packet", map[string]interface{}{
|
|
"address": clientAddr,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// isValidAuthenticatedMagicPacket checks if the packet contains valid authentication
|
|
// followed by a valid Magic Packet
|
|
func (s *UDPServer) isValidAuthenticatedMagicPacket(data []byte) bool {
|
|
username, password, magicPacketData, ok := magicpacket.ExtractAuthFromPacket(data)
|
|
if !ok {
|
|
masterlog.Info("Packet does not contain valid auth format", map[string]interface{}{
|
|
"packet_size": len(data),
|
|
})
|
|
return false
|
|
}
|
|
|
|
masterlog.Info("Extracted authentication from packet", map[string]interface{}{
|
|
"username": username,
|
|
"password_length": len(password),
|
|
"magic_packet_size": len(magicPacketData),
|
|
})
|
|
|
|
// Verify authentication
|
|
if !s.authenticator.Verify(username, password) {
|
|
masterlog.Info("Authentication failed", map[string]interface{}{
|
|
"username": username,
|
|
})
|
|
return false
|
|
}
|
|
|
|
masterlog.Info("Authentication successful", map[string]interface{}{
|
|
"username": username,
|
|
})
|
|
|
|
// Check if it's a valid magic packet
|
|
isValid := magicpacket.IsMagicPacket(magicPacketData)
|
|
if !isValid {
|
|
masterlog.Info("Magic packet validation failed", map[string]interface{}{
|
|
"magic_packet_size": len(magicPacketData),
|
|
"magic_packet_hex": hex.EncodeToString(magicPacketData),
|
|
})
|
|
}
|
|
|
|
return isValid
|
|
}
|