diff --git a/docker/ssrf_proxy/README.md b/docker/ssrf_proxy/README.md new file mode 100644 index 0000000000..ad7eb3c8c1 --- /dev/null +++ b/docker/ssrf_proxy/README.md @@ -0,0 +1,114 @@ +# SSRF Proxy Configuration + +This directory contains the Squid proxy configuration used to prevent Server-Side Request Forgery (SSRF) attacks in Dify. + +## Security by Default + +The default configuration (`squid.conf.template`) is **strict by default** to prevent SSRF attacks: + +- **Blocks all private/internal networks** (RFC 1918, loopback, link-local, etc.) +- **Only allows HTTP (80) and HTTPS (443) ports** +- **Denies all requests by default** unless explicitly allowed + +## Customizing the Configuration + +### For Development/Local Environments + +To allow additional domains or relax restrictions for your local environment: + +1. Create a `conf.d` directory in your deployment +2. Copy example configurations from `conf.d.example/` and modify as needed +3. Mount the config files to `/etc/squid/conf.d/` in the container + +### Example: Docker Compose + +```yaml +services: + ssrf-proxy: + volumes: + - ./my-proxy-configs:/etc/squid/conf.d:ro +``` + +### Example: Kubernetes ConfigMap + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: squid-custom-config +data: + 10-allow-marketplace.conf: | + acl allowed_marketplace dstdomain .marketplace.dify.ai + http_access allow allowed_marketplace +--- +apiVersion: apps/v1 +kind: Deployment +spec: + template: + spec: + containers: + - name: ssrf-proxy + volumeMounts: + - name: custom-config + mountPath: /etc/squid/conf.d + volumes: + - name: custom-config + configMap: + name: squid-custom-config +``` + +## Available Example Configurations + +The `conf.d.example/` directory contains example configurations: + +- **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 +- **40-allow-additional-ports.conf.example**: Allow additional ports + +## Security Considerations + +⚠️ **WARNING**: Relaxing these restrictions can expose your system to SSRF attacks! + +- **Never allow access to private networks in production** unless absolutely necessary +- **Carefully review any domains you whitelist** to ensure they cannot be used for SSRF +- **Avoid allowing high port ranges** (1025-65535) as they can bypass security restrictions +- **Monitor proxy logs** for suspicious activity + +## Default Blocked Networks + +The following networks are blocked by default to prevent SSRF: + +- `0.0.0.0/8` - "This" network +- `10.0.0.0/8` - Private network (RFC 1918) +- `127.0.0.0/8` - Loopback +- `169.254.0.0/16` - Link-local (RFC 3927) +- `172.16.0.0/12` - Private network (RFC 1918) +- `192.168.0.0/16` - Private network (RFC 1918) +- `224.0.0.0/4` - Multicast +- `fc00::/7` - IPv6 unique local addresses +- `fe80::/10` - IPv6 link-local +- `::1/128` - IPv6 loopback + +## Troubleshooting + +If your application needs to access a service that's being blocked: + +1. Check the Squid logs to identify what's being blocked +2. Create a custom configuration in `/etc/squid/conf.d/` +3. Only allow the minimum necessary access +4. Test thoroughly to ensure security is maintained + +## File Structure + +``` +docker/ssrf_proxy/ +├── squid.conf.template # Strict default configuration +├── docker-entrypoint.sh # Container entrypoint script +├── conf.d.example/ # Example override configurations +│ ├── 10-allow-marketplace.conf.example +│ ├── 20-allow-internal-services.conf.example +│ ├── 30-allow-external-domains.conf.example +│ └── 40-allow-additional-ports.conf.example +└── README.md # This file +``` \ No newline at end of file diff --git a/docker/ssrf_proxy/conf.d.example/10-allow-marketplace.conf.example b/docker/ssrf_proxy/conf.d.example/10-allow-marketplace.conf.example new file mode 100644 index 0000000000..868a22ce65 --- /dev/null +++ b/docker/ssrf_proxy/conf.d.example/10-allow-marketplace.conf.example @@ -0,0 +1,5 @@ +# Example: Allow access to Dify marketplace +# Copy this file to /etc/squid/conf.d/10-allow-marketplace.conf to enable + +acl allowed_marketplace dstdomain .marketplace.dify.ai +http_access allow allowed_marketplace \ No newline at end of file diff --git a/docker/ssrf_proxy/conf.d.example/20-allow-internal-services.conf.example b/docker/ssrf_proxy/conf.d.example/20-allow-internal-services.conf.example new file mode 100644 index 0000000000..15daab6917 --- /dev/null +++ b/docker/ssrf_proxy/conf.d.example/20-allow-internal-services.conf.example @@ -0,0 +1,15 @@ +# Example: Allow access to internal services (USE WITH CAUTION!) +# Copy this file to /etc/squid/conf.d/20-allow-internal-services.conf to enable +# WARNING: This reduces SSRF protection. Only use if you understand the security implications. + +# Example: Allow specific internal service +# acl internal_api_service dst 10.0.1.100 +# http_access allow internal_api_service + +# Example: Allow Docker network (172.17.0.0/16 is Docker's default bridge network) +# acl docker_network dst 172.17.0.0/16 +# http_access allow docker_network + +# Example: Allow localhost access (DANGEROUS - can bypass SSRF protection) +# acl localhost_dst dst 127.0.0.1 +# http_access allow localhost_dst \ No newline at end of file diff --git a/docker/ssrf_proxy/conf.d.example/30-allow-external-domains.conf.example b/docker/ssrf_proxy/conf.d.example/30-allow-external-domains.conf.example new file mode 100644 index 0000000000..39cfbcf63b --- /dev/null +++ b/docker/ssrf_proxy/conf.d.example/30-allow-external-domains.conf.example @@ -0,0 +1,18 @@ +# Example: Allow access to specific external domains +# Copy this file to /etc/squid/conf.d/30-allow-external-domains.conf to enable + +# Allow specific domains for API integrations +# acl allowed_apis dstdomain .api.openai.com .anthropic.com .googleapis.com +# http_access allow allowed_apis + +# Allow webhook endpoints +# acl webhook_endpoints dstdomain .webhook.site .zapier.com +# http_access allow webhook_endpoints + +# Allow storage services +# acl storage_services dstdomain .s3.amazonaws.com .blob.core.windows.net .storage.googleapis.com +# http_access allow storage_services + +# Allow by specific IP address (use with caution) +# acl trusted_ip dst 203.0.113.10 +# http_access allow trusted_ip \ No newline at end of file diff --git a/docker/ssrf_proxy/conf.d.example/40-allow-additional-ports.conf.example b/docker/ssrf_proxy/conf.d.example/40-allow-additional-ports.conf.example new file mode 100644 index 0000000000..d4a632d5fd --- /dev/null +++ b/docker/ssrf_proxy/conf.d.example/40-allow-additional-ports.conf.example @@ -0,0 +1,17 @@ +# Example: Allow additional ports for specific protocols +# Copy this file to /etc/squid/conf.d/40-allow-additional-ports.conf to enable +# WARNING: Opening additional ports can increase security risks + +# Allow additional safe ports +# acl Safe_ports port 8080 # http-alt +# acl Safe_ports port 8443 # https-alt +# acl Safe_ports port 3000 # common development port +# acl Safe_ports port 5000 # common API port + +# Allow additional SSL ports for CONNECT method +# acl SSL_ports port 8443 # https-alt +# acl SSL_ports port 3443 # custom ssl + +# Allow high ports (1025-65535) - DANGEROUS! Can be used to bypass restrictions +# acl Safe_ports port 1025-65535 +# acl SSL_ports port 1025-65535 \ No newline at end of file diff --git a/docker/ssrf_proxy/squid.conf.template b/docker/ssrf_proxy/squid.conf.template index 1775a1fff9..db55fbc2ab 100644 --- a/docker/ssrf_proxy/squid.conf.template +++ b/docker/ssrf_proxy/squid.conf.template @@ -1,37 +1,56 @@ -acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN) -acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN) -acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN) -acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines -acl localnet src 172.16.0.0/12 # RFC 1918 local private network (LAN) -acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN) -acl localnet src fc00::/7 # RFC 4193 local private network range -acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines +################################## SSRF Protection Configuration ################################## +# This is a strict default configuration to prevent SSRF attacks +# To allow additional domains or relax restrictions, create config files in /etc/squid/conf.d/ + +################################## Security ACLs ################################## +# Define private/local networks that should be BLOCKED by default +acl private_networks dst 0.0.0.0/8 # "This" network +acl private_networks dst 10.0.0.0/8 # RFC 1918 private network +acl private_networks dst 100.64.0.0/10 # RFC 6598 shared address space +acl private_networks dst 127.0.0.0/8 # Loopback +acl private_networks dst 169.254.0.0/16 # RFC 3927 link-local +acl private_networks dst 172.16.0.0/12 # RFC 1918 private network +acl private_networks dst 192.168.0.0/16 # RFC 1918 private network +acl private_networks dst 224.0.0.0/4 # Multicast +acl private_networks dst 240.0.0.0/4 # Reserved for future use +acl private_networks dst 255.255.255.255/32 # Broadcast +acl private_networks dst fc00::/7 # IPv6 unique local addresses +acl private_networks dst fe80::/10 # IPv6 link-local addresses +acl private_networks dst ::1/128 # IPv6 loopback +acl private_networks dst ff00::/8 # IPv6 multicast + +# Define ports acl SSL_ports port 443 -# acl SSL_ports port 1025-65535 # Enable the configuration to resolve this issue: https://github.com/langgenius/dify/issues/12792 -acl Safe_ports port 80 # http -acl Safe_ports port 21 # ftp -acl Safe_ports port 443 # https -acl Safe_ports port 70 # gopher -acl Safe_ports port 210 # wais -acl Safe_ports port 1025-65535 # unregistered ports -acl Safe_ports port 280 # http-mgmt -acl Safe_ports port 488 # gss-http -acl Safe_ports port 591 # filemaker -acl Safe_ports port 777 # multiling http +acl Safe_ports port 80 # http +acl Safe_ports port 443 # https acl CONNECT method CONNECT -acl allowed_domains dstdomain .marketplace.dify.ai -http_access allow allowed_domains + +################################## Strict Default Rules ################################## +# DENY access to all private/local networks - prevents SSRF attacks +http_access deny private_networks + +# DENY non-safe ports http_access deny !Safe_ports + +# DENY CONNECT to non-SSL ports http_access deny CONNECT !SSL_ports + +# Allow manager access from localhost only http_access allow localhost manager http_access deny manager -http_access allow localhost + +# DENY all requests by default +# User overrides in /etc/squid/conf.d/*.conf should be placed here include /etc/squid/conf.d/*.conf + +# Final deny all http_access deny all -################################## Proxy Server ################################ +################################## Proxy Server Configuration ################################## http_port ${HTTP_PORT} coredump_dir ${COREDUMP_DIR} + +# Refresh patterns refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 @@ -41,16 +60,16 @@ refresh_pattern \/InRelease$ 0 0% 0 refresh-ims refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims refresh_pattern . 0 20% 4320 +# Upstream proxy configuration (uncomment and configure if needed) +# cache_peer parent 3128 0 no-query no-digest no-netdb-exchange default -# cache_dir ufs /var/spool/squid 100 16 256 -# upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks -# cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default - -################################## Reverse Proxy To Sandbox ################################ +################################## Reverse Proxy To Sandbox ################################## http_port ${REVERSE_PROXY_PORT} accel vhost cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver -acl src_all src all -http_access allow src_all -# Unless the option's size is increased, an error will occur when uploading more than two files. -client_request_buffer_max_size 100 MB +# 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