How to Configure Squid as a Secure HTTPS Forward Proxy for Heroku Applications with Dynamic IPs


4 views

When integrating Heroku applications with services behind firewalls requiring static IP whitelisting, we face a fundamental infrastructure mismatch. Heroku's dynamic IP architecture directly conflicts with traditional firewall rules that demand fixed source addresses.

The solution requires a three-tier architecture:

[Heroku Dynos] → [Squid HTTPS Proxy (static IP)] → [Destination Service]

The proxy must enforce:

  • HTTPS encryption for all proxy connections
  • Digest authentication for client verification
  • Strict access controls
  • No caching of sensitive data

Here's the optimized squid.conf for secure forwarding:

# Base security
acl manager proto cache_object
acl localhost src 127.0.0.1/32 ::1

# SSL configuration
https_port 3129 cert=/etc/squid/ssl/fullchain.pem key=/etc/squid/ssl/privkey.pem \
  cipher=HIGH:!aNULL:!MD5:!RC4:!3DES options=NO_SSLv2,NO_SSLv3,SINGLE_DH_USE

# Authentication
auth_param digest program /usr/lib64/squid/digest_pw_auth -c /etc/squid/squid_passwd
auth_param digest children 20 startup=0 idle=1
auth_param digest realm "Secure Proxy Gateway"
auth_param digest nonce_garbage_interval 5 minutes

acl authenticated proxy_auth REQUIRED
http_access allow authenticated
http_access deny all

# Security headers
request_header_add X-Forwarded-Proto https
request_header_add Front-End-Https On

The original error SSL23_GET_CLIENT_HELLO:http request indicates protocol mismatch. Modern solutions require:

# Test with openssl first:
openssl s_client -connect proxy.example.com:3129 -showcerts

# Proper curl syntax:
curl --proxy https://proxy.example.com:3129 \
  --proxy-cacert /path/to/ca-bundle.crt \
  --proxy-user user:pass \
  https://target.service.com/api
  • Generate certificates with proper SAN entries
  • Implement certificate rotation
  • Monitor connection attempts
  • Set up fail2ban for brute force protection

For high-throughput scenarios:

# Increase file descriptors
ulimit -n 65535

# Worker tuning
workers 4
max_filedescriptors 8192

# Keepalive settings
client_persistent_connections on
server_persistent_connections on

When integrating Heroku services with firewall-protected external APIs that require static IP whitelisting, we face a fundamental architectural challenge. Heroku's dynamic routing means our application's outbound requests originate from unpredictable IP addresses, while the target service only accepts connections from pre-approved static IPs.

The authentication flow needs careful consideration:

# Digest authentication configuration (extract from squid.conf)
auth_param digest program /usr/lib64/squid/digest_pw_auth -c /etc/squid/squid_passwd
auth_param digest children 20 startup=0 idle=1
auth_param digest realm squid
acl authenticated proxy_auth REQUIRED
http_access allow authenticated

The critical HTTPS proxy configuration requires proper certificate handling:

# Minimum working HTTPS proxy configuration
https_port 3129 cert=/etc/squid/ssl/fullchain.pem key=/etc/squid/ssl/privkey.pem

# Certificate preparation example:
openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \
  -keyout /etc/squid/ssl/privkey.pem \
  -out /etc/squid/ssl/fullchain.pem \
  -subj "/CN=proxy.yourdomain.com"

The error SSL23_GET_CLIENT_HELLO:http request indicates protocol mismatch. Modern Squid versions require explicit protocol specification:

# Updated https_port configuration
https_port 3129 cert=/etc/squid/ssl/cert.pem key=/etc/squid/ssl/key.pem \
  cipher=HIGH:MEDIUM:!SSLv2:!SSLv3 \
  options=NO_SSLv2,NO_SSLv3,SINGLE_DH_USE

Here's a validated configuration that supports HTTPS forwarding:

# Basic ACL definitions
acl SSL_ports port 443
acl Safe_ports port 80
acl CONNECT method CONNECT

# Authentication setup
auth_param digest program /usr/lib64/squid/digest_pw_auth -c /etc/squid/squid_passwd
auth_param digest realm "Squid Proxy"
acl authenticated proxy_auth REQUIRED

# Port configuration
http_port 3128
https_port 3129 cert=/etc/squid/ssl/cert.pem key=/etc/squid/ssl/key.pem \
  cipher=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256 \
  options=NO_TLSv1,NO_TLSv1_1,SINGLE_DH_USE

# Access control
http_access allow authenticated
http_access deny all

# Disable caching for pure forwarding
cache deny all

Validate the proxy with these curl commands:

# Test HTTP proxying
curl -x http://user:pass@proxy:3128 http://example.com

# Test HTTPS proxying (critical for our use case)
curl -x https://user:pass@proxy:3129 --proxy-cacert /path/to/ca.pem \
  https://firewalled-service.com/api

For production workloads, tune these parameters:

# Connection pooling
max_filedescriptors 8192
workers 4

# Timeout adjustments
forward_timeout 120
connect_timeout 30
client_lifetime 1 hour

Essential security measures beyond basic auth:

# Restrict allowed TLS versions
sslproxy_options NO_SSLv2,NO_SSLv3,NO_TLSv1,NO_TLSv1_1

# Enable certificate verification
sslproxy_cert_error allow all
sslproxy_flags DONT_VERIFY_PEER