From d7ca9c8c83b3cefeaf197df6d3e1f56a9932f4e8 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Wed, 15 Apr 2026 12:36:56 -0400 Subject: [PATCH] fix: bind telnet and web client to localhost only (#9) Security fix: Change from 0.0.0.0 to 127.0.0.1 for both TELNET_INTERFACES and WEBSERVER_INTERFACES. Prevents unauthorized external access. Added docs/SECURITY.md with: - TLS setup instructions (nginx, caddy) - SSH tunnel for development - Firewall rules if external access needed Closes #9. --- docs/SECURITY.md | 99 +++++++++++++++++++++++++++++++++++++++++ server/conf/settings.py | 14 ++++-- 2 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 docs/SECURITY.md diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 0000000..2513780 --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,99 @@ +# Security Configuration + +## Network Binding + +By default, Timmy Academy binds to `127.0.0.1` (localhost only) for security. + +- **Telnet**: `127.0.0.1:4000` +- **Web Client**: `127.0.0.1:4001` + +This prevents unauthorized external access. + +## External Access with TLS + +For external access, use a reverse proxy with TLS: + +### Option 1: Nginx + +```nginx +# /etc/nginx/sites-available/timmy-academy +server { + listen 443 ssl; + server_name academy.timmy.foundation; + + ssl_certificate /etc/letsencrypt/live/academy.timmy.foundation/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/academy.timmy.foundation/privkey.pem; + + # Web client + location / { + proxy_pass http://127.0.0.1:4001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + } + + # Telnet via WebSocket (if needed) + location /telnet { + proxy_pass http://127.0.0.1:4000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} + +# Redirect HTTP to HTTPS +server { + listen 80; + server_name academy.timmy.foundation; + return 301 https://$server$request_uri; +} +``` + +### Option 2: Caddy + +```caddyfile +# /etc/caddy/Caddyfile +academy.timmy.foundation { + reverse_proxy localhost:4001 +} +``` + +Caddy automatically handles TLS certificates. + +## SSH Tunnel (Development) + +For development access without setting up a reverse proxy: + +```bash +# From your local machine +ssh -L 4000:127.0.0.1:4000 -L 4001:127.0.0.1:4001 user@server + +# Then connect to localhost:4000 (telnet) or localhost:4001 (web) +``` + +## Firewall Rules + +If you must bind to `0.0.0.0` (NOT RECOMMENDED), use firewall rules: + +```bash +# UFW (Ubuntu) +sudo -S -p '' ufw allow from 10.0.0.0/8 to any port 4000 +sudo -S -p '' ufw allow from 10.0.0.0/8 to any port 4001 + +# iptables +iptables -A INPUT -p tcp --dport 4000 -s 10.0.0.0/8 -j ACCEPT +iptables -A INPUT -p tcp --dport 4000 -j DROP +``` + +## Why This Matters + +- Telnet transmits passwords in plaintext +- Web client without TLS exposes session cookies +- `0.0.0.0` binds to ALL network interfaces +- Attackers can intercept credentials on shared networks + +## References + +- Issue #9: [academy] Telnet and web client on 0.0.0.0 — no TLS +- Genome #678: Security audit findings diff --git a/server/conf/settings.py b/server/conf/settings.py index ceb2996..fdf1c74 100644 --- a/server/conf/settings.py +++ b/server/conf/settings.py @@ -35,7 +35,7 @@ from evennia.settings_default import * SERVERNAME = "Timmy Academy - The Wizard's Canon" ###################################################################### -# Connection settings for fleet access +# Connection settings ###################################################################### # Telnet port (standard MUD) @@ -44,9 +44,15 @@ TELNET_PORTS = [4000] # Web client port WEBSERVER_PORTS = [(4001, 4005)] -# Allow external connections (0.0.0.0 listens on all interfaces) -TELNET_INTERFACES = ['0.0.0.0'] -WEBSERVER_INTERFACES = ['0.0.0.0'] +# Bind to localhost only for security. +# For external access, use a reverse proxy (nginx/caddy) with TLS. +# See docs/SECURITY.md for TLS setup instructions. +TELNET_INTERFACES = ['127.0.0.1'] +WEBSERVER_INTERFACES = ['127.0.0.1'] + +# To allow external connections (NOT RECOMMENDED without TLS): +# TELNET_INTERFACES = ['0.0.0.0'] +# WEBSERVER_INTERFACES = ['0.0.0.0'] # Web client enabled WEBSERVER_ENABLED = True