Files
wol-sol-agent/server/udp.go
2025-11-12 22:32:39 +01:00

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
}