Pfsense HAProxy

From Deathbybandaid Wiki
Revision as of 20:16, 8 December 2021 by Deathbybandaid (talk | contribs) (Created page with " =HAProxy ports 80/443= ==pfsense admin port change== Step one here is to change pfsense admin interface port from 443. pfsense Admin Port Change ==Adjust Firewall Rules== In order for HAProxy to be used, we need to change some firewall rules to pass traffic for 80/443 ===If you previously NATted 80/443=== You will want to disable these NAT rules. File:pfsense-removenat.png ===Adjust WAN rules to allow access=== Add these rules to allow access to HAProxy File...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

HAProxy ports 80/443

pfsense admin port change

Step one here is to change pfsense admin interface port from 443. pfsense Admin Port Change

Adjust Firewall Rules

In order for HAProxy to be used, we need to change some firewall rules to pass traffic for 80/443

If you previously NATted 80/443

You will want to disable these NAT rules.

Adjust WAN rules to allow access

Add these rules to allow access to HAProxy

HAProxy setup

Go to your package manager and download and install HAproxy.

Make sure the above settings are set.

Create Basic HTTP site

Below, we will demonstrate a simple Port 80 access to a dummy webpage. I'd recommend a dummy nginx setup on another device.

Create First Backend

Here, we will create a Backend that goes to a dummy webpage (set this up on a seperate device)

Create Shared HTTP Frontend

There are only a few settings to change here:

Then scroll to the bottom and change the following:

Create a host matching frontend

We will now utilize the shared frontend to match a requested host name and direct that traffic to the backend that we setup.

Test

Assuming you've already directed the A Record for your domain name to you external IP, opening your domain name in a browser should now show your test webpage.

Upgrade Basic HTTP site to HTTPS

Now that we have a basic HTTP site functioning, we will add a certificate to HAProxy and allow HTTPS traffic on port 443.

Obtain Certificate

For this setup I will focus on using Acme Letsencrypt to obtain a certificate. There are other ways to add a cert to your haproxy setup.

See https://docs.netgate.com/pfsense/en/latest/certificates/certificate-management.html

Create Acme cert Backend

MAKE SURE HEALTH CHECKS ARE DISABLED

Create Frontend Rule to use Acme Backend

For ease of copy-paste,

/.well-known/acme-challenge/

Use The Acme package to get a cert

Install and prepare Acme

pfsense acme

Restart HAProxy

Create Shared HTTPS Frontend

Now that we have a working Certificate, we'll add a shared fronend similar to the HTTP one before.

Copy Acme ACL from HTTP to HTTPS

For good measure, we'll copy the acme rule to the shared HTTPS frontend

(The rectangle icon is the copy button)

Create an ACL for the shared HTTP frontend to permanently redirect traffic from 80 to 443

Now we will want all HTTP traffic to use HTTPS on port 443:

Move Domain Matched ACL to HTTP

Go to edit the previously created Frontend for your dummy webserver.

Change the "Primary Frontend" from "Shared-HTTP" to "Shared-HTTPS"

Test

You should now be able to open your domain in a browser to see your dummy webpage with HTTPS.

Frontend ACL Tricks

These ACLs can be applied to both HTTP and HTTPS frontends

Blocks

Block access by IP Address

Using Host-Regex matching with http-request-deny 403:

IPv4

^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$

IPv6

(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))

Block access by Charter Spectrum Address

Using Host-Regex matching with http-request-deny 403:

.spectrum.com

.charter.com

Block access by Hurricane Electric Address

Using Host-Regex matching with http-request-deny 403:

.ipv6.he.net

Set a robots.txt globally

Lua Script

Under the "Files" tab of HAProxy, create a filename "robots" with the type "Lua script" with the following content

 robots = function(applet) 
 local response = "User-agent: *\nDisallow: /"
 applet:add_header("Content-Length", string.len(response)) 
 applet:add_header("Content-Type", "text/plain") 
 applet:set_status(200) 
 applet:start_response() 
 applet:send(response) 
 end 
 
 core.register_service("robots", "http", robots)
 

Frontend ACL

Other

Redirect Naked Domains to www.domain.net

Use a Custom-acl with "Not" checked with a value of:

hdr_reg(host) -i .*\..*\..* :

Then use http-request-redirect

prefix https://www.%[hdr(host)] code 301

Backend ACL Tricks

Rewrite / to /somethingelse/

Use Path-Matches to http-request-redirect

prefix https://%[hdr(host)]/somethingelse/ code 301