Open schklom opened 1 year ago
Hi, Checkout that module for HAProxy which allow you to manage authentication with ldap or OIDC: https://github.com/criteo/haproxy-spoe-auth/blob/master/README.md
then you’ll have just to setup the target provider accordingly.
Not a bad idea, but it looks like this requires to run an extra service on top of HAProxy and Authentik.
Authelia simply requires to add a few Lua scripts to HAProxy, which HAProxy handles natively, and it works with OIDC pretty well.
I use HAProxy directly on PfSense, with Authelia (Authentik when I switch) on a Raspberry Pi, and would prefer to avoid involving another service.
Nothing in addition within Authentik, only setting up the proper Provider (OIDC or LDAP).
otherwise, if you want to use OIDC with HAProxy, look at that guide for keycloak. https://mackdanz.net/Add-OIDC-single-sign-on-to-any-website-with-HAProxy-and-Keycloak Easy to adapt for Authentik by following the setup doc here regarding to OIDC settings : https://goauthentik.io/docs/providers/oauth2/
note: could be even simpler with that lua script https://github.com/haproxytech/haproxy-lua-oauth
Nothing in addition within Authentik, only setting up the proper Provider (OIDC or LDAP).
But it is an extra service to run with Docker. I am looking for Authentik to do like it does with other reverse-proxies: by indicating how to let HAProxy delegate authentication to Authentik.
In order to do Forward-Auth with Traefik and Authentik, you don't need any other Docker container to run: https://goauthentik.io/docs/providers/proxy/server_traefik. Authelia does the same thing with HAProxy, but Authentik does not, which is my issue.
I would love to see that as well. I am running HAProxy as my reverse proxy and having the configuration shared like you guys do for traefik, npm, caddy would be great.
@thimplicity FYI, usually, devs prefer when people give a thumbs up or similar emoji to the first post. It makes it easier for them to see how much reaction an issue gets rather than counting all reaction messages.
Hi all!
I got forward auth working with haproxy and authentik. I took most of the source from authelia samples and modified the parameters to play well with authentiks nginx outpost.
Take lua files and general preconditions from here: https://github.com/authelia/authelia/tree/master/internal/suites/example/compose/haproxy
within your haproxy.conf frontend place:
http-request set-var(req.scheme) str(http) if !{ ssl_fc }
http-request set-var(req.questionmark) str(?) if { query -m found }
http-request set-header X-Real-IP %[src]
http-request set-header X-Forwarded-Method %[method]
http-request set-header X-Forwarded-Proto %[var(req.scheme)]
http-request set-header X-Forwarded-Host %[req.hdr(Host)]
http-request set-header X-Original-URL %[url]
acl protected-frontends hdr(host) -m reg -i ^(?i)(aaaa|bbbb|cccc)\.xx\.xxxx\.xx
acl is_authentikoutpost path -m reg ^/outpost.goauthentik.io/
# websockets break if all headers are passed to be_auth_requests as the Upgrade header screws the process up - so we pass manual list
http-request lua.auth-intercept be_auth_request /outpost.goauthentik.io/auth/nginx HEAD x-original-url,x-real-ip,x-forwarded-host,x-forwarded-proto,user-agent,cookie,accept,x-forwarded-method x-authentik-username,x-authentik-uid,x-authentik-email,x-authentik-name,x-authentik-groups - if protected-frontends !is_authentikoutpost
http-request redirect code 302 location /outpost.goauthentik.io/start?rd=%[hdr(X-Original-URL)] if protected-frontends !{ var(txn.auth_response_successful) -m bool } { var(txn.auth_response_code) -m int 401 } !is_authentikoutpost
http-request deny if protected-frontends !{ var(txn.auth_response_successful) -m bool } { var(txn.auth_response_code) -m int 403 } !is_authentikoutpost
http-request redirect location %[var(txn.auth_response_location)] if protected-frontends !{ var(txn.auth_response_successful) -m bool } !is_authentikoutpost
use_backend be_auth if protected-frontends is_authentikoutpost
and the required backends:
backend be_auth_request
server proxy 127.0.0.1:8085
listen be_auth_request_proxy
bind :::8085 v4v6
server authentikhost authentikhost.xxx.xxx.xx:8443 ssl verify none check
within authentik set up a provider configured as Forward auth (single application) and input your domain and you should be good to go. Disclaimer: I am no expert in this - if you see any obvious errors or security holes please point them out :)
best regards
Michael
Hi Michael,
I'm pretty inexperienced with HAProxy but was told to use it and now I'm in the weeds trying to get it to work with authentik. Any chance you can give me a hand with this, either with screenshots or more explicit instructions? I basically got into this mess following Laurence Systems youtube videos for HAProxy and ACME and pfsense. So I am about as ignorant as it comes with this and unfortunately i dont have the time for the forseeable future to redo everything i did with other proxies to something like npm. Ive got sftp'd into my pfsense box and made a backup of my haproxy.cfg. Could you give me something more to work with so I can get this setup? Id be really in your debt.
EDIT: I put a link to my discord profile in my github social links if you want to try and reach out.
did anyone else ever get this working on pfsense with haproxy? tried the above by @miccico with no success
@LojDev maybe i can help. I implemented the set-up - Ha-Proxy (Pfsense) | Traefik | Authentik.
Where did you get stuck?
I had some problem with pfsense GUI and how to set-up the "lua.auth-intercept" and rules for "ha-proxy". Following post (not related to the exact topic here) helped me to understand it. How to configure lua.auth-intercept in pfsense
To upload the file to pfsense through the GUI: Command Prompt -> Upload (pfsense upload it to /tmp/[Filename]). Then cp to destination: cp /tmp/[Filename] /path/to/destination
I used the set up @miccico, but changed the lua script because it hasn't set the response headers properly. So i used wildcards.
http-request lua.auth-intercept bmAuthentik_ipvANY /outpost.goauthentik.io/auth/traefik HEAD "*" "*" "*" - if protected-frontends !is_authentikoutpost
hey @raphaeldeveloperberlin,
When I attempted it, I couldnt get authentik to load at all after following what miccico shared.
I already had authelia setup as my frontend auth provider so i already had the json.lua, auth-request.lua and haproxy-lua-http.lua files setup in haproxy however i replaced the auth-request.lua and haproxy-lua-http.lua with the ones from the link miccico shared because I belive i saw some differences in those ones.
Then after a few days of messing around I got authentik to load by not using the is_authentikopupost
acl. I created a custom acl here hdr(host) -m reg -i ^(?i)([\w\d\-]*[\.]*)*([\.]?com)((\/outpost.goauthentik.io)[\/]?)?
and by using this acl got authentik to load but then I ran into another issue where whenever I would authenticate, it would not redirect to the service i was trying to access, authentik would always redirect to itself. I believe I had to slightly modify some more of the info that miccico posted but i forgot those modifications as I did not really document the changes i made apart from that custom acl i made.
And thats where I stopped and gave up and moved back to authelia. I have not tried to get authentik working with haproxy since then.
If you could post some pictures of how you have the acl's and actions setup in pfsense, that may be of some help.
@miccico Feel free to open a PR to add these instructions to the docs, or if you're ok with we can also add it to the docs
How to configure lua.auth-intercept in pfsense
Would you be able to post some pictures of your setup please @raphaeldeveloperberlin
So, I've got this semi working, pretty sure miccico's config has at least one error
use_backend be_auth (on the last line) should be:
use_backend be_auth_request
Here's my full haproxy config:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
maxconn 40000
ulimit-n 81000
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
# 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
# Authentik Auth Lua files
lua-prepend-path /usr/local/share/lua/5.3/?.lua
lua-load /usr/local/share/lua/5.3/auth-request.lua
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
timeout connect 30s
timeout client 30s
timeout server 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
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
# LE Backend
backend letsencrypt-backend
server letsencrypt 127.0.0.1:8888
# Frontend for redirecting traffic to the required frontend
frontend https-redirect
bind *:443 ssl crt /etc/ssl/home.MYDOMAIN.com.pem
mode tcp
option tcplog
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
acl internal src 0.0.0.0/24 #IP RANGE OF MY NETWORK
use_backend internal if internal
# Frontend for users
frontend internal
bind abns@internal accept-proxy
# Crowdsec bouncer
stick-table type ip size 10k expire 30m # declare a stick table to cache captcha verifications
http-request lua.crowdsec_allow # action to identify crowdsec remediation
http-request track-sc0 src if { var(req.remediation) -m str "captcha-allow" } # cache captcha allow decision
http-request redirect location %[var(req.redirect_uri)] if { var(req.remediation) -m str "captcha-allow" } # redirect to initial url
http-request use-service lua.reply_captcha if { var(req.remediation) -m str "captcha" } # serve captcha template if remediation is captcha
http-request use-service lua.reply_ban if { var(req.remediation) -m str "ban" } # serve ban template if remediation is ban
#Authentik config
acl protected-frontends hdr(host) -m reg -i ^(?i)(arrs|downloads)\.(home|media)\.home\.MYDOMAIN\.com
acl is_authentikoutpost path -m reg ^/outpost.goauthentik.io/
http-request set-var(req.scheme) str(http) if !{ ssl_fc }
http-request set-var(req.questionmark) str(?) if { query -m found }
http-request set-header X-Real-IP %[src]
http-request set-header X-Forwarded-Method %[method]
http-request set-header X-Forwarded-Proto %[var(req.scheme)]
http-request set-header X-Forwarded-Host %[req.hdr(Host)]
http-request set-header X-Original-URL %[url]
# websockets break if all headers are passed to be_auth_requests as the Upgrade header screws the process up - so we pass manual list
http-request lua.auth-intercept be_auth_request /outpost.goauthentik.io/auth/nginx HEAD x-original-url,x-real-ip,x-forwarded-host,x-forwarded-proto,user-agent,cookie,accept,x-forwarded-method x-authentik-username,x-authentik-uid,x-authentik-email,x-authentik-name,x-authentik-groups - if protected-frontends !is_authentikoutpost
http-request redirect code 302 location /outpost.goauthentik.io/start?rd=%[hdr(X-Original-URL)] if protected-frontends !{ var(txn.auth_response_successful) -m bool } { var(txn.auth_response_code) -m int 401 } !is_authentikoutpost
http-request deny if protected-frontends !{ var(txn.auth_response_successful) -m bool } { var(txn.auth_response_code) -m int 403 } !is_authentikoutpost
http-request redirect location %[var(txn.auth_response_location)] if protected-frontends !{ var(txn.auth_response_successful) -m bool } !is_authentikoutpost
# Select backend based on services.map file or use backend no-match if not found.
use_backend be_auth_request if protected-frontends is_authentikoutpost
use_backend %[base,lower,map_beg(/etc/haproxy/services.map,no-match)]
use_backend %[req.hdr(host),lower,map(/etc/haproxy/services.map,no-match)]
backend internal
mode tcp
server loopback-for-tls abns@internal send-proxy-v2
backend auth
server auth home:9443 ssl verify none check
backend be_auth_request
server proxy home:9000 check
listen be_auth_request_proxy
bind :9000
server be_auth_request home:9443 ssl verify none check
listen ldap_proxy
bind :389
server proxy home:389 check
backend ldap
server be_auth_request home:389 check
# Normal Backends
backend no-match
http-request deny deny_status 403
backend homedash
server homedash home:81 check
backend hassio
server hassio home:8123 check
backend downloads
server downloads home:8200 check
backend prowlarr
server prowlarr home:9696 check
backend radarr
server radarr home:7878 check
backend sonarr
server sonarr home:8989 check
backend arrs
server arrs home:5055 check
# Backend for google to allow DNS resolution if using reCAPTCHA
backend captcha_verifier
server captcha_verifier www.google.com:443 check
# Backend for crowdsec to allow DNS resolution
backend crowdsec
server crowdsec *:8080 check
My services.map file:
home.MYDOMAIN.com homedash
#
auth.home.MYDOMAIN.com auth
auth.home.MYDOMAIN.com be_auth_request
home.home.MYDOMAIN.com hassio
#
arrs.media.home.MYDOMAIN.com arrs
#
downloads.media.home.MYDOMAIN.com downloads
arrs.media.home.MYDOMAIN.com/prowlarr prowlarr
arrs.media.home.MYDOMAIN.com/radarr radarr
arrs.media.home.MYDOMAIN.com/sonarr sonarr
A few notes:
If someone chooses to emulate this config, crowdsec can either be omitted or configured using this as a guide: https://ciphermenial.github.io/posts/haproxy-crowdsec/ (just omit the Cloudflare part unless you need it). Otherwise all that needs changing is MYDOMAIN and the ip range for the acl
I still haven't figured out how to translate:
proxy_set_header X-ak-hass-user $X_ak_hass_user;
auth_request_set $X_ak_hass_user $upstream_http_x_ak_hass_user;
To haproxy
So anyway, this is far as I've got, if anyone has any solutions/fixes for 2 and 3 it'd be most welcomed, if not maybe this will get a few people further than they've got so far.
https://goauthentik.io/docs/providers/proxy/forward_auth lists only forward-auth setups with Nginx, Caddy, Envoy, and Traefik. I use HAProxy, and am not sure how to set it up, so I cannot use Authentik yet.
Authelia has a setup with HAProxy. Could you write up something about this reverse-proxy as well?