Tutorial 2024/06: HAProxy + Let's Encrypt Wildcard Certificates + 100% A+ Rating

Started by TheHellSite, May 31, 2021, 01:06:11 PM

Previous topic - Next topic
Quote from: sorano on June 07, 2021, 02:21:02 PMSince HAProxy is already listening on 0.0.0.0 (all available IPv4 interfaces) I resolve the Split DNS to the internal IP of my DMZ CARP IP (but any internal IPv4 interface will do as long as you allow 80/443).
So this means you are actually also using sort of a virtual IP.  :D
Okay so you say the easier way is like this:
- Firewall rule on WAN allowing 443+80
- SNI_frontend listening on 0.0.0.0:80+443 (Which covers all interfaces)
- SSL_frontend listening on 127.0.0.1:443
- Split DNS pointing to f.e. the LAN IP of OPNsense.

You are right, with that you could skip the virtual IPs.
I would however still prefer to use a virtual IP for the SSL_frontend as I don't want to hijack the localhost for it. I just prefer to keep things seperated.

Quote from: sorano on June 07, 2021, 02:21:02 PMI also have certain domains I don't want reachable from the Internet so I use two map file rules, one for internal domains along with a condition that checks that source is RFC1918.
For this I guess you have to use 0.0.0.0 on the SNI_frontend otherwise you would need another NAT rule forwarding 443-LAN traffic to the virtual IP.

EDIT 20210611:
Implemented @sorano's enhancements  :)
All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite

All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite

This is exactly what I was looking for, have had trouble coming from pfsense to opnsense to setup haproxy/let's encrypt.  I have cloudflare setup to use DNS.

I am using google domain, how do I go about setting up the 1st part (Dynamic DNS), do I need to create 3 custom records:

domain.com (A type)
*.domain.com (A type)
www.domain.com (CNAME)

And also I created separate dynamicDNS for plex.domain.com to use for part 7 (configure Dynamic DNS on opnsense).

Thanks

Quote from: pintu1228 on July 08, 2021, 04:49:36 PM
I am using google domain, how do I go about setting up the 1st part (Dynamic DNS), do I need to create 3 custom records:

domain.com (A type)
*.domain.com (A type)
www.domain.com (CNAME)

It all depends on what you would like to achieve!
You can set your DynDNS to update the IP of "domain.com" and then have a CNAME record in the form of "subdomain.domain.com" pointing to the IP of "domain.com".

However since you might also want to host a website on "domain.com / www.domain.com", you will probably want a subdomain for your domain first!
I myself always create individual 1st-level-subdomains for each physical location that is sitting in a different building / city / country having there own public IP.

f.e. location.domain.tld = earth.thehellsite.com / moon.thehellsite.com / mars.thehellsite.com and so on

And then (as I already explained in my tutorial) a wildcard 2nd-level-subdomain.
Which means that any string in the 2nd-level-subdomain is pointing to my 1st-level-subdomain.

f.e. any_string.location.domain.tld = *.earth.thehellsite.com = abcxyz.earth.thehellsite.com / 123.earth.thehellsite.com


If you do it my way then you only need to set up three things in your Google DNS zone.


  • An "A Record", f.e. location.domain.tld
  • A wildcard "CNAME Record", f.e. *.location.domain.tld
  • A "CAA Record", as explained in the tutorial

Your DynDNS should then be updating the "A Record".




But again, there are many different ways to achieve this.
You just need to find out how you would like to do it.
All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite

Thanks a lot for the write up, I will try this out as soon as I can :)

The only thing that could be added on Part 4.3 is to use an Alias for Port 80 and 443 to only use one Firewall Rule ;)
OPNsense: Intel Core i5-6500, 16 GB RAM, 2x 120GB SSD ZFS-mirror, 4x Intel i350-T4

Quote from: _Alchemist_ on July 14, 2021, 01:45:11 PM
Thanks a lot for the write up, I will try this out as soon as I can :)

The only thing that could be added on Part 4.3 is to use an Alias for Port 80 and 443 to only use one Firewall Rule ;)

Good Idea!
Will add this in my next update.
All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite

Quote from: sorano on June 07, 2021, 02:21:02 PM

I also have certain domains I don't want reachable from the Internet so I use two map file rules, one for internal domains along with a condition that checks that source is RFC1918.

And one for external domains where I also require additional authentication.

Dear @TheHellSite,
thanks for the great tutorial! It works well.

Dear @sorano,

thanks for your input. The hint with map file works well. However, I am unable to create a rule with multiple "OR" conditions for various sub-domains to match and check it with an "AND" condition to test if it is an internal IP. It shall cover your described rule.

Currently I try to create a rule like:
use map file 1
IF
condition 1 "subdomain1" OR condition 2 "subdomain2"
AND condition 3 "local IP (RFC1918)" is matched


