From ce4fced3800178c77adc0a28688c9da0a2b31c91 Mon Sep 17 00:00:00 2001 From: glenneth Date: Mon, 3 Nov 2025 19:47:53 +0300 Subject: [PATCH] security: Fix Docker port bindings and externalize all passwords MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITICAL SECURITY FIXES: - Bind all Docker services to localhost only (127.0.0.1) - Prevents external access to Liquidsoap telnet (port 1234) - Prevents direct Icecast access without HAproxy (port 8000) - Secures PostgreSQL port (5432) DOCKER CHANGES (docker-compose.yml): - Icecast: 127.0.0.1:8000:8000 (was 8000:8000) - Liquidsoap: 127.0.0.1:1234:1234 (was 1234:1234) - PostgreSQL: 127.0.0.1:5432:5432 (was 5432:5432) - All passwords now use environment variables CONFIG TEMPLATE: - Added ICECAST_SOURCE_PASSWORD - Added ICECAST_RELAY_PASSWORD - Documented all Docker password variables Addresses TODO items from b612.asteroid.radio deployment: - Problem 1: Liquidsoap telnet exposed ✅ FIXED - Problem 2: Icecast binding to 0.0.0.0 ✅ FIXED This prevents the security issues that forced Fade to shut down the production server. Services are now only accessible via HAproxy on the host machine. Ref: TODO.org lines 25-27 --- SECURITY-CONFIG-CHANGES.org | 37 +++++++++++++++++++++++++++++++++---- config.template.env | 5 +++++ docker/docker-compose.yml | 18 +++++++++--------- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/SECURITY-CONFIG-CHANGES.org b/SECURITY-CONFIG-CHANGES.org index 848d5cb..0e53f69 100644 --- a/SECURITY-CONFIG-CHANGES.org +++ b/SECURITY-CONFIG-CHANGES.org @@ -71,23 +71,52 @@ Eliminated hardcoded Icecast admin password from codebase. - ~*supported-formats*~ → ~(config-supported-formats *config*)~ - ~*stream-base-url*~ → ~(config-stream-base-url *config*)~ +** Docker Security Fixes (~docker/docker-compose.yml~) - CRITICAL + +*** Port Bindings Secured + +All services now bind to localhost only (127.0.0.1) instead of 0.0.0.0: + +- *Icecast*: ~127.0.0.1:8000:8000~ - Use HAproxy to expose publicly +- *Liquidsoap telnet*: ~127.0.0.1:1234:1234~ - Never expose to internet +- *PostgreSQL*: ~127.0.0.1:5432:5432~ - Database access from host only + +This prevents external access to: +- Liquidsoap telnet management interface (Problem 1) +- Direct Icecast access without HAproxy (Problem 2) +- PostgreSQL database port + +*** Passwords Externalized + +All Docker container passwords now use environment variables: + +#+BEGIN_SRC yaml +environment: + - ICECAST_SOURCE_PASSWORD=${ICECAST_SOURCE_PASSWORD:-default} + - ICECAST_ADMIN_PASSWORD=${ICECAST_ADMIN_PASSWORD:-default} + - ICECAST_RELAY_PASSWORD=${ICECAST_RELAY_PASSWORD:-default} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-default} +#+END_SRC + * TODO Items Addressed ** DONE Problem 4: Templates no longer advertise default admin password ** DONE Server runtime configuration: All configuration parameterized and loaded from environment +** DONE Problem 1: Liquidsoap telnet binding secured (localhost only) +** DONE Problem 2: Icecast external binding secured (localhost only) ** TODO Problem 3: Database backend selection implemented (PostgreSQL support ready, migration needed) * Production Deployment Issues (From b612.asteroid.radio Test) ** Critical Security (Must fix before public launch) -- [ ] *Problem 1*: Fix Liquidsoap telnet binding (currently exposed on external interface) +- [X] *Problem 1*: Fix Liquidsoap telnet binding ✅ FIXED - Issue: ~telnet asteroid.radio 1234~ works from anywhere - - Fix: Bind to localhost only in Docker config + - Fix: Bind to ~127.0.0.1:1234:1234~ in docker-compose.yml -- [ ] *Problem 2*: Fix Icecast external binding +- [X] *Problem 2*: Fix Icecast external binding ✅ FIXED - Issue: Icecast binding to 0.0.0.0 - - Fix: Bind to localhost only, use HAproxy to proxy + - Fix: Bind to ~127.0.0.1:8000:8000~, use HAproxy to proxy - [ ] *Problem 5*: Set up TLS/Let's Encrypt with HAproxy diff --git a/config.template.env b/config.template.env index 8ed030c..f852f1d 100644 --- a/config.template.env +++ b/config.template.env @@ -30,6 +30,11 @@ ASTEROID_STREAM_URL=http://localhost:8000 ICECAST_ADMIN_USER=admin ICECAST_ADMIN_PASSWORD=CHANGE_THIS_PASSWORD +# Additional Icecast passwords (used by Docker containers) +# These are for Liquidsoap source connection and relay +ICECAST_SOURCE_PASSWORD=CHANGE_THIS_PASSWORD +ICECAST_RELAY_PASSWORD=CHANGE_THIS_PASSWORD + # ============================================================================ # DATABASE CONFIGURATION # ============================================================================ diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 5560750..193103e 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -3,13 +3,13 @@ services: image: infiniteproject/icecast:latest container_name: asteroid-icecast ports: - - "8000:8000" + - "127.0.0.1:8000:8000" # Bind to localhost only - use HAproxy to expose publicly volumes: - ./icecast.xml:/etc/icecast.xml environment: - - ICECAST_SOURCE_PASSWORD=H1tn31EhsyLrfRmo - - ICECAST_ADMIN_PASSWORD=asteroid_admin_2024 - - ICECAST_RELAY_PASSWORD=asteroid_relay_2024 + - ICECAST_SOURCE_PASSWORD=${ICECAST_SOURCE_PASSWORD:-H1tn31EhsyLrfRmo} + - ICECAST_ADMIN_PASSWORD=${ICECAST_ADMIN_PASSWORD:-asteroid_admin_2024} + - ICECAST_RELAY_PASSWORD=${ICECAST_RELAY_PASSWORD:-asteroid_relay_2024} restart: unless-stopped networks: - asteroid-network @@ -20,7 +20,7 @@ services: dockerfile: Dockerfile.liquidsoap container_name: asteroid-liquidsoap ports: - - "1234:1234" + - "127.0.0.1:1234:1234" # Bind telnet to localhost only - SECURITY: Never expose to internet depends_on: - icecast volumes: @@ -35,11 +35,11 @@ services: image: postgres:16-alpine container_name: asteroid-postgres environment: - POSTGRES_DB: asteroid - POSTGRES_USER: asteroid - POSTGRES_PASSWORD: asteroid_db_2025 + POSTGRES_DB: ${POSTGRES_DB:-asteroid} + POSTGRES_USER: ${POSTGRES_USER:-asteroid} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-asteroid_db_2025} ports: - - "5432:5432" + - "127.0.0.1:5432:5432" # Bind to localhost only volumes: - postgres-data:/var/lib/postgresql/data - ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro