I believe I’ve worked out most of the kinks just by reading through the docs and learning how the config is supposed to work. Now I’m running into an issue getting HAProxy to bind to the frontend ports. I’m a bit confused as to why.
HAProxy config: https://pastebin.com/RSVqc9By
Journalctl -xe output: https://pastebin.com/g21Q7he9
netstat doesn’t show that I’ve got anything connected or listening on any of the ports I’m using. I also tried changing the backend ports to 8080 or 82 because I thought the frontend and backend might not want to be the same. That didn’t help though.
What have I misunderstood here? Any insight appreciated.
Thanks!
It’s haproxy itself.
Differently to what you may be used to from Apache and nginx, you cannot and must not redefine the same listen/bind directive in different context.
You can only listen to port 80 once and you can only listen to port 443 once (unless those are different IP addresses of course, but I immagine they are the same).
So use a single frontend section for everything, unless you have multiple IP addresses you can listen to (then configure IP:port combination instead of just using the port).
You can use the host header to differentiate between the different backends:
use_backend example.net if { hdr(host) -i example.net }
use_backend example.com if { hdr(host) -i example.com }
use_backend example.org if { hdr(host) -i example.org }
You can specify multiple certificates on the same bind line by either pointing to a directory or specifying the crt
keyword mutliple times.
1 Like
That’s awesome. Thank you. You are correct. I’m funneling everything through one public IP.
Since I’m using a few different certs for different sites, and given your comment, if I wanted to list all certs on one line would my new bind for 443 look like:
frontend catchAll
bind :80
bind :443 ssl crt-list /etc/haproxy/certs/catchAll/pemList alpn h2
where pemList is a file which reads:
/etc/haproxy/certs/blechinger.io/blechinger.io.pem
/etc/haproxy/certs/rachelreagan.com/rachelreagan.com.pem
/etc/haproxy/certs/exponentialnews.net/exponentialnews.net.pem
/etc/haproxy/certs/kylejohnson.io/kylejohnson.io.pem
Is that correct? If so my only outstanding question is how exactly does HAProxy determine which .pem to use?
Thank you again. I sincerely appreciate the quick response and pointed answer. Very helpful.
Yes, your understanding is correct. Haproxy maps SNI value (from the SSL hanshake’s client_hello) to certificate based on the CN and SAN in the certificate. Wildcard certificates are also handled correctly.
This works very well automatically, unless you have overlapping certificates or you want to serve certificates that do not match the client’s SNI value. You can override haproxy’s behavior be using filters (even negative filters), as per the crt-list docs (note that this is documenting the featureset in Haproxy 1.8, older releases will have a more limited functionality and some features may also depend on the openssl release haproxy runs with).
1 Like
Thank you again, lukastribus. Very helpful. I should be able to make the adjustments shortly. I’ll report back on whether or not this solved my issue and post the working config for the edification of future readers.
Alright. HAProxy is starting and routing HTTPS traffic to the appropriate sites! Very exciting.
I’m now experiencing two issues. I’m going to ask for help here for the sake of continuity. Please let me know if this is inappropriate and I’ll open a new thread.
Issue #1: Too many redirects. - I’ve attempted access from multiple locations (internal and external network) and multiple browsers. Consistent results depending on site. https blechingerDOTio (sorry for the broken link - forum rules only allowing me to post two links at a time) is a good example of this problem. Site is inaccessible due to too many redirects.
haproxy.conf: https://pastebin.com/6TYiyUM8
nginx.conf: https://pastebin.com/GgM0ri1G
Issue# 2: HTTPS for working sites isn’t coming up green. Not sure how else to explain it. Qualsys SSL Labs testing comes back good. The only “smoking gun” I see in the report is that HTTP forwarding is in PLAINTEXT. Is this due to the SSL Termination at HAProxy? If so how do I remediate this? https pterodactylDOTblechingerDOTio is a good example of this problem.
Yeah, new users are restricted to a certain number of links for spam protection reasons. I bumped your trust level, you should be fine now.
Issue #1: your backend does not know that the client is actually already using HTTPS (because to nginx it looks like http, given that haproxy does the SSL termination) - so it keeps redirecting to HTTPS. So you need to tell your backend that HTTPS is used. The way to usually do this (for example in wordpress), is to add the X-Forwarded-Proto header (in your frontend, for example):
http-request set-header X-Forwarded-Proto https if { ssl_fc }
If (but only if) your backend application considers this header, it won’t redirect to https anymore if it isn’t justified. Wordpress should understand this. Support in other backend applications may vary. Disabling HTTPS redirect in your application could be another workaround.
Issue 2: this is because a secure HTTPS site either includes insecure HTTP links, or other insecure elements. Use the development console (F12) of Chrome or Firefox to understand this. In this case, the error in the dev console in Chrome is:
Resources - non-secure form
This page includes a form with a non-secure “action” attribute.
Because the form action points to a insecure link (notice the http:// here instead of https://):
<form id="loginForm" action="http://pterodactyl.blechinger.io/auth/login" method="POST">
To solutions (that does not require to hardcode https in your application):
- use relative links from root, like
action="/auth/login"
: but this breaks when your application is installed in something other than /
- use scheme agnostic links, like
action="//pterodactyl.blechinger.io/auth/login"
hope this helps,
lukas
Thanks lukas. This makes sense. I should’ve picked up on the root cause for #2. That’s pretty obvious now that it’s been pointed out. You’ve helped me make a ton of progress today. My only outstanding issue is getting all www. URLs to redirect to non-www URLs.
For instance: www.blechinger.io -> https://blechinger.io
I’ve tired about a dozen examples from around the web and attempted to create my own ACL / redirect rule inside my frontend catchAll:
# Redirect www. URLs to non-www https URLs (Not working yet)
acl does_use_www hdr(host) -m beg www.
http-request redirect code 301 location %[hdr(host)] if does_use_www
but to no avail. What’s the proper way of doing this in HAProxy 1.8?
Below is just my reporting on the issue and how it was solved. HAProxy now seems to be working correctly and all issues I’m currently experiencing are related to nginx configuration issues and issues with site content. I’m only posting again in order to be helpful for others in the future (I hate it when someone says THANKS FOR THE HELP IT WORKS YAAAAY! and disappears without presenting the final product!).
I added
http-request set-header X-Forwarded-Proto https if { ssl_fc }
to my frontend and restarted the haproxy service. Same result as before. I definitely want http to redirect to https (attempting to force HSTS preloading for all sites). I think this might be an nginx issue.
pterodactyl.blechinger.io is a separate webserver entirely from the wordpress multisite. Domains other than the *.blechinger.io domains which are hosted in the wordpress multisite work just fine. It’s only *.blechinger.io domains within the wordpress multisite that are encountering the continuous 301 issue (observed in nginx’s access.log). I’ll narrow this down to the nginx config for the wordpress sites.
If, in the nginx config for the wordpress sites, I change the server name for blechinger.io (for instance) from blechinger.io to https://blechinger.io I no longer get a redirect loop. If I remove the X-Forwarded-Proto header from the frontend config I encounter errors again.
HAProxy is doing its job. Nginx was then redirecting the client to a non-https site. Obviously that’s not what we want. Explicitly calling https solves the issue. Other issues seem to be site-content specific. As stated previously my only serious outstanding issue is getting www. URLs to redirect to non-www URLs.
If you know of a more graceful way of solving this issue I’d love to hear it. Otherwise thank you VERY much for your time and expertise. <3
final configs examples:
haproxy.conf: https://pastebin.com/Vt53SzA1
nginx.conf: https://pastebin.com/G6etYDZS
NOTE: nginx.conf is not literal. For me this file is in /etc/nginx/sites-available/example.io
.
EDITED: changed example of failed acl/redirect attempt