Hi,
I used the search before opening this thread and realized that there are several similar threads, but no one with a solution …
First of all, I am a tech enthusiast with a home lab and don’t manage a data center. However, I have a 10g internet connection that wants to be used, run several servers, and like to learn new things.
Almost two years ago I got in touch with L7 forwarding and cloudflare via this youtube video that describes exactly what I am looking for: Use cloudflare wild card certificates with a free KEMP loadbalancer to do L7 forwarding via subdomains and port 443 to different servers on my network.
However, the free KEMP loadbalancer is limited to 20Mbit/s, so I was looking for a free alternative and started playing around with HAproxy, but never really got it to work and at some point gave up and fell back to KEMP. Now I moved countries, upgraded my home lab, have an even faster internet connection and would like to give it another try.
I found a step-by-step tutorial for HAProxy that describes what I want to accomplish: How to add Cloudflare in front of HAProxy
However, the tutorial is for a GUI version of HAProxy and therefore for people who can afford paying big money / companies. I am looking for something similar that describes how to configure something like that with the free (GUI-less) version.
I also found the free HAProxy-wi and Roxy-Wi, whereof the installation instructions of the former one are not working because of missing files and the latter one requires a donation before it can be tested (I am happy to donate, but I don’t want to donate in the first place and then realize afterwards that it also doesn’t work).
There are also tutorials for pfSense/HAProxy, but I don’t have pfSense.
Is anyone aware of a working tutorial to set something like that up?
If anyone has an example configuration that he/she would be willing to share, I also would be grateful!
Hi,
I am really sorry, but I can’t get it to work with your instructions. I might not get how to do the forwarding to subdomains correctly.
I set up the certificate and private key file as described in your description and saved it in domain.com.pem.
To incorporated the forwarding, I modified the service lines … but what I did doesn’t look correct to me …
I have a domain at cloudflare, let’s call it dummy.com. I generated an origin certificate and private key for dummy.com and *.dummy.com as described on your website.
On cloudflare, I set up a CNAME record for nextcloud.dummy.com that is proxied and grafana.dummy.com that is also proxied.
I set the SSL/TLS encryption mode on Cloudflare to Full strict.
Then I copied your config file and edited the parts for the frontend and backend according to what I thought it might look like.
Then I restarted the service and of course it failed.
According to this tutorial: HAProxy For Load Balancing and Subdomain-Port Redirection — Steemit
I need something like acl sub1 hdr_sub(host) -i nextcloud.dummy.com
and acl sub2 hdr_sub(host) -i grafana.dummy.com
with a bind to port 80 in the frontend and mode http (not https ?!?) in the backend.
… but I don’t want to forward stuff on port 80, but from 443 to 443, just based on which subdomain was used. I guess this must be a super simple case and I apologize for not getting it, but I don’t get it.
That’s what I have so far:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd liste>
user haproxy
group haproxy
daemon
maxconn 40000
ulimit-n 81000
crt-base /etc/haproxy/certificates/
defaults
mode http
option httplog
option dontlognull
option forwardfor
log global
timeout client 30s
timeout server 30s
timeout connect 5s
# HTTP Frontend
frontend fe_http
bind *:80
http-request redirect scheme https code 301
# HTTPS Frontend
frontend fe_https
bind *:443 ssl crt domain.com.pem
acl service1 ssl_fc_sni nextcloud.dummy.com
use_backend be_service1 if service1
acl service2 ssl_fc_sni grafana.dummy.com
use_backend be_service2 if service2
# This redirects to a failure page
default_backend be_no-match
backend be_no-match
http-request deny deny_status 403
backend be_service1
#option forwardfor
server service1 172.16.52.10:443 check
backend be_service2
#option forwardfor
server service2 172.16.52.31:3000 check
The port 80 config is simply telling the client to use 443 instead.
If your backend has TLS enabled, you might need to have ssl verify none on the server backend after check. This is required if you are using a self-signed certificate and HAProxy does not have the root certificate installed. It is perfectly safe to do this because HAProxy is doing TLS offloading.
Oh yeah!!!
It’s working!!
I wasn’t able to rebuild your fancy setup, although I’d like to!
I installed crowdsec, but things with the bouncer didn’t work. However, it would be nice to see the original IPs of the visitor. I set my firewall up do allow access only from certain countries and having them hidden behind cloudflare is not ideal.
The frontend for internal IPs is also neat! But I wasn’t sure what to do with the wildcard certificate. Up to my knowledge it is not possible to download it from cloudflare. I will look into generating my own with the certbot cloudflare plugin/API (Welcome to certbot-dns-cloudflare’s documentation! — certbot-dns-cloudflare 0 documentation, other DNS services here: User Guide — Certbot 2.4.0 documentation)
Thanks for your help! Highly appreciated!
For everyone else looking for a simple working example, see below (it is simplexion’s config, just skimmed + the ssl verify none in the end):
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
user haproxy
group haproxy
daemon
maxconn 40000
ulimit-n 81000
crt-base /etc/haproxy/certificates/
## Crowdsec bouncer
#lua-prepend-path /usr/lib/crowdsec/lua/haproxy/?.lua
#lua-load /usr/lib/crowdsec/lua/haproxy/crowdsec.lua
#setenv CROWDSEC_CONFIG /etc/crowdsec/bouncers/crowdsec-haproxy-bouncer.conf
defaults
mode http
option httplog
option forwardfor
option dontlognull
log global
timeout client 30s
timeout server 30s
timeout connect 5s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
#listen stats
# bind *:8404
# stats enable
# stats hide-version
# stats realm Haproxy\ Statistics
# stats uri /haproxy_stats
# stats auth HAProxy:Password
# Frontend to redirect HTTP to HTTPS with code 301
frontend http-redirect
bind *:80
http-request redirect scheme https code 301
# Frontend for redirecting traffic to the required frontend
frontend https-redirect
bind *:443
mode tcp
option tcplog
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
#acl internal src 192.168.210.0/24
#IPs from here: https://www.cloudflare.com/ips-v4
acl cloudflare src -f /etc/haproxy/CF_ips.lst
use_backend cloudflare if cloudflare
#use_backend internal if internal
# Frontend for external users that a connecting through Cloudflare
frontend cloudflare
bind *:7000 accept-proxy ssl crt domain.com.pem
# SNI ACLs
acl nextcloud hdr(host) -i nextcloud.domain.com
acl grafana hdr(host) -i grafana.domain.com
# Send to backend based on SNI ACL
use_backend nextcloud if nextcloud
use_backend grafana if grafana
# This redirects to a failure page
default_backend no-match
# Redirect to frontend based on internal or external connections
backend cloudflare
mode tcp
server loopback-for-tls 127.0.0.1:7000 send-proxy-v2
# Normal Backends
backend no-match
http-request deny deny_status 403
backend nextcloud
server nextcloud 172.16.3.2:443 check ssl verify none
backend grafana
server grafana 172.168.3.3:443 check ssl verify none