How did you solve this with the conditions and rules within OPNsense HAProxy plugin?

thanks in advance for your help and reply.
Saarko

Thanks for the feedback!

I had a chat with @sorano and changed my config a little bit in the meantime.

I will update my post in a few days, hopefully. Very busy with work atm.
This will also solve your problem @saarko.
All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite

I followed this, however, decided against using the LE and now not getting 100% A+. is there something I am missing...

Quote from: lilsense on July 29, 2021, 07:34:44 PM
I followed this, however, decided against using the LE and now not getting 100% A+. is there something I am missing...

Since you didn't use "LE"? (I guess you mean Let's Encrypt certificates) you should probably check out this page.
https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide

So if I would have had to guess it is most likely due to the fact that the key length of your certificate is too short!

If you followed the rest of my guide (OPNsense settings + HAProxy settings) accordingly and didn't miss any configuration steps, you should be getting 100% A+ at SSLLabs!
Again, provided that your certificate has a long enough key length...



I hope you can understand that it is very hard to help you out, since you didn't share any more details about your config, the SSLLabs test results, the certificate you are using ...
All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite

  • Changelog 20210729
    • Added an alias for the HAProxy ports and updated the WAN interface firewall rule with it.
      This leaves us with only one firewall rule instead of two and makes even more sense if one is using additional frontends on different ports.
      Thanks @_Alchemist_ for the suggestion.
    • The tutorial is now using a map file instead of "condition + rule" for service configuration.


@saarko
I didn't manage to finish part 7 "local-access-only subdomains" today.
I will try to do this tomorrow!

In the meantime you can already change your config over to map files.  :)
See part 5, step 7 to step 10. This is the only thing that has changed for using map files.
Map files will also make part 7 very easy for you!
All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite

ggetting this from hap:

[WARNING] 210/114212 (27105) : Proxy '1_HTTPS_Frontend': no-sslv3/no-tlsv1x are ignored for bind '192.168.1.50:443' at [/usr/local/etc/haproxy.conf.staging:71]. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.
Warnings were found.
Configuration file is valid

Quote from: lilsense on July 30, 2021, 05:43:22 PM
ggetting this from hap:

[WARNING] 210/114212 (27105) : Proxy '1_HTTPS_Frontend': no-sslv3/no-tlsv1x are ignored for bind '192.168.1.50:443' at [/usr/local/etc/haproxy.conf.staging:71]. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.
Warnings were found.
Configuration file is valid

Please post a screenshot of your entire HTTPS_frontend config, including advanced.
You can redact your rules.
All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite



# Frontend: 1_HTTPS_Frontend
frontend 1_HTTPS_Frontend
    # WARNING: ciphersuites cannot be used with flavour libressl.
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    bind 10.10.1.50:5555 name 10.10.1.50:555 accept-proxy ssl curves secp384r1  no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ssl-min-ver TLSv1.2 ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/60f9db54XXX3488.certlist
    mode http
    option http-keep-alive
    option forwardfor
    # tuning options
    timeout client 30s

Quote from: lilsense on July 30, 2021, 06:51:11 PM


# Frontend: 1_HTTPS_Frontend
frontend 1_HTTPS_Frontend
    # WARNING: ciphersuites cannot be used with flavour libressl.
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    bind 10.10.1.50:5555 name 10.10.1.50:555 accept-proxy ssl curves secp384r1  no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ssl-min-ver TLSv1.2 ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/60f9db54XXX3488.certlist
    mode http
    option http-keep-alive
    option forwardfor
    # tuning options
    timeout client 30s


I was already assuming what you did (wrong) and your config is confirming it.  ;D

First of all. This is not an error but only a warning which won't make HAProxy refuse to start.
Your setup should still be working if you did everything else correctly.

This warning is appearing because you set "ssl-min-version = TLS1.2" in your HTTPS_frontend config.
Which is pretty much pointless since my config example is already blocking "sslv3 tls1.0 tls1.1" using the "Bind options" in the HTTPS_frontend field. This is why HAProxy is giving you a warning.
You can of course also remove my bind options and only use "min-ssl-version = TLS1.2", this is up to you.
Either way will work and allow only TLS1.3 connections.


Quote from: lilsense on July 30, 2021, 06:51:11 PM
# Frontend: 1_HTTPS_Frontend
frontend 1_HTTPS_Frontend
    # WARNING: ciphersuites cannot be used with flavour libressl.
...

What you should be aware of is that I specifically mentioned that my guide might not work well on LibreSSL due to the fact that not all features of the last HAProxy version is supported by the LibreSSL firmware variant of OPNsense, yet!
All of my posts are submitted with the best of knowledge and belief.


My post was helpful to you?
Feel free to click [applaud] to the left underneath my profile.
Additionally you can consider donating: https://www.buymeacoffee.com/thehellsite