Skip to content

Commit 65c9814

Browse files
committed
Redesign secure telnet port configuration for TLS proxy architecture
- SecureTelnetPort is now display-only (shown on website, not bound) - Added SecureTelnetLocalPort for internal binding (where TLS proxy forwards) - Updated connection detection to check SecureTelnetLocalPort - This allows proper stunnel4/HAProxy integration: * TLS proxy binds to public SecureTelnetPort (e.g., 33334) * TLS proxy forwards to SecureTelnetLocalPort (e.g., 9998) * Game binds to SecureTelnetLocalPort on localhost only * Connections via SecureTelnetLocalPort show as 'TLS' on online page
1 parent 620752f commit 65c9814

File tree

4 files changed

+26
-24
lines changed

4 files changed

+26
-24
lines changed

_datafiles/config.yaml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,10 +384,17 @@ Network:
384384
# ports by separating them with commas. For example, [33333, 33334, 33335]
385385
TelnetPort: [33333, 44444]
386386
# - SecureTelnetPort -
387-
# Localhost-only ports for secure telnet connections (e.g., TLS proxy forwarding).
388-
# Like LocalPort but shown on website. Multiple ports supported: [33334, 33335]
389-
# Set to [0] to disable.
387+
# Display-only: External ports where users connect via TLS proxy (e.g., stunnel4).
388+
# These ports are shown on the website but NOT bound by the game server.
389+
# Example: [33334] if stunnel4 listens on port 33334
390+
# Set to [0] to disable display.
390391
SecureTelnetPort: [0]
392+
# - SecureTelnetLocalPort -
393+
# Internal port where TLS proxy forwards secure connections (localhost only).
394+
# Game server binds to this port to receive forwarded TLS connections.
395+
# Example: 9998 if stunnel4 forwards to localhost:9998
396+
# Set to 0 to disable.
397+
SecureTelnetLocalPort: 0
391398
# - LocalPort -
392399
# A port that can only be accessed via localhost, but will not limit based on connection count
393400
LocalPort: 9999

internal/configs/config.network.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package configs
22

33
type Network struct {
4-
MaxTelnetConnections ConfigInt `yaml:"MaxTelnetConnections"` // Maximum number of telnet connections to accept
5-
TelnetPort ConfigSliceString `yaml:"TelnetPort"` // One or more Ports used to accept telnet connections
6-
SecureTelnetPort ConfigSliceString `yaml:"SecureTelnetPort"` // One or more Ports used to accept secure telnet connections
7-
LocalPort ConfigInt `yaml:"LocalPort"` // Port used for admin connections, localhost only
8-
HttpPort ConfigInt `yaml:"HttpPort"` // Port used for web requests
9-
HttpsPort ConfigInt `yaml:"HttpsPort"` // Port used for web https requests
4+
MaxTelnetConnections ConfigInt `yaml:"MaxTelnetConnections"` // Maximum number of telnet connections to accept
5+
TelnetPort ConfigSliceString `yaml:"TelnetPort"` // One or more Ports used to accept telnet connections
6+
SecureTelnetPort ConfigSliceString `yaml:"SecureTelnetPort"` // Display-only: external ports where users connect via TLS
7+
SecureTelnetLocalPort ConfigInt `yaml:"SecureTelnetLocalPort"` // Internal port where TLS proxy forwards to (localhost only)
8+
LocalPort ConfigInt `yaml:"LocalPort"` // Port used for admin connections, localhost only
9+
HttpPort ConfigInt `yaml:"HttpPort"` // Port used for web requests
10+
HttpsPort ConfigInt `yaml:"HttpsPort"` // Port used for web https requests
1011
HttpsRedirect ConfigBool `yaml:"HttpsRedirect"` // If true, http traffic will be redirected to https
1112
AfkSeconds ConfigInt `yaml:"AfkSeconds"` // How long until a player is marked as afk?
1213
MaxIdleSeconds ConfigInt `yaml:"MaxIdleSeconds"` // How many seconds a player can go without a command in game before being kicked.

internal/users/userrecord.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -625,19 +625,15 @@ func (u *UserRecord) GetOnlineInfo() OnlineInfo {
625625
if connections.IsWebsocket(u.connectionId) {
626626
connectionType = "Web"
627627
} else {
628-
// Check if connected through a secure telnet port
628+
// Check if connected through the secure telnet local port (where TLS proxy forwards)
629629
port := connections.GetConnectionPort(u.connectionId)
630630
networkConfig := configs.GetNetworkConfig()
631631

632632
// Debug logging
633-
mudlog.Debug("Connection type check", "connectionId", u.connectionId, "port", port, "securePorts", networkConfig.SecureTelnetPort)
633+
mudlog.Debug("Connection type check", "connectionId", u.connectionId, "port", port, "secureLocalPort", networkConfig.SecureTelnetLocalPort)
634634

635-
for _, securePortStr := range networkConfig.SecureTelnetPort {
636-
securePort, _ := strconv.Atoi(securePortStr)
637-
if securePort > 0 && port == securePort {
638-
connectionType = "TLS"
639-
break
640-
}
635+
if networkConfig.SecureTelnetLocalPort > 0 && port == int(networkConfig.SecureTelnetLocalPort) {
636+
connectionType = "TLS"
641637
}
642638
}
643639

main.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,13 +271,11 @@ func main() {
271271
TelnetListenOnPort(`127.0.0.1`, int(c.Network.LocalPort), &wg, 0)
272272
}
273273

274-
// Secure telnet ports - same as LocalPort but tracked differently
275-
for _, port := range c.Network.SecureTelnetPort {
276-
if p, err := strconv.Atoi(port); err == nil && p > 0 {
277-
mudlog.Info("Telnet", "stage", "Listening on secure port (localhost only)", "port", p)
278-
// Same as LocalPort - localhost only, no connection limit
279-
TelnetListenOnPort(`127.0.0.1`, p, &wg, 0)
280-
}
274+
// Secure telnet local port - where TLS proxy forwards to
275+
if c.Network.SecureTelnetLocalPort > 0 {
276+
mudlog.Info("Telnet", "stage", "Listening on secure local port (localhost only)", "port", c.Network.SecureTelnetLocalPort)
277+
// Same as LocalPort - localhost only, no connection limit
278+
TelnetListenOnPort(`127.0.0.1`, int(c.Network.SecureTelnetLocalPort), &wg, 0)
281279
}
282280

283281
go worldManager.InputWorker(workerShutdownChan, &wg)

0 commit comments

Comments
 (0)