From 2fc0f7a74ff2092eea140b7b3a3e298e11444528 Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Sat, 28 Sep 2024 15:36:04 +0100 Subject: [PATCH] log challenge requests --- pkg/udpproxy/session.go | 11 ++++++-- pkg/udpproxy/udpproxy.go | 4 +-- pkg/udpproxy/validator.go | 54 ++++++++++++++++++++++----------------- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/pkg/udpproxy/session.go b/pkg/udpproxy/session.go index 2d5b2b5..99b86e3 100644 --- a/pkg/udpproxy/session.go +++ b/pkg/udpproxy/session.go @@ -2,6 +2,7 @@ package udpproxy import ( "errors" + "fmt" "net" "strings" "time" @@ -68,7 +69,7 @@ func (s *session) proxyFrom(buf []byte) error { if s.isBadRconResponse(buf) { log.Infof("Response: Bad rcon from %s", s.caddr.IP) } else { - log.Debugf("Response: %s", string(buf[10:])) + log.Debugf("Response: %s", string(buf[len(s.rconResponseHeader):])) } } @@ -77,7 +78,13 @@ func (s *session) proxyFrom(buf []byte) error { func (s *session) proxyTo(buf []byte) error { if !s.isValidRequestPacket(buf) { - err := errors.New("not a rcon or query request packet") + var err error + if s.isChallengeRequestPacket(buf) { + parts := strings.SplitN(string(buf), " ", 3) + err = fmt.Errorf("invalid challenge from %s with GUID: %s", s.caddr.IP, parts[len(parts)-1]) + } else { + err = errors.New("not a rcon or query request packet") + } log.Error(err.Error()) return err } diff --git a/pkg/udpproxy/udpproxy.go b/pkg/udpproxy/udpproxy.go index 6437da9..04df3b8 100644 --- a/pkg/udpproxy/udpproxy.go +++ b/pkg/udpproxy/udpproxy.go @@ -53,8 +53,8 @@ func (c *Client) ListenAndServe() error { log.Error(err) } - session, found := c.sessions[caddr.String()] - if !found { + session, ok := c.sessions[caddr.String()] + if !ok { session, err = newSession(caddr, c.raddr, c.proxyConn) if err != nil { log.Error(err) diff --git a/pkg/udpproxy/validator.go b/pkg/udpproxy/validator.go index f60b405..5faf007 100644 --- a/pkg/udpproxy/validator.go +++ b/pkg/udpproxy/validator.go @@ -3,57 +3,63 @@ package udpproxy import "bytes" type validator struct { - rconRequestHeader []byte - getstatusRequestHeader []byte - getinfoRequestHeader []byte - rconResponseHeader []byte - getstatusResponseHeader []byte - getinfoResponseHeader []byte - badRconIdentifier []byte + rconRequestHeader []byte + getstatusRequestHeader []byte + getinfoRequestHeader []byte + getchallengeRequestHeader []byte + rconResponseHeader []byte + getstatusResponseHeader []byte + getinfoResponseHeader []byte + badRconIdentifier []byte } func newValidator() validator { - v := validator{} - v.rconRequestHeader = []byte("\xff\xff\xff\xffrcon") - v.getstatusRequestHeader = []byte("\xff\xff\xff\xffgetstatus") - v.getinfoRequestHeader = []byte("\xff\xff\xff\xffgetinfo") - v.rconResponseHeader = []byte("\xff\xff\xff\xffprint\n") - v.getstatusResponseHeader = []byte("\xff\xff\xff\xffstatusResponse\n") - v.getinfoResponseHeader = []byte("\xff\xff\xff\xffinfoResponse\n") - v.badRconIdentifier = []byte("Bad rcon") - return v + return validator{ + rconRequestHeader: []byte("\xff\xff\xff\xffrcon"), + getstatusRequestHeader: []byte("\xff\xff\xff\xffgetstatus"), + getinfoRequestHeader: []byte("\xff\xff\xff\xffgetinfo"), + getchallengeRequestHeader: []byte("\xff\xff\xff\xffgetchallenge"), + rconResponseHeader: []byte("\xff\xff\xff\xffprint\n"), + getstatusResponseHeader: []byte("\xff\xff\xff\xffstatusResponse\n"), + getinfoResponseHeader: []byte("\xff\xff\xff\xffinfoResponse\n"), + badRconIdentifier: []byte("Bad rcon"), + } } -func (v *validator) compare(buf, c []byte) bool { +func (v validator) compare(buf, c []byte) bool { return bytes.Equal(buf[:len(c)], c) } -func (v *validator) isRconRequestPacket(buf []byte) bool { +func (v validator) isRconRequestPacket(buf []byte) bool { return v.compare(buf, v.rconRequestHeader) } -func (v *validator) isQueryRequestPacket(buf []byte) bool { +func (v validator) isQueryRequestPacket(buf []byte) bool { return v.compare(buf, v.getstatusRequestHeader) || v.compare(buf, v.getinfoRequestHeader) } -func (v *validator) isValidRequestPacket(buf []byte) bool { +func (v validator) isValidRequestPacket(buf []byte) bool { return v.isRconRequestPacket(buf) || v.isQueryRequestPacket(buf) } -func (v *validator) isRconResponsePacket(buf []byte) bool { +func (v validator) isChallengeRequestPacket(buf []byte) bool { + return v.compare(buf, v.getchallengeRequestHeader) +} + +func (v validator) isRconResponsePacket(buf []byte) bool { return v.compare(buf, v.rconResponseHeader) } -func (v *validator) isQueryResponsePacket(buf []byte) bool { +func (v validator) isQueryResponsePacket(buf []byte) bool { return v.compare(buf, v.getstatusResponseHeader) || v.compare(buf, v.getinfoResponseHeader) } -func (v *validator) isValidResponsePacket(buf []byte) bool { +func (v validator) isValidResponsePacket(buf []byte) bool { return v.isRconResponsePacket(buf) || v.isQueryResponsePacket(buf) } -func (v *validator) isBadRconResponse(buf []byte) bool { +func (v validator) isBadRconResponse(buf []byte) bool { return v.compare(buf[len(v.rconResponseHeader):], v.badRconIdentifier) }