Haproxy ssl pass-through config file for backend domains

Hello there

This is my first post and I really wanted to instead to post a question of a problem, I wanted to post a solution to a problem by sharing my haproxy.cfg file so I didn't know where exactly where to post it (just wanted to give back to the community). I've seen this topic popup a lot out there and after trying different methods, I finally got a very nice config file to solve the issue of not being able to redirect ssl traffic to several backend webservers without having to copy the ssl certificates and keys into openwrt and let the backend server handle them individually. These webservers are running in two different physical machines connected directly to a nanopi r4s. I'm open to ear some feedback!

Check your configuration with: haproxy -c -f /etc/haproxy.cfg
If all goes well restart haproxy: /etc/init.d/haproxy restart

Global settings

global
daemon # Run HAProxy in daemon mode
nosplice # Disable using splice for receiving and transmitting data

Default settings

defaults
log global # Log messages to the global log facility
mode http # Set the default mode to HTTP
option httplog # Enable HTTP request/response logging
log 127.0.0.1:514 local0 # Log messages to the local syslog server
log /var/log/haproxy.log local0 # Log messages to a custom log file
timeout client 30s # Set client timeout to 30 seconds
timeout connect 30s # Set connect timeout to 30 seconds
timeout server 30s # Set server timeout to 30 seconds

Frontend for HAProxy statistics

frontend stats
bind *:9000 # Listen on port 9000
mode http # Set mode to HTTP
stats enable # Enable statistics reporting
stats uri /haproxy # Set URI path for accessing statistics
stats realm HAProxy\ Statistics # Set realm for HTTP authentication
stats auth username:password # Set username and password for HTTP authentication

Frontend for HTTP traffic

frontend http_in
mode http # Set mode to HTTP
option httplog # Enable HTTP request/response logging
bind *:80 # Listen for HTTP traffic on port 80
http-request redirect scheme https # Redirect HTTP traffic to HTTPS
option forwardfor # Add X-Forwarded-For header to forwarded requests
# Add enhanced security headers
http-response add-header Strict-Transport-Security max-age=31536000;\ includeSubDomains;\ preload # Add HSTS header
http-response add-header Content-Security-Policy default-src\ 'self' # Add CSP header

Frontend for HTTPS traffic

frontend https_in
mode tcp # Set mode to TCP for handling encrypted traffic
option tcplog # Enable TCP logging
bind *:443 # Listen for HTTPS traffic on port 443
acl tls req.ssl_hello_type 1 # Check for TLS handshake
tcp-request inspect-delay 5s # Delay inspection of traffic by 5 seconds
tcp-request content accept if { req_ssl_hello_type 1 } # Accept traffic after TLS handshake
# Track session data for rate limiting
stick-table type ip size 100k expire 30m # Define session tracking table
tcp-request content track-sc0 src # Track session data based on source IP
# Use backend based on SNI
use_backend %[req_ssl_sni,lower,word(1,:)]_tls # Select backend based on SNI

Backend servers for HTTPS traffic

backend example1.com_tls
mode tcp # Set mode to TCP
server example1.com 192.168.1.101:443 check # Define backend server and its IP address

backend example2.com_tls
mode tcp # Set mode to TCP
server example2.com 192.168.1.102:443 check # Define backend server and its IP address

backend example3.com_tls
mode tcp # Set mode to TCP
server example3.com 192.168.1.103:443 check # Define backend server and its IP address

backend example4.com_tls
mode tcp # Set mode to TCP
server example4.com 192.168.1.104:443 check # Define backend server and its IP address

2 Likes

Thanks for this timely post as I'm setting up HAProxy for a reverse proxy.

I noticed you use SNI for identification instead of the recommended ACL in the docs... what was the reasoning for this?

Edit: I tried and it seems SNI is the only way to id which backend to use for https.

