diff --git a/.web/docs/developers/subscribe_example.go b/.web/docs/developers/subscribe_example.go index 897404d4..a295c0e1 100644 --- a/.web/docs/developers/subscribe_example.go +++ b/.web/docs/developers/subscribe_example.go @@ -11,7 +11,8 @@ func SubscribeExample(p *proxy.Proxy) { mgr := p.Event() // Subscribe to an event. - event.Subscribe(mgr, 0, func(e *proxy.PreLoginEvent) { + const priority = 0 + event.Subscribe(mgr, priority, func(e *proxy.PreLoginEvent) { // Kicks every player e.Deny(&component.Text{Content: "Sorry, the server is in maintenance."}) }) diff --git a/.web/docs/guide/lite.md b/.web/docs/guide/lite.md index 21a305cf..33f9cb27 100644 --- a/.web/docs/guide/lite.md +++ b/.web/docs/guide/lite.md @@ -73,7 +73,7 @@ config: ## Security considerations -If you use Lite mode and you backend servers do player authentication, +If you use Lite mode and your backend servers do player authentication, you do not need to worry. Checkout the [Anti-DDoS](security#ddos-protecting-your-minecraft-server) guide for how diff --git a/.web/docs/guide/security.md b/.web/docs/guide/security.md index 38b2c221..683de4f0 100644 --- a/.web/docs/guide/security.md +++ b/.web/docs/guide/security.md @@ -17,7 +17,7 @@ This does not apply to [Lite mode](lite), where backend servers should do the au ## DDoS Protecting your Minecraft server -If you are running a public Minecraft server, and you are not using [Connect](https://connect.minekube.com), +If you are running a high-profile public Minecraft server, and you are not using [Connect](https://connect.minekube.com), having a good DDoS protection is essential to prevent your server from being taken offline. If you are under attack, your server will be lagging, become unresponsive and timeout players. diff --git a/pkg/edition/java/proto/codec/encoder.go b/pkg/edition/java/proto/codec/encoder.go index 5538b19a..6f036fc6 100644 --- a/pkg/edition/java/proto/codec/encoder.go +++ b/pkg/edition/java/proto/codec/encoder.go @@ -67,8 +67,8 @@ func (e *Encoder) WritePacket(packet proto.Packet) (n int, err error) { defer e.mu.Unlock() packetID, found := e.registry.PacketID(packet) if !found { - return n, fmt.Errorf("packet id for type %T in protocol %s not registered in the %s state registry", - packet, e.registry.Protocol, e.state) + return n, fmt.Errorf("packet id for type %T in protocol %s not registered in the %s %s state registry", + packet, e.registry.Protocol, e.direction, e.state) } pk := reflect.TypeOf(packet) diff --git a/pkg/edition/java/proto/packet/chat/builder.go b/pkg/edition/java/proto/packet/chat/builder.go index b73d68ef..022dc35b 100644 --- a/pkg/edition/java/proto/packet/chat/builder.go +++ b/pkg/edition/java/proto/packet/chat/builder.go @@ -82,11 +82,7 @@ func (b *Builder) ToServer() proto.Packet { if b.Timestamp.IsZero() { b.Timestamp = time.Now() } - if b.Protocol.GreaterEqual(version.Minecraft_1_19_3) { // Keyed chat - if strings.HasPrefix(b.Message, "/") { - return NewKeyedPlayerCommand(strings.TrimPrefix(b.Message, "/"), nil, b.Timestamp) - } - } else if b.Protocol.GreaterEqual(version.Minecraft_1_19) { // Session chat + if b.Protocol.GreaterEqual(version.Minecraft_1_19_3) { // Session chat if strings.HasPrefix(b.Message, "/") { return &SessionPlayerCommand{ Command: strings.TrimPrefix(b.Message, "/"), @@ -96,6 +92,17 @@ func (b *Builder) ToServer() proto.Packet { return &SessionPlayerChat{ Message: b.Message, Timestamp: b.Timestamp, + Signature: []byte{0}, + } + } else if b.Protocol.GreaterEqual(version.Minecraft_1_19) { // Keyed chat + if strings.HasPrefix(b.Message, "/") { + return NewKeyedPlayerCommand(strings.TrimPrefix(b.Message, "/"), nil, b.Timestamp) + } + // This will produce an error on the server, but needs to be here. + return &KeyedPlayerChat{ + Message: b.Message, + Unsigned: true, + Expiry: b.Timestamp, } } // Legacy chat diff --git a/pkg/edition/java/proxy/handle_chat.go b/pkg/edition/java/proxy/handle_chat.go index a6a2b98b..df6f931e 100644 --- a/pkg/edition/java/proxy/handle_chat.go +++ b/pkg/edition/java/proxy/handle_chat.go @@ -80,10 +80,8 @@ func (c *chatHandler) handleSessionChat(packet *chat.SessionPlayerChat) error { } return nil } - if evt.Message() != packet.Message { - if packet.Signed { - c.invalidChange(c.log, c.player) + if packet.Signed && c.invalidChange(c.log, c.player) { return nil } return server.WritePacket((&chat.Builder{ @@ -132,9 +130,8 @@ func (c *chatHandler) handleOldSignedChat(server netmc.MinecraftConn, packet *ch } if event.Message() != packet.Message { - if denyRevision { + if denyRevision && c.invalidChange(c.log, c.player) { // Bad, very bad. - c.invalidChange(c.log, c.player) return nil } c.log.Info("a plugin changed a signed chat message. The server may not accept it") @@ -152,15 +149,17 @@ func (c *chatHandler) invalidCancel(log logr.Logger, player *connectedPlayer) { c.invalidMessage(log.WithName("invalidCancel"), player) } -func (c *chatHandler) invalidChange(log logr.Logger, player *connectedPlayer) { - c.invalidMessage(log.WithName("invalidChange"), player) +func (c *chatHandler) invalidChange(log logr.Logger, player *connectedPlayer) bool { + return c.invalidMessage(log.WithName("invalidChange"), player) } -func (c *chatHandler) invalidMessage(log logr.Logger, player *connectedPlayer) { +func (c *chatHandler) invalidMessage(log logr.Logger, player *connectedPlayer) bool { if c.disconnectIllegalProtocolState(player) { log.Info("A plugin tried to cancel a signed chat message." + " This is no longer possible in 1.19.1 and newer. Try disabling forceKeyAuthentication if you still want to allow this.") + return true } + return false } func (c *chatHandler) disconnectIllegalProtocolState(player *connectedPlayer) bool {