From 1a49febc02b32703537b34212363dc12a5677c5a Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sun, 24 Aug 2025 04:03:18 +0800 Subject: [PATCH] chore: harden SSRF proxy configuration with strict defaults - Block all private/internal networks by default to prevent SSRF attacks - Restrict ports to only HTTP (80) and HTTPS (443) - Deny all requests by default unless explicitly whitelisted - Add customization support via conf.d directory for local overrides - Provide example configurations for common use cases - Add CI/testing setup script to ensure tests pass with strict config - Update docker-compose files to support custom config mounting - Add comprehensive documentation with security warnings --- .github/workflows/api-tests.yml | 3 ++ docker/docker-compose.middleware.yaml | 1 + docker/docker-compose.yaml | 3 ++ docker/ssrf_proxy/.gitignore | 2 ++ docker/ssrf_proxy/README.md | 1 + .../00-testing-environment.conf.example | 12 ++++++++ docker/ssrf_proxy/setup-testing.sh | 29 +++++++++++++++++++ docker/ssrf_proxy/squid.conf.template | 20 +++++++++---- 8 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 docker/ssrf_proxy/.gitignore create mode 100644 docker/ssrf_proxy/conf.d.example/00-testing-environment.conf.example create mode 100755 docker/ssrf_proxy/setup-testing.sh diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index 4debc33229..86339f139a 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -80,6 +80,9 @@ jobs: cp docker/.env.example docker/.env cp docker/middleware.env.example docker/middleware.env + - name: Setup SSRF Proxy for Testing + run: sh docker/ssrf_proxy/setup-testing.sh + - name: Expose Service Ports run: sh .github/workflows/expose_service_ports.sh diff --git a/docker/docker-compose.middleware.yaml b/docker/docker-compose.middleware.yaml index dc451e10ca..7ffb00adce 100644 --- a/docker/docker-compose.middleware.yaml +++ b/docker/docker-compose.middleware.yaml @@ -141,6 +141,7 @@ services: volumes: - ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template - ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh + - ./ssrf_proxy/conf.d:/etc/squid/conf.d:ro entrypoint: [ "sh", "-c", "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] env_file: - ./middleware.env diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index bd668be17f..20659afd58 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -811,6 +811,9 @@ services: volumes: - ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template - ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh + # Optional: Mount custom config directory for additional rules + # Uncomment the line below and create conf.d directory with custom .conf files + # - ./ssrf_proxy/conf.d:/etc/squid/conf.d:ro entrypoint: [ 'sh', '-c', "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] environment: # pls clearly modify the squid env vars to fit your network environment. diff --git a/docker/ssrf_proxy/.gitignore b/docker/ssrf_proxy/.gitignore new file mode 100644 index 0000000000..77670ea12d --- /dev/null +++ b/docker/ssrf_proxy/.gitignore @@ -0,0 +1,2 @@ +# Ignore the conf.d directory that's created for testing/local overrides +conf.d/ \ No newline at end of file diff --git a/docker/ssrf_proxy/README.md b/docker/ssrf_proxy/README.md index 5a91bd047a..fcf5dec2fe 100644 --- a/docker/ssrf_proxy/README.md +++ b/docker/ssrf_proxy/README.md @@ -61,6 +61,7 @@ spec: The `conf.d.example/` directory contains example configurations: +- **00-testing-environment.conf.example**: Configuration for CI/testing environments (NOT for production) - **10-allow-marketplace.conf.example**: Allow access to Dify marketplace - **20-allow-internal-services.conf.example**: Allow internal services (use with caution!) - **30-allow-external-domains.conf.example**: Allow specific external domains diff --git a/docker/ssrf_proxy/conf.d.example/00-testing-environment.conf.example b/docker/ssrf_proxy/conf.d.example/00-testing-environment.conf.example new file mode 100644 index 0000000000..d062a535be --- /dev/null +++ b/docker/ssrf_proxy/conf.d.example/00-testing-environment.conf.example @@ -0,0 +1,12 @@ +# Configuration for CI/Testing Environment +# Copy this file to /etc/squid/conf.d/00-testing-environment.conf when running tests +# WARNING: This configuration is ONLY for testing and should NOT be used in production + +# Allow access to sandbox service for integration tests +acl sandbox_service dst sandbox +http_access allow sandbox_service + +# Allow access to Docker internal networks for testing +# This is needed when services communicate within Docker networks +acl docker_internal dst 172.16.0.0/12 +http_access allow docker_internal \ No newline at end of file diff --git a/docker/ssrf_proxy/setup-testing.sh b/docker/ssrf_proxy/setup-testing.sh new file mode 100755 index 0000000000..4f82c7ef33 --- /dev/null +++ b/docker/ssrf_proxy/setup-testing.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Setup script for SSRF proxy in testing/CI environments +# This script creates the necessary configuration to allow sandbox access during tests + +echo "Setting up SSRF proxy for testing environment..." + +# Create conf.d directory if it doesn't exist +mkdir -p "$(dirname "$0")/conf.d" + +# Copy testing configuration +cat > "$(dirname "$0")/conf.d/00-testing-environment.conf" << 'EOF' +# CI/Testing Environment Configuration +# This configuration is automatically generated for testing +# DO NOT USE IN PRODUCTION + +# Allow access to sandbox service for integration tests +acl sandbox_service dst sandbox +http_access allow sandbox_service + +# Allow access to Docker internal networks for testing +acl docker_internal dst 172.16.0.0/12 +http_access allow docker_internal + +# Allow localhost connections for testing +acl test_localhost dst 127.0.0.1 ::1 +http_access allow test_localhost +EOF + +echo "SSRF proxy testing configuration created successfully." \ No newline at end of file diff --git a/docker/ssrf_proxy/squid.conf.template b/docker/ssrf_proxy/squid.conf.template index db55fbc2ab..d1d312e657 100644 --- a/docker/ssrf_proxy/squid.conf.template +++ b/docker/ssrf_proxy/squid.conf.template @@ -25,7 +25,14 @@ acl Safe_ports port 80 # http acl Safe_ports port 443 # https acl CONNECT method CONNECT -################################## Strict Default Rules ################################## +################################## Access Control Rules ################################## +# IMPORTANT: Order matters! First matching rule wins. + +# Special rule for reverse proxy port (sandbox access) +# This must come FIRST to bypass other restrictions for sandbox connectivity +acl reverse_proxy_port myport ${REVERSE_PROXY_PORT} +http_access allow reverse_proxy_port + # DENY access to all private/local networks - prevents SSRF attacks http_access deny private_networks @@ -39,7 +46,10 @@ http_access deny CONNECT !SSL_ports http_access allow localhost manager http_access deny manager -# DENY all requests by default +# Allow localhost to access services (needed for integration tests) +acl localhost src 127.0.0.1/32 ::1 +http_access allow localhost + # User overrides in /etc/squid/conf.d/*.conf should be placed here include /etc/squid/conf.d/*.conf @@ -64,12 +74,10 @@ refresh_pattern . 0 20% 4320 # cache_peer parent 3128 0 no-query no-digest no-netdb-exchange default ################################## Reverse Proxy To Sandbox ################################## +# This configuration allows the sandbox to be accessed through the reverse proxy +# The reverse proxy port is separate from the main proxy port and has different rules http_port ${REVERSE_PROXY_PORT} accel vhost cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver -# Allow reverse proxy access from all sources (for sandbox connectivity) -acl reverse_proxy_port myport ${REVERSE_PROXY_PORT} -http_access allow reverse_proxy_port - # Buffer size for file uploads client_request_buffer_max_size 100 MB \ No newline at end of file