I'm trying to configure HAProxy to be used for both HTTPS traffic and OpenVPN connections through port 443. The configuration is straightforward (first-level domain replaced by example.com
for the sake of anonymousity):
frontend www_ssl
mode tcp
bind *:443
acl host_vpn hdr(host) -i vpn.example.com
use_backend vpn_backend if host_vpn
default_backend nginx_pool_ssl
backend nginx_pool_ssl
balance first
mode tcp
server web1 192.168.1.2:443 send-proxy check
server web2 192.168.1.3:443 send-proxy check
backend vpn_backend
mode tcp
server vpn1 192.168.1.4:443
When establishing an OpenVPN connection, it fails with the following message:
WARNING: Bad encapsulated packet length from peer (18516), which must be > 0 and <= 1547 -- please ensure that --tun-mtu or --link-mtu is equal on both peers -- this condition could also indicate a possible active attack on the TCP link -- [Attempting restart...]
What happens is that instead of redirecting the traffic to 192.168.1.4, HAProxy goes to 192.168.1.2 which attempts to treat it as an HTTPS request. The same goes when I open vpn.example.com
in the browser: I just get the website served by 192.168.1.2.
If I replace the above configuration by this:
frontend www_ssl
mode tcp
bind *:443
default_backend host_vpn
backend vpn_backend
mode tcp
server vpn1 192.168.1.4:443
then OpenVPN connection is established correctly and the browser is unable to show anything, meaning that the issue comes from HAProxy configuration.
What is happening here? Is there a error in the original configuration?
Found it.
The obvious problem is that the ACL directive is relying on HTTP headers: given that HAProxy won't be able to extract the headers from HTTPS traffic and OpenVPN doesn't have them, the ACL has no effect, and the use of
default_backend
is expected here.My first thought was to use
req.ssl_sni
instead ofhdr(host)
. This would make it possible—I thought—to detect whether it's HTTPS traffic or not:While it worked well for browser requests, I experienced a problem where a part of the traffic from
svn
to WebDAV through HTTPS was redirected to OpenVPN server. I'm not sure what is happening here, and without tracing the network traffic, it was difficult to find the issue, nor which requests exactly were failing and why.I ended up moving OpenVPN to port 80. By using the predefined
HTTP
ACL, the configuration is now looking like that: