chore: strengthen SSRF proxy default configuration

- Block all private/internal networks by default to prevent SSRF attacks
- Restrict allowed ports to only HTTP (80) and HTTPS (443)
- Remove default domain allowlists (e.g., marketplace.dify.ai)
- Implement deny-all-by-default policy with explicit whitelisting
- Add example configuration files for common customization scenarios
- Provide comprehensive documentation for security configuration

Fixes #24392
This commit is contained in:
-LAN- 2025-08-24 03:41:45 +08:00
parent 2e6e414a9e
commit 23c97ec7f7
No known key found for this signature in database
GPG Key ID: 6BA0D108DED011FF
6 changed files with 220 additions and 32 deletions

114
docker/ssrf_proxy/README.md Normal file
View File

@ -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
```

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 <upstream_proxy_ip> 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