mirror of
https://github.com/r-smith/deceptifeed.git
synced 2025-10-23 00:12:22 +00:00
Compare commits
6 Commits
153191f6c5
...
fd02995f52
Author | SHA1 | Date | |
---|---|---|---|
|
fd02995f52 | ||
|
4ab8f2dfee | ||
|
cefc9952f0 | ||
|
5c91ae0e4f | ||
|
363c429a1e | ||
|
8c97e05f6f |
@@ -28,6 +28,7 @@
|
||||
<port>2222</port>
|
||||
<logEnabled>true</logEnabled>
|
||||
<sendToThreatFeed>true</sendToThreatFeed>
|
||||
<useProxyProtocol>false</useProxyProtocol>
|
||||
<keyPath>/opt/deceptifeed/certs/ssh-key.pem</keyPath>
|
||||
<banner>SSH-2.0-OpenSSH_9.6</banner>
|
||||
</server>
|
||||
@@ -38,6 +39,7 @@
|
||||
<port>8080</port>
|
||||
<logEnabled>true</logEnabled>
|
||||
<sendToThreatFeed>true</sendToThreatFeed>
|
||||
<sourceIpHeader></sourceIpHeader>
|
||||
<rules>
|
||||
<!-- Update the threat feed if any of the following rules match: -->
|
||||
<include target="path" negate="true">(?i)^(/|/index\.html|/favicon\.ico|/robots\.txt|/sitemap\.xml|/\.well-known/\w+\.txt)$</include>
|
||||
@@ -55,6 +57,7 @@
|
||||
<port>8443</port>
|
||||
<logEnabled>true</logEnabled>
|
||||
<sendToThreatFeed>true</sendToThreatFeed>
|
||||
<sourceIpHeader></sourceIpHeader>
|
||||
<certPath>/opt/deceptifeed/certs/https-cert.pem</certPath>
|
||||
<keyPath>/opt/deceptifeed/certs/https-key.pem</keyPath>
|
||||
<rules>
|
||||
@@ -75,6 +78,7 @@
|
||||
<port>2323</port>
|
||||
<logEnabled>true</logEnabled>
|
||||
<sendToThreatFeed>true</sendToThreatFeed>
|
||||
<useProxyProtocol>false</useProxyProtocol>
|
||||
<banner>\nUser Access Verification\n\n</banner>
|
||||
<prompts>
|
||||
<prompt log="username">Username: </prompt>
|
||||
|
@@ -28,6 +28,7 @@
|
||||
<port>2222</port>
|
||||
<logEnabled>true</logEnabled>
|
||||
<sendToThreatFeed>true</sendToThreatFeed>
|
||||
<useProxyProtocol>false</useProxyProtocol>
|
||||
<keyPath>key-ssh-private.pem</keyPath>
|
||||
<banner>SSH-2.0-OpenSSH_9.6</banner>
|
||||
</server>
|
||||
@@ -38,6 +39,7 @@
|
||||
<port>8080</port>
|
||||
<logEnabled>true</logEnabled>
|
||||
<sendToThreatFeed>true</sendToThreatFeed>
|
||||
<sourceIpHeader></sourceIpHeader>
|
||||
<rules>
|
||||
<!-- Update the threat feed if any of the following rules match: -->
|
||||
<include target="path" negate="true">(?i)^(/|/index\.html|/favicon\.ico|/robots\.txt|/sitemap\.xml|/\.well-known/\w+\.txt)$</include>
|
||||
@@ -55,6 +57,7 @@
|
||||
<port>8443</port>
|
||||
<logEnabled>true</logEnabled>
|
||||
<sendToThreatFeed>true</sendToThreatFeed>
|
||||
<sourceIpHeader></sourceIpHeader>
|
||||
<certPath>key-https-public.pem</certPath>
|
||||
<keyPath>key-https-private.pem</keyPath>
|
||||
<rules>
|
||||
@@ -75,6 +78,7 @@
|
||||
<port>2323</port>
|
||||
<logEnabled>true</logEnabled>
|
||||
<sendToThreatFeed>true</sendToThreatFeed>
|
||||
<useProxyProtocol>false</useProxyProtocol>
|
||||
<banner>\nUser Access Verification\n\n</banner>
|
||||
<prompts>
|
||||
<prompt log="username">Username: </prompt>
|
||||
|
@@ -104,6 +104,7 @@ type Server struct {
|
||||
Headers []string `xml:"headers>header"`
|
||||
Prompts []Prompt `xml:"prompts>prompt"`
|
||||
SendToThreatFeed bool `xml:"sendToThreatFeed"`
|
||||
UseProxyProtocol bool `xml:"useProxyProtocol"`
|
||||
Rules Rules `xml:"rules"`
|
||||
SourceIPHeader string `xml:"sourceIpHeader"`
|
||||
LogPath string `xml:"logPath"`
|
||||
@@ -257,9 +258,15 @@ func (c *Config) InitializeLoggers() error {
|
||||
io.MultiWriter(file, c.Monitor),
|
||||
&slog.HandlerOptions{
|
||||
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
|
||||
// Remove 'message' and 'log level' fields from output.
|
||||
if a.Key == slog.MessageKey || a.Key == slog.LevelKey {
|
||||
switch a.Key {
|
||||
case slog.MessageKey, slog.LevelKey:
|
||||
// Remove default 'message' and 'log level' fields.
|
||||
return slog.Attr{}
|
||||
case "source_ip_error":
|
||||
// Remove 'source_ip_error' field if it's empty.
|
||||
if len(a.Value.String()) == 0 {
|
||||
return slog.Attr{}
|
||||
}
|
||||
}
|
||||
return a
|
||||
},
|
||||
|
@@ -149,21 +149,21 @@ func listenHTTPS(cfg *config.Server, response *responseConfig) {
|
||||
// based on the honeypot configuration.
|
||||
func handleConnection(cfg *config.Server, customHeaders map[string]string, response *responseConfig) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Log connection details. The log fields and format differ based on
|
||||
// whether a custom source IP header is configured.
|
||||
dst_ip, dst_port := getLocalAddr(r)
|
||||
src_ip, _, _ := net.SplitHostPort(r.RemoteAddr)
|
||||
logData := []slog.Attr{}
|
||||
// Record connection details.
|
||||
dstIP, dstPort := getLocalAddr(r)
|
||||
srcIP, _, _ := net.SplitHostPort(r.RemoteAddr)
|
||||
var remIP string
|
||||
var parsed bool
|
||||
var errMsg string
|
||||
|
||||
// If a custom source IP header is configured, set remIP to the remote
|
||||
// IP and extract the client IP from the header into srcIP.
|
||||
if len(cfg.SourceIPHeader) > 0 {
|
||||
// A custom source IP header is configured. Set rem_ip to the
|
||||
// original connecting IP and src_ip to the IP from the header. If
|
||||
// the header is missing, invalid, contains multiple IPs, or if
|
||||
// there a multiple headers with the same name, parsing will fail,
|
||||
// and src_ip will fallback to the original connecting IP.
|
||||
rem_ip := src_ip
|
||||
// If the custom header is missing, invalid, contains multiple IPs,
|
||||
// or if there a multiple headers with the same name, parsing will
|
||||
// fail, and srcIP will fallback to the original connecting IP.
|
||||
remIP = srcIP
|
||||
header := r.Header[cfg.SourceIPHeader]
|
||||
parsed := false
|
||||
errMsg := ""
|
||||
switch len(header) {
|
||||
case 0:
|
||||
errMsg = "missing header " + cfg.SourceIPHeader
|
||||
@@ -177,39 +177,33 @@ func handleConnection(cfg *config.Server, customHeaders map[string]string, respo
|
||||
}
|
||||
} else {
|
||||
parsed = true
|
||||
src_ip = v
|
||||
srcIP = v
|
||||
}
|
||||
default:
|
||||
errMsg = "multiple instances of header " + cfg.SourceIPHeader
|
||||
}
|
||||
|
||||
logData = append(logData,
|
||||
slog.String("event_type", "http"),
|
||||
slog.String("source_ip", src_ip),
|
||||
slog.Bool("source_ip_parsed", parsed),
|
||||
)
|
||||
if !parsed {
|
||||
logData = append(logData, slog.String("source_ip_error", errMsg))
|
||||
}
|
||||
logData = append(logData,
|
||||
slog.String("remote_ip", rem_ip),
|
||||
slog.String("server_ip", dst_ip),
|
||||
slog.String("server_port", dst_port),
|
||||
slog.String("server_name", config.GetHostname()),
|
||||
)
|
||||
} else {
|
||||
// No custom source IP header is configured. Log the standard
|
||||
// connection details, keeping src_ip as the remote connecting IP.
|
||||
logData = append(logData,
|
||||
slog.String("event_type", "http"),
|
||||
slog.String("source_ip", src_ip),
|
||||
slog.String("server_ip", dst_ip),
|
||||
slog.String("server_port", dst_port),
|
||||
slog.String("server_name", config.GetHostname()),
|
||||
)
|
||||
}
|
||||
|
||||
// Log standard HTTP request information.
|
||||
// Log the connection details.
|
||||
logData := make([]slog.Attr, 0, 9)
|
||||
logData = append(logData,
|
||||
slog.String("event_type", "http"),
|
||||
slog.String("source_ip", srcIP),
|
||||
)
|
||||
if len(cfg.SourceIPHeader) > 0 {
|
||||
logData = append(logData,
|
||||
slog.Bool("source_ip_parsed", parsed),
|
||||
slog.String("source_ip_error", errMsg),
|
||||
slog.String("remote_ip", remIP),
|
||||
)
|
||||
}
|
||||
logData = append(logData,
|
||||
slog.String("server_ip", dstIP),
|
||||
slog.String("server_port", dstPort),
|
||||
slog.String("server_name", config.GetHostname()),
|
||||
)
|
||||
|
||||
// Log the HTTP request information.
|
||||
eventDetails := []any{
|
||||
slog.String("method", r.Method),
|
||||
slog.String("path", r.URL.Path),
|
||||
@@ -236,13 +230,12 @@ func handleConnection(cfg *config.Server, customHeaders map[string]string, respo
|
||||
cfg.Logger.LogAttrs(context.Background(), slog.LevelInfo, "", logData...)
|
||||
|
||||
// Print a simplified version of the request to the console.
|
||||
fmt.Printf("[HTTP] %s %s %s %s\n", src_ip, r.Method, r.URL.Path, r.URL.RawQuery)
|
||||
fmt.Printf("[HTTP] %s %s %s %s\n", srcIP, r.Method, r.URL.Path, r.URL.RawQuery)
|
||||
|
||||
// Update the threat feed using the source IP address (src_ip). If a
|
||||
// custom header is configured, src_ip contains the IP extracted from
|
||||
// the header. Otherwise, it contains the remote connecting IP.
|
||||
// Update the threat feed with srcIP. If Proxy Protocol is enabled, srcIP
|
||||
// is taken from the proxy header. Otherwise, it's the connecting IP.
|
||||
if shouldUpdateThreatFeed(cfg, r) {
|
||||
threatfeed.Update(src_ip)
|
||||
threatfeed.Update(srcIP)
|
||||
}
|
||||
|
||||
// Apply optional custom HTTP response headers.
|
||||
|
@@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/r-smith/deceptifeed/internal/config"
|
||||
"github.com/r-smith/deceptifeed/internal/proxyproto"
|
||||
"github.com/r-smith/deceptifeed/internal/threatfeed"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
@@ -62,39 +63,6 @@ func Start(cfg *config.Server) {
|
||||
return nil, fmt.Errorf("permission denied")
|
||||
}
|
||||
|
||||
// Define the password authentication callback function.
|
||||
sshConfig.PasswordCallback = func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
|
||||
// Log the the username and password submitted by the client.
|
||||
dst_ip, dst_port, _ := net.SplitHostPort(conn.LocalAddr().String())
|
||||
src_ip, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
||||
cfg.Logger.LogAttrs(context.Background(), slog.LevelInfo, "",
|
||||
slog.String("event_type", "ssh"),
|
||||
slog.String("source_ip", src_ip),
|
||||
slog.String("server_ip", dst_ip),
|
||||
slog.String("server_port", dst_port),
|
||||
slog.String("server_name", config.GetHostname()),
|
||||
slog.Group("event_details",
|
||||
slog.String("username", conn.User()),
|
||||
slog.String("password", string(password)),
|
||||
slog.String("ssh_client", string(conn.ClientVersion())),
|
||||
),
|
||||
)
|
||||
|
||||
// Print a simplified version of the request to the console.
|
||||
fmt.Printf("[SSH] %s Username: %q Password: %q\n", src_ip, conn.User(), string(password))
|
||||
|
||||
// Update the threat feed with the source IP address from the request.
|
||||
if cfg.SendToThreatFeed {
|
||||
threatfeed.Update(src_ip)
|
||||
}
|
||||
|
||||
// Insert fixed delay to mimic PAM.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Reject the authentication request.
|
||||
return nil, fmt.Errorf("invalid username or password")
|
||||
}
|
||||
|
||||
// Start the SSH server.
|
||||
listener, err := net.Listen("tcp", ":"+cfg.Port)
|
||||
if err != nil {
|
||||
@@ -110,21 +78,87 @@ func Start(cfg *config.Server) {
|
||||
continue
|
||||
}
|
||||
|
||||
go handleConnection(conn, sshConfig)
|
||||
go handleConnection(conn, sshConfig, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
// handleConnection manages incoming SSH client connections. It performs the
|
||||
// handshake and handles authentication callbacks.
|
||||
func handleConnection(conn net.Conn, config *ssh.ServerConfig) {
|
||||
func handleConnection(conn net.Conn, sshConfig *ssh.ServerConfig, cfg *config.Server) {
|
||||
defer conn.Close()
|
||||
|
||||
// Record connection details.
|
||||
dstIP, dstPort, _ := net.SplitHostPort(conn.LocalAddr().String())
|
||||
srcIP, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
||||
var remIP string
|
||||
var errMsg string
|
||||
var parsed bool
|
||||
|
||||
// If Proxy Protocol is enabled, set remIP to the remote IP and extract the
|
||||
// client IP from the proxy header into srcIP.
|
||||
if cfg.UseProxyProtocol {
|
||||
remIP = srcIP
|
||||
if clientIP, err := proxyproto.ReadHeader(conn); err != nil {
|
||||
errMsg = err.Error()
|
||||
} else {
|
||||
parsed = true
|
||||
srcIP = clientIP
|
||||
}
|
||||
}
|
||||
|
||||
// Set a connection deadline.
|
||||
_ = conn.SetDeadline(time.Now().Add(serverTimeout))
|
||||
|
||||
// Set the password authentication callback function. This function is
|
||||
// called after a successful SSH handshake. It logs the credentials,
|
||||
// updates the threat feed, then responds to the client that auth failed.
|
||||
sshConfig.PasswordCallback = func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
|
||||
// Log the authentication attempt.
|
||||
logData := make([]slog.Attr, 0, 9)
|
||||
logData = append(logData,
|
||||
slog.String("event_type", "ssh"),
|
||||
slog.String("source_ip", srcIP),
|
||||
)
|
||||
if cfg.UseProxyProtocol {
|
||||
logData = append(logData,
|
||||
slog.Bool("source_ip_parsed", parsed),
|
||||
slog.String("source_ip_error", errMsg),
|
||||
slog.String("remote_ip", remIP),
|
||||
)
|
||||
}
|
||||
logData = append(logData,
|
||||
slog.String("server_ip", dstIP),
|
||||
slog.String("server_port", dstPort),
|
||||
slog.String("server_name", config.GetHostname()),
|
||||
slog.Group("event_details",
|
||||
slog.String("username", conn.User()),
|
||||
slog.String("password", string(password)),
|
||||
slog.String("ssh_client", string(conn.ClientVersion())),
|
||||
),
|
||||
)
|
||||
cfg.Logger.LogAttrs(context.Background(), slog.LevelInfo, "", logData...)
|
||||
|
||||
// Print a simplified version of the request to the console.
|
||||
fmt.Printf("[SSH] %s Username: %q Password: %q\n", srcIP, conn.User(), string(password))
|
||||
|
||||
// Update the threat feed with srcIP. If Proxy Protocol is enabled,
|
||||
// srcIP is from the proxy header. Otherwise, it's the connecting IP.
|
||||
if cfg.SendToThreatFeed {
|
||||
threatfeed.Update(srcIP)
|
||||
}
|
||||
|
||||
// Insert a fixed delay between authentication attempts.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Reject the authentication request.
|
||||
return nil, fmt.Errorf("invalid username or password")
|
||||
}
|
||||
|
||||
// Perform handshake and authentication. Authentication callbacks are
|
||||
// defined in the SSH server configuration. Since authentication requests
|
||||
// are always rejected, this function will consistently return an error,
|
||||
// and no further connection handling is necessary.
|
||||
sshConn, _, _, err := ssh.NewServerConn(conn, config)
|
||||
sshConn, _, _, err := ssh.NewServerConn(conn, sshConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/r-smith/deceptifeed/internal/config"
|
||||
"github.com/r-smith/deceptifeed/internal/proxyproto"
|
||||
"github.com/r-smith/deceptifeed/internal/threatfeed"
|
||||
)
|
||||
|
||||
@@ -31,6 +32,13 @@ func Start(cfg *config.Server) {
|
||||
}
|
||||
defer listener.Close()
|
||||
|
||||
// Replace occurrences of "\n" with "\r\n". The configuration file uses
|
||||
// "\n", but CRLF is expected for TCP protocols.
|
||||
cfg.Banner = strings.ReplaceAll(cfg.Banner, "\\n", "\r\n")
|
||||
for i := range cfg.Prompts {
|
||||
cfg.Prompts[i].Text = strings.ReplaceAll(cfg.Prompts[i].Text, "\\n", "\r\n")
|
||||
}
|
||||
|
||||
// Listen for and accept incoming connections.
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
@@ -48,21 +56,39 @@ func Start(cfg *config.Server) {
|
||||
// client interaction.
|
||||
func handleConnection(conn net.Conn, cfg *config.Server) {
|
||||
defer conn.Close()
|
||||
_ = conn.SetDeadline(time.Now().Add(serverTimeout))
|
||||
|
||||
// Print an optional banner. Replace any occurrences of the newline escape
|
||||
// sequence "\\n" with "\r\n" (carriage return, line feed), used by
|
||||
// protocols such as Telnet and SMTP.
|
||||
if len(cfg.Banner) > 0 {
|
||||
_, _ = conn.Write([]byte(strings.ReplaceAll(cfg.Banner, "\\n", "\r\n")))
|
||||
// Record connection details.
|
||||
dstIP, dstPort, _ := net.SplitHostPort(conn.LocalAddr().String())
|
||||
srcIP, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
||||
var remIP string
|
||||
var parsed bool
|
||||
var errMsg string
|
||||
|
||||
// If Proxy Protocol is enabled, set remIP to the remote IP and extract the
|
||||
// client IP from the proxy header into srcIP.
|
||||
if cfg.UseProxyProtocol {
|
||||
remIP = srcIP
|
||||
if clientIP, err := proxyproto.ReadHeader(conn); err != nil {
|
||||
errMsg = err.Error()
|
||||
} else {
|
||||
parsed = true
|
||||
srcIP = clientIP
|
||||
}
|
||||
}
|
||||
|
||||
// Present the prompts from the server configuration to the connected
|
||||
// client and record their responses.
|
||||
// Set a connection deadline.
|
||||
_ = conn.SetDeadline(time.Now().Add(serverTimeout))
|
||||
|
||||
// Display initial banner to the client if configured.
|
||||
if len(cfg.Banner) > 0 {
|
||||
_, _ = conn.Write([]byte(cfg.Banner))
|
||||
}
|
||||
|
||||
// Display configured prompts to the client and record the responses.
|
||||
scanner := bufio.NewScanner(conn)
|
||||
responses := make(map[string]string)
|
||||
for i, prompt := range cfg.Prompts {
|
||||
_, _ = conn.Write([]byte(strings.ReplaceAll(prompt.Text, "\\n", "\r\n")))
|
||||
_, _ = conn.Write([]byte(prompt.Text))
|
||||
scanner.Scan()
|
||||
var key string
|
||||
// Each prompt includes an optional Log field that serves as the key
|
||||
@@ -70,7 +96,6 @@ func handleConnection(conn net.Conn, cfg *config.Server) {
|
||||
// the response will not be logged. If Log is omitted, the default key
|
||||
// "data00" is used, where "00" is the index plus one.
|
||||
if prompt.Log == "none" {
|
||||
// Skip logging for this entry.
|
||||
continue
|
||||
} else if len(prompt.Log) > 0 {
|
||||
key = prompt.Log
|
||||
@@ -80,8 +105,8 @@ func handleConnection(conn net.Conn, cfg *config.Server) {
|
||||
responses[key] = scanner.Text()
|
||||
}
|
||||
|
||||
// If no prompts are provided in the configuration, wait for the client to
|
||||
// send data then record the received input.
|
||||
// If no prompts are configured, wait for client input and record the
|
||||
// received data.
|
||||
if len(cfg.Prompts) == 0 {
|
||||
scanner.Scan()
|
||||
responses["data"] = scanner.Text()
|
||||
@@ -99,24 +124,34 @@ func handleConnection(conn net.Conn, cfg *config.Server) {
|
||||
return
|
||||
}
|
||||
|
||||
// Log the connection along with all responses received from the client.
|
||||
dst_ip, dst_port, _ := net.SplitHostPort(conn.LocalAddr().String())
|
||||
src_ip, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
||||
cfg.Logger.LogAttrs(context.Background(), slog.LevelInfo, "",
|
||||
// Log the connection and all responses received from the client.
|
||||
logData := make([]slog.Attr, 0, 9)
|
||||
logData = append(logData,
|
||||
slog.String("event_type", "tcp"),
|
||||
slog.String("source_ip", src_ip),
|
||||
slog.String("server_ip", dst_ip),
|
||||
slog.String("server_port", dst_port),
|
||||
slog.String("source_ip", srcIP),
|
||||
)
|
||||
if cfg.UseProxyProtocol {
|
||||
logData = append(logData,
|
||||
slog.Bool("source_ip_parsed", parsed),
|
||||
slog.String("source_ip_error", errMsg),
|
||||
slog.String("remote_ip", remIP),
|
||||
)
|
||||
}
|
||||
logData = append(logData,
|
||||
slog.String("server_ip", dstIP),
|
||||
slog.String("server_port", dstPort),
|
||||
slog.String("server_name", config.GetHostname()),
|
||||
slog.Any("event_details", responses),
|
||||
)
|
||||
cfg.Logger.LogAttrs(context.Background(), slog.LevelInfo, "", logData...)
|
||||
|
||||
// Print a simplified version of the interaction to the console.
|
||||
fmt.Printf("[TCP] %s %q\n", src_ip, responsesToString(responses))
|
||||
fmt.Printf("[TCP] %s %q\n", srcIP, responsesToString(responses))
|
||||
|
||||
// Update the threat feed with the source IP address from the interaction.
|
||||
// Update the threat feed with srcIP. If Proxy Protocol is enabled, srcIP
|
||||
// is taken from the proxy header. Otherwise, it's the connecting IP.
|
||||
if cfg.SendToThreatFeed {
|
||||
threatfeed.Update(src_ip)
|
||||
threatfeed.Update(srcIP)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -57,14 +57,14 @@ func Start(cfg *config.Server) {
|
||||
// addresses, this may not correspond to the IP address that
|
||||
// received the UDP data. However, this limitation is acceptable as
|
||||
// the primary goal is to log the received data.
|
||||
_, dst_port, _ := net.SplitHostPort(conn.LocalAddr().String())
|
||||
src_ip, _, _ := net.SplitHostPort(remoteAddr.String())
|
||||
_, dstPort, _ := net.SplitHostPort(conn.LocalAddr().String())
|
||||
srcIP, _, _ := net.SplitHostPort(remoteAddr.String())
|
||||
cfg.Logger.LogAttrs(context.Background(), slog.LevelInfo, "",
|
||||
slog.String("event_type", "udp"),
|
||||
slog.String("source_ip", src_ip+" [unreliable]"),
|
||||
slog.String("source_ip", srcIP+" [unreliable]"),
|
||||
slog.String("source_reliability", "unreliable"),
|
||||
slog.String("server_ip", config.GetHostIP()),
|
||||
slog.String("server_port", dst_port),
|
||||
slog.String("server_port", dstPort),
|
||||
slog.String("server_name", config.GetHostname()),
|
||||
slog.Group("event_details",
|
||||
slog.String("data", string(buffer[:n])),
|
||||
@@ -72,7 +72,7 @@ func Start(cfg *config.Server) {
|
||||
)
|
||||
|
||||
// Print a simplified version of the interaction to the console.
|
||||
fmt.Printf("[UDP] %s Data: %q\n", src_ip, strings.TrimSpace(string(buffer[:n])))
|
||||
fmt.Printf("[UDP] %s Data: %q\n", srcIP, strings.TrimSpace(string(buffer[:n])))
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user