In this guide, we’ll configure HAProxy on OPNsense to support TLS passthrough with SNI-based routing. This allows secure HTTPS traffic to be routed based on domain names without decrypting the traffic on the firewall.
- Install HAProxy Plugin
- Go to System > Firmware > Plugins
- Search for:
os-haproxy
- Click Install
- After installation, go to Services > HAProxy (you may need to reboot)
- Enable HAProxy
- Go to Services > HAProxy > Settings > Service
- Check Enable HAProxy
- Click Apply
- Add Real Servers
- Go to Services > HAProxy > Settings > Real Servers
- Click Add
Name | app | k8s-controller |
Type | static | static |
FQDN or IP | 10.0.128.5 | 10.0.128.240 |
Port | 443 | 443 |
SSL | Unchecked | Unchecked |
Verify SSL Certificate | Unchecked | Unchecked |
- Click Save
- Click Apply
- Create Backend Pools
- Go to Services > HAProxy > Settings > Virtual Services > Backend Pools
- Click Add
Name | app | k8s-controller |
Mode | TCP (Layer 4) | TCP (Layer 4) |
Servers | app | k8s-controller |
Enable Health Checking | Unchecked | Unchecked |
- Click Save
- Click Apply
- Create TCP Frontend with SNI Routing
- Go to Services > HAProxy > Settings > Virtual Services > Public Services
- Click Add
Name: frontend-https
Listen Address: 0.0.0.0:443
Type: SSL/HTTPS(TCP mode)
Default Backend Pool: None - Option pass-through
Enable advanced mode and scroll down to Advanced settings > Option pass-through
Paste this:
# Required to extract SNI from TLS handshake in TCP mode
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
# ACL: is_app_tls
acl is_app_tls req.ssl_sni -i maksonlee.com
acl is_app_tls req.ssl_sni -i www.maksonlee.com
acl is_app_tls req.ssl_sni -i zabbix.maksonlee.com
acl is_app_tls req.ssl_sni -i jenkins-test.maksonlee.com
# ACL: is_k8s_tls
acl is_k8s_tls req.ssl_sni -i whoami.maksonlee.com
# ACTION: app
use_backend app if is_app_tls
# ACTION: k8s
use_backend k8s-controller if is_k8s_tls
This enables SNI-based routing in the correct order, which the UI doesn’t handle automatically.
- Click Save
Click Apply
Done, now it’s time to test.
HTTP Pass-through (Optional)
If you want to forward port 80 traffic as plain HTTP (not TLS passthrough), here is the configuration:
# Frontend: frontend-http ()
frontend frontend-http
bind 0.0.0.0:80 name 0.0.0.0:80
mode http
option http-keep-alive
# logging options
# WARNING: pass through options below this line
# ACL: is_app_http
acl is_app_http hdr(host) -i maksonlee.com
acl is_app_http hdr(host) -i www.maksonlee.com
acl is_app_http hdr(host) -i zabbix.maksonlee.com
acl is_app_http hdr(host) -i jenkins-test.maksonlee.com
# ACL: is_k8s_http
acl is_k8s_http hdr(host) -i whoami.maksonlee.com
# ACTION: app
use_backend app-http if is_app_http
# ACTION: k8s
use_backend k8s-controller-http if is_k8s_http
# Backend: app-http ()
backend app-http
# health checking is DISABLED
mode http
balance source
# stickiness
stick-table type ip size 50k expire 30m
stick on src
http-reuse safe
server app 10.0.128.5
# Backend: k8s-controller-http ()
backend k8s-controller-http
# health checking is DISABLED
mode http
balance source
# stickiness
stick-table type ip size 50k expire 30m
stick on src
http-reuse safe
server k8s-controller 10.0.128.240