diff --git a/config.go b/config.go index 21499f2..3e91153 100644 --- a/config.go +++ b/config.go @@ -24,6 +24,10 @@ type Config struct { // to the proxy and start communicating. Secret string `json:"secret"` } `json:"communication"` + // ReaderLimits determines if things like slices will have a maximum length as they are read from socket clients. + // It is recommended that this is always set to true in order to prevent possible attack vectors, however if any + // non-malicious clients are reaching these limits, you may want to disable it. + ReaderLimits bool `json:"reader_limits"` } `json:"network"` // Logger holds settings related to the logging aspects of the proxy. Logger struct { @@ -62,6 +66,7 @@ type Config struct { func DefaultConfig() (c Config) { c.Network.Address = ":19132" c.Network.Communication.Address = ":19131" + c.Network.ReaderLimits = true c.Logger.File = "proxy.log" c.Logger.Level = "debug" c.PlayerLatency.Report = true diff --git a/examples/main.go b/examples/main.go index 9660285..ead140c 100644 --- a/examples/main.go +++ b/examples/main.go @@ -65,7 +65,7 @@ func main() { logger.Fatalf("failed to listen on %s: %v", conf.Network.Address, err) } - socketServer := socket.NewDefaultServer(conf.Network.Communication.Address, conf.Network.Communication.Secret, p.SessionStore(), p.ServerRegistry(), logger) + socketServer := socket.NewDefaultServer(conf.Network.Communication.Address, conf.Network.Communication.Secret, p.SessionStore(), p.ServerRegistry(), logger, conf.Network.ReaderLimits) if err := socketServer.Listen(); err != nil { p.Logger().Fatalf("socket server failed to listen: %v", err) } diff --git a/socket/client.go b/socket/client.go index be75d6d..e3aca59 100644 --- a/socket/client.go +++ b/socket/client.go @@ -17,6 +17,8 @@ type Client struct { log internal.Logger conn net.Conn + readerLimits bool + pool packet.Pool sendMu sync.Mutex @@ -29,11 +31,13 @@ type Client struct { // NewClient creates a new socket Client with default allocations and required data. It pre-allocates 4096 // bytes to prevent allocations during runtime as much as possible. -func NewClient(conn net.Conn, log internal.Logger) *Client { +func NewClient(conn net.Conn, log internal.Logger, readerLimits bool) *Client { return &Client{ log: log, conn: conn, + readerLimits: readerLimits, + pool: packet.NewPool(), buf: bytes.NewBuffer(make([]byte, 0, 4096)), hdr: &packet.Header{}, @@ -95,7 +99,7 @@ func (c *Client) ReadPacket() (pk packet.Packet, err error) { err = fmt.Errorf("%T: %w", pk, recoveredErr.(error)) } }() - pk.Unmarshal(protocol.NewReader(buf, 0)) + pk.Unmarshal(protocol.NewReader(buf, 0, c.readerLimits)) if buf.Len() > 0 { return nil, fmt.Errorf("still have %v bytes unread", buf.Len()) } diff --git a/socket/server.go b/socket/server.go index 1011dd1..58f45b9 100644 --- a/socket/server.go +++ b/socket/server.go @@ -39,8 +39,9 @@ type Server interface { type DefaultServer struct { log internal.Logger - addr string - secret string + addr string + secret string + readerLimits bool listener net.Listener clientsMu sync.RWMutex @@ -52,12 +53,13 @@ type DefaultServer struct { } // NewDefaultServer creates a new default server to be used for accepting socket connections. -func NewDefaultServer(addr, secret string, sessionStore *session.Store, serverRegistry *server.Registry, log internal.Logger) *DefaultServer { +func NewDefaultServer(addr, secret string, sessionStore *session.Store, serverRegistry *server.Registry, log internal.Logger, readerLimits bool) *DefaultServer { return &DefaultServer{ log: log, - addr: addr, - secret: secret, + addr: addr, + secret: secret, + readerLimits: readerLimits, clients: make(map[string]*Client), unconnectedClients: make(map[net.Addr]*Client), @@ -85,7 +87,7 @@ func (s *DefaultServer) Listen() error { } s.log.Debugf("socket server accepted a new connection") - go s.handleClient(NewClient(conn, s.log)) + go s.handleClient(NewClient(conn, s.log, s.readerLimits)) } }() return nil