I had configured my http reverse proxy servers but was stumped on my https servers (I'm not redirecting, I have both http and https) Your post helped a lot - thank you!

The acl tls req.ssl_hello_type 1 creates an ACL (Access Control List) named tls that checks for the presence of a TLS handshake (req.ssl_hello_type 1 ) and the use_backend %[req_ssl_sni,lower,word(1,:)]_tls : Selects the backend based on the server name Indication (SNI) provided by the client during the TLS handshake. This allows HAProxy to route traffic to the appropriate backend server based on the hostname requested by the client. So in short, when a request comes to reach example.com haproxy first makes sure that is a valid https request then "reads" the domain name (example.com) and then redirects to the right local ip address. I though this was a simpler approach than configuring haproxy with specific ACLs and managing all the certificates for my servers. Also I believe this approach reduces the load in openwrt because it is not processing much info.. just passing along the packages to another device to handle them and ensuring that no decryption is done until the package gets to the final destination. Cheers!

Good approach, thank you!

You should "sandwich" your config between two rows of backtick characters ` (which themselves will be invisible in the preview) looking in something like this in the editor:
```
Your Pasted Text as preformatted text with fixed width font
1
1111 (note with fixed-width fonts the numbers are right-aligned)
```
but looking like this in the rendered forum:

Your Pasted Text as preformatted text with fixed width font
   1
1111 (note with fixed-width fonts the numbers are right-aligned)
1 Like

I can't find an option to edit my initial post so here it goes preformatted.

# Global settings
global
daemon # Run HAProxy in daemon mode
nosplice # Disable using splice for receiving and transmitting data

# Default settings
defaults
log global # Log messages to the global log facility
mode http # Set the default mode to HTTP
option httplog # Enable HTTP request/response logging
log 127.0.0.1:514 local0 # Log messages to the local syslog server
log /var/log/haproxy.log local0 # Log messages to a custom log file
timeout client 30s # Set client timeout to 30 seconds
timeout connect 30s # Set connect timeout to 30 seconds
timeout server 30s # Set server timeout to 30 seconds

# Frontend for HAProxy statistics
frontend stats
bind *:9000 # Listen on port 9000
mode http # Set mode to HTTP
stats enable # Enable statistics reporting
stats uri /haproxy # Set URI path for accessing statistics
stats realm HAProxy\ Statistics # Set realm for HTTP authentication
stats auth username:password # Set username and password for HTTP authentication

# Frontend for HTTP traffic
frontend http_in
mode http # Set mode to HTTP
option httplog # Enable HTTP request/response logging
bind *:80 # Listen for HTTP traffic on port 80
http-request redirect scheme https # Redirect HTTP traffic to HTTPS
option forwardfor # Add X-Forwarded-For header to forwarded requests
# Add enhanced security headers
http-response add-header Strict-Transport-Security max-age=31536000;\ includeSubDomains;\ preload # Add HSTS header
http-response add-header Content-Security-Policy default-src\ 'self' # Add CSP header

# Frontend for HTTPS traffic
frontend https_in
mode tcp # Set mode to TCP for handling encrypted traffic
option tcplog # Enable TCP logging
bind *:443 # Listen for HTTPS traffic on port 443
acl tls req.ssl_hello_type 1 # Check for TLS handshake
tcp-request inspect-delay 5s # Delay inspection of traffic by 5 seconds
tcp-request content accept if { req_ssl_hello_type 1 } # Accept traffic after TLS handshake # Track session data for rate limiting
stick-table type ip size 100k expire 30m # Define session tracking table
tcp-request content track-sc0 src # Track session data based on source IP # Use backend based on SNI
use_backend %[req_ssl_sni,lower,word(1,:)]_tls # Select backend based on SNI

# Backend servers for HTTPS traffic
backend example1.com_tls
mode tcp # Set mode to TCP
server example1.com 192.168.1.101:443 check # Define backend server and its IP address

backend example2.com_tls
mode tcp # Set mode to TCP
server example2.com 192.168.1.102:443 check # Define backend server and its IP address

backend example3.com_tls
mode tcp # Set mode to TCP
server example3.com 192.168.1.103:443 check # Define backend server and its IP address

backend example4.com_tls
mode tcp # Set mode to TCP
server example4.com 192.168.1.104:443 check # Define backend server and its IP address