Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add BungeeGuard Compatible mode #390

Merged
merged 6 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .web/docs/guide/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ We highly recommend using [Paper](https://papermc.io/) for running a server in m
Gate is tested with older and most recent versions of it.

You can use `modern` forwarding (like Velocity does) if you run Paper
1.13.2 or higher. If you use Paper 1.12.2 or lower, you must use `legacy` BungeeCord-style forwarding.
1.13.2 or higher. If you use Paper 1.12.2 or lower, you can use `legacy` BungeeCord-style forwarding or the more secure `bungeeguard` [Bungeeguard](https://www.spigotmc.org/resources/bungeeguard.79601/) forwarding.

## Spigot

Spigot is not well-tested with Gate.
However, it is based on vanilla and as it is the base for Paper, it is relatively well-supported.

Spigot does not support Gate/Velocity modern forwarding, but does support legacy BungeeCord forwarding.
Spigot does not support Gate/Velocity modern forwarding, but does support legacy BungeeCord forwarding and the more secure Bungeeguard forwarding when using the [Bungeeguard](https://www.spigotmc.org/resources/bungeeguard.79601/) plugin.

## Forks of Spigot/Paper

Expand Down
4 changes: 3 additions & 1 deletion config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,12 @@ config:
# This allows you to customize how player information such as IPs and UUIDs are forwarded to your server.
# See the documentation for more information.
forwarding:
# Options: legacy, none, velocity
# Options: legacy, none, bungeeguard, velocity
mode: legacy
# The secret used if the mode is velocity.
#velocitySecret: secret_here
# The secret used if the mode is bungeeguard.
#bungeeGuardSecret: secret_here
# Proxy protocol (HA-Proxy) determines whether Gate should support proxy protocol for players.
# Do not enable this if you don't know what it is.
proxyProtocol: false
Expand Down
12 changes: 8 additions & 4 deletions pkg/edition/java/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"fmt"

liteconfig "go.minekube.com/gate/pkg/edition/java/lite/config"
"go.minekube.com/gate/pkg/edition/java/proto/version"
"go.minekube.com/gate/pkg/util/componentutil"
Expand Down Expand Up @@ -135,8 +136,9 @@ type (
ShowPlugins bool `yaml:"showPlugins"`
}
Forwarding struct {
Mode ForwardingMode `yaml:"mode"`
VelocitySecret string `yaml:"velocitySecret"` // Used with "velocity" mode
Mode ForwardingMode `yaml:"mode"`
VelocitySecret string `yaml:"velocitySecret"` // Used with "velocity" mode
BungeeGuardSecret string `yaml:"bungeeGuardSecret"` // Used with "bungeeguard" mode
}
Compression struct {
Threshold int `yaml:"threshold"`
Expand Down Expand Up @@ -171,6 +173,8 @@ const (
// VelocityForwardingMode is a forwarding mode specified by the Velocity java proxy and
// supported by PaperSpigot for versions starting at 1.13.
VelocityForwardingMode ForwardingMode = "velocity"
// BungeeGuardForwardingMode is a forwarding mode used by versions lower than 1.13
BungeeGuardForwardingMode ForwardingMode = "bungeeguard"
)

// Validate validates Config.
Expand Down Expand Up @@ -217,9 +221,9 @@ func (c *Config) Validate() (warns []error, errs []error) {
case NoneForwardingMode:
w("Player forwarding is disabled! Backend servers will have players with " +
"offline-mode UUIDs and the same IP as the proxy.")
case LegacyForwardingMode, VelocityForwardingMode:
case LegacyForwardingMode, VelocityForwardingMode, BungeeGuardForwardingMode:
default:
e("Unknown forwarding mode %q, must be one of none,legacy,velocity", c.Forwarding.Mode)
e("Unknown forwarding mode %q, must be one of none,legacy,velocity,bungeeguard", c.Forwarding.Mode)
}

if len(c.Servers) == 0 {
Expand Down
2 changes: 1 addition & 1 deletion pkg/edition/java/proxy/phase/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (*legacyForgeConnType) AddGameProfileTokensIfRequired(
// since both use the "hostname" field in the handshake. We add a special property to the
// profile instead, which will be ignored by non-Forge servers and can be intercepted by a
// Forge coremod, such as SpongeForge.
if forwardingType == config.LegacyForwardingMode {
if forwardingType == config.LegacyForwardingMode || forwardingType == config.BungeeGuardForwardingMode {
original.Properties = append(original.Properties, profile.Property{Name: "forgeClient", Value: "true"})
}
return original
Expand Down
28 changes: 27 additions & 1 deletion pkg/edition/java/proxy/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"go.minekube.com/gate/pkg/edition/java/forge/modernforge"
"go.minekube.com/gate/pkg/edition/java/profile"
"go.minekube.com/gate/pkg/edition/java/proto/state/states"
"net"
"strings"
Expand Down Expand Up @@ -343,8 +344,12 @@ func (s *serverConnection) handshakeAddr(vHost string, player Player) string {
var ok bool
if ha, ok = s.Server().ServerInfo().(HandshakeAddresser); !ok {
if ha, ok = s.Server().(HandshakeAddresser); !ok {
if s.config().Forwarding.Mode == config.LegacyForwardingMode {
switch s.config().Forwarding.Mode {
case config.LegacyForwardingMode:
return s.createLegacyForwardingAddress()
case config.BungeeGuardForwardingMode:
secret := s.config().Forwarding.BungeeGuardSecret
return s.createBungeeGuardForwardingAddress(secret)
}
}
}
Expand Down Expand Up @@ -491,6 +496,27 @@ func (s *serverConnection) createLegacyForwardingAddress() string {
return b.String()
}

func (s *serverConnection) createBungeeGuardForwardingAddress(secret string) string {
// Bungeeguard IP forwading is the same as the legacy Bungeecord IP forwarding but with an additional
// property in the profile properties that contains the bungeeguard-token.
playerIP := netutil.Host(s.player.RemoteAddr())
b := new(strings.Builder)
b.WriteString(s.server.ServerInfo().Addr().String())
const sep = "\000"
b.WriteString(sep)
b.WriteString(playerIP)
b.WriteString(sep)
b.WriteString(s.player.profile.ID.Undashed())
b.WriteString(sep)
props, err := json.Marshal(
append(s.player.profile.Properties, profile.Property{Name: "bungeeguard-token", Value: secret}))
if err != nil { // should never happen
panic(err)
}
b.WriteString(string(props)) // first convert props to string
return b.String()
}

// Returns the active backend server connection or false if inactive.
func (s *serverConnection) ensureConnected() (backend netmc.MinecraftConn, connected bool) {
if s == nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/edition/java/proxy/session_backend_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func (b *backendLoginSessionHandler) handleServerLoginSuccess() {
}

func (b *backendLoginSessionHandler) Disconnected() {
if b.config().Forwarding.Mode == config.LegacyForwardingMode {
if b.config().Forwarding.Mode == config.LegacyForwardingMode || b.config().Forwarding.Mode == config.BungeeGuardForwardingMode {
b.requestCtx.result(nil, errs.NewSilentErr(`The connection to the remote server was unexpectedly closed.
This is usually because the remote server does not have BungeeCord IP forwarding correctly enabled.`))
} else {
Expand Down
1 change: 0 additions & 1 deletion pkg/edition/java/proxy/session_client_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ func (a *authSessionHandler) Activated() {
// Some connection types may need to alter the game profile.
gameProfile := *a.inbound.delegate.Type().AddGameProfileTokensIfRequired(
a.profile, a.config().Forwarding.Mode)

profileRequest := NewGameProfileRequestEvent(a.inbound, gameProfile, a.onlineMode)
a.eventMgr.Fire(profileRequest)
conn := a.inbound.delegate.MinecraftConn
Expand Down