mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-04-19 06:44:58 +00:00
feat(docs): Add HAProxy Configurations to Docs (#1424)
* Add HAProxy docs * Add changes to Changelog * Add CodeBlock import to haproxy.mdc * Fix typos * Add exceptions to spelling
This commit is contained in:
6
.github/actions/spelling/expect.txt
vendored
6
.github/actions/spelling/expect.txt
vendored
@@ -119,6 +119,7 @@ FCr
|
|||||||
fcrdns
|
fcrdns
|
||||||
fediverse
|
fediverse
|
||||||
ffprobe
|
ffprobe
|
||||||
|
fhdr
|
||||||
financials
|
financials
|
||||||
finfos
|
finfos
|
||||||
Firecrawl
|
Firecrawl
|
||||||
@@ -156,6 +157,7 @@ grw
|
|||||||
gzw
|
gzw
|
||||||
Hashcash
|
Hashcash
|
||||||
hashrate
|
hashrate
|
||||||
|
hdr
|
||||||
headermap
|
headermap
|
||||||
healthcheck
|
healthcheck
|
||||||
healthz
|
healthz
|
||||||
@@ -165,6 +167,7 @@ Hetzner
|
|||||||
hmc
|
hmc
|
||||||
homelab
|
homelab
|
||||||
hostable
|
hostable
|
||||||
|
HSTS
|
||||||
htmlc
|
htmlc
|
||||||
htmx
|
htmx
|
||||||
httpdebug
|
httpdebug
|
||||||
@@ -331,6 +334,8 @@ stackoverflow
|
|||||||
startprecmd
|
startprecmd
|
||||||
stoppostcmd
|
stoppostcmd
|
||||||
storetest
|
storetest
|
||||||
|
srcip
|
||||||
|
strcmp
|
||||||
subgrid
|
subgrid
|
||||||
subr
|
subr
|
||||||
subrequest
|
subrequest
|
||||||
@@ -355,6 +360,7 @@ Timpibot
|
|||||||
TLog
|
TLog
|
||||||
traefik
|
traefik
|
||||||
trunc
|
trunc
|
||||||
|
txn
|
||||||
uberspace
|
uberspace
|
||||||
Unbreak
|
Unbreak
|
||||||
unbreakdocker
|
unbreakdocker
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Fix honeypot and imprint links missing `BASE_PREFIX` when deployed behind a path prefix ([#1402](https://github.com/TecharoHQ/anubis/issues/1402))
|
- Fix honeypot and imprint links missing `BASE_PREFIX` when deployed behind a path prefix ([#1402](https://github.com/TecharoHQ/anubis/issues/1402))
|
||||||
- Add ANEXIA Sponsor logo to docs ([#1409](https://github.com/TecharoHQ/anubis/pull/1409))
|
- Add ANEXIA Sponsor logo to docs ([#1409](https://github.com/TecharoHQ/anubis/pull/1409))
|
||||||
- Improve idle performance in memory storage
|
- Improve idle performance in memory storage
|
||||||
|
- Add HAProxy Configurations to Docs ([#1424](https://github.com/TecharoHQ/anubis/pull/1424))
|
||||||
|
|
||||||
<!-- This changes the project to: -->
|
<!-- This changes the project to: -->
|
||||||
|
|
||||||
|
|||||||
99
docs/docs/admin/environments/haproxy.mdx
Normal file
99
docs/docs/admin/environments/haproxy.mdx
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# HAProxy
|
||||||
|
|
||||||
|
import CodeBlock from "@theme/CodeBlock";
|
||||||
|
|
||||||
|
To use Anubis with HAProxy, you have two variants:
|
||||||
|
- simple - stick Anubis between HAProxy and your application backend (simple)
|
||||||
|
- perfect if you only have a single application in general
|
||||||
|
- advanced - force Anubis challenge by default and route to the application backend by HAProxy if the challenge is correct
|
||||||
|
- useful for complex setups
|
||||||
|
- routing can be done in HAProxy
|
||||||
|
- define ACLs in HAProxy for domains, paths etc which are required/excluded regarding Anubis
|
||||||
|
- HAProxy 3.0 recommended
|
||||||
|
|
||||||
|
## Simple Variant
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
---
|
||||||
|
title: HAProxy with simple config
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
T(User Traffic)
|
||||||
|
HAProxy(HAProxy Port 80/443)
|
||||||
|
Anubis
|
||||||
|
Application
|
||||||
|
|
||||||
|
T --> HAProxy
|
||||||
|
HAProxy --> Anubis
|
||||||
|
Anubis --> |Happy Traffic| Application
|
||||||
|
```
|
||||||
|
|
||||||
|
Your Anubis env file configuration may look like this:
|
||||||
|
|
||||||
|
import simpleAnubis from "!!raw-loader!./haproxy/simple-config.env";
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{simpleAnubis}</CodeBlock>
|
||||||
|
|
||||||
|
The important part is that `TARGET` points to your actual application and if Anubis and HAProxy are on the same machine, a UNIX socket can be used.
|
||||||
|
|
||||||
|
Your frontend and backend configuration of HAProxy may look like the following:
|
||||||
|
|
||||||
|
import simpleHAProxy from "!!raw-loader!./haproxy/simple-haproxy.cfg";
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{simpleHAProxy}</CodeBlock>
|
||||||
|
|
||||||
|
This simply enables SSL offloading, sets some useful and required headers and routes to Anubis directly.
|
||||||
|
|
||||||
|
## Advanced Variant
|
||||||
|
|
||||||
|
Due to the fact that HAProxy can decode JWT, we are able to verify the Anubis token directly in HAProxy and route the traffic to the specific backends ourselves.
|
||||||
|
|
||||||
|
In this example are three applications behind one HAProxy frontend. Only App1 and App2 are secured via Anubis; App3 is open for everyone. The path `/excluded/path` can also be accessed by anyone.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
---
|
||||||
|
title: HAProxy with advanced config
|
||||||
|
---
|
||||||
|
|
||||||
|
flowchart LR
|
||||||
|
T(User Traffic)
|
||||||
|
HAProxy(HAProxy Port 80/443)
|
||||||
|
B1(App1)
|
||||||
|
B2(App2)
|
||||||
|
B3(App3)
|
||||||
|
Anubis
|
||||||
|
|
||||||
|
T --> HAProxy
|
||||||
|
HAProxy --> |Traffic for App1 and App2 without valid challenge| Anubis
|
||||||
|
HAProxy --> |app1.example.com | B1
|
||||||
|
HAProxy --> |app2.example.com| B2
|
||||||
|
HAProxy --> |app3.example.com| B3
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
For an improved JWT decoding performance, it's recommended to use HAProxy version 3.0 or above.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Your Anubis env file configuration may look like this:
|
||||||
|
|
||||||
|
import advancedAnubis from "!!raw-loader!./haproxy/advanced-config.env";
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{advancedAnubis}</CodeBlock>
|
||||||
|
|
||||||
|
It's important to use `HS512_SECRET` which HAProxy understands. Please replace `<SECRET-HERE>` with your own secret string (alphanumerical string with 128 characters recommended).
|
||||||
|
|
||||||
|
You can set Anubis to force a challenge for every request using the following policy file:
|
||||||
|
|
||||||
|
import advancedAnubisPolicy from "!!raw-loader!./haproxy/advanced-config-policy.yml";
|
||||||
|
|
||||||
|
<CodeBlock language="yaml">{advancedAnubisPolicy}</CodeBlock>
|
||||||
|
|
||||||
|
The HAProxy config file may look like this:
|
||||||
|
|
||||||
|
import advancedHAProxy from "!!raw-loader!./haproxy/advanced-haproxy.cfg";
|
||||||
|
|
||||||
|
<CodeBlock language="haproxy">{advancedHAProxy}</CodeBlock>
|
||||||
|
|
||||||
|
Please replace `<SECRET-HERE>` with the same secret from the Anubis config.
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# /etc/anubis/challenge-any.yml
|
||||||
|
|
||||||
|
bots:
|
||||||
|
- name: any
|
||||||
|
action: CHALLENGE
|
||||||
|
user_agent_regex: .*
|
||||||
|
|
||||||
|
status_codes:
|
||||||
|
CHALLENGE: 403
|
||||||
|
DENY: 403
|
||||||
|
|
||||||
|
thresholds: []
|
||||||
|
|
||||||
|
dnsbl: false
|
||||||
|
|
||||||
11
docs/docs/admin/environments/haproxy/advanced-config.env
Normal file
11
docs/docs/admin/environments/haproxy/advanced-config.env
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# /etc/anubis/default.env
|
||||||
|
|
||||||
|
BIND=/run/anubis/default.sock
|
||||||
|
BIND_NETWORK=unix
|
||||||
|
DIFFICULTY=4
|
||||||
|
METRICS_BIND=:9090
|
||||||
|
# target is irrelevant here, backend routing happens in HAProxy
|
||||||
|
TARGET=http://0.0.0.0
|
||||||
|
HS512_SECRET=<SECRET-HERE>
|
||||||
|
COOKIE_DYNAMIC_DOMAIN=True
|
||||||
|
POLICY_FNAME=/etc/anubis/challenge-any.yml
|
||||||
59
docs/docs/admin/environments/haproxy/advanced-haproxy.cfg
Normal file
59
docs/docs/admin/environments/haproxy/advanced-haproxy.cfg
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# /etc/haproxy/haproxy.cfg
|
||||||
|
|
||||||
|
frontend FE-multiple-applications
|
||||||
|
mode http
|
||||||
|
bind :80
|
||||||
|
# ssl offloading on port 443 using a certificate from /etc/haproxy/ssl/ directory
|
||||||
|
bind :443 ssl crt /etc/haproxy/ssl/ alpn h2,http/1.1 ssl-min-ver TLSv1.2 no-tls-tickets
|
||||||
|
|
||||||
|
# set X-Real-IP header required for Anubis
|
||||||
|
http-request set-header X-Real-IP "%[src]"
|
||||||
|
|
||||||
|
# redirect HTTP to HTTPS
|
||||||
|
http-request redirect scheme https code 301 unless { ssl_fc }
|
||||||
|
# add HSTS header
|
||||||
|
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||||
|
|
||||||
|
# only force Anubis challenge for app1 and app2
|
||||||
|
acl acl_anubis_required hdr(host) -i "app1.example.com"
|
||||||
|
acl acl_anubis_required hdr(host) -i "app2.example.com"
|
||||||
|
|
||||||
|
# exclude Anubis for a specific path
|
||||||
|
acl acl_anubis_ignore path /excluded/path
|
||||||
|
|
||||||
|
# use Anubis if auth cookie not found
|
||||||
|
use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore !{ req.cook(techaro.lol-anubis-auth) -m found }
|
||||||
|
|
||||||
|
# get payload of the JWT such as algorithm, expire time, restrictions
|
||||||
|
http-request set-var(txn.anubis_jwt_alg) req.cook(techaro.lol-anubis-auth),jwt_header_query('$.alg') if acl_anubis_required !acl_anubis_ignore
|
||||||
|
http-request set-var(txn.anubis_jwt_exp) cook(techaro.lol-anubis-auth),jwt_payload_query('$.exp','int') if acl_anubis_required !acl_anubis_ignore
|
||||||
|
http-request set-var(txn.anubis_jwt_res) cook(techaro.lol-anubis-auth),jwt_payload_query('$.restriction') if acl_anubis_required !acl_anubis_ignore
|
||||||
|
http-request set-var(txn.srcip) req.fhdr(X-Real-IP) if acl_anubis_required !acl_anubis_ignore
|
||||||
|
http-request set-var(txn.now) date() if acl_anubis_required !acl_anubis_ignore
|
||||||
|
|
||||||
|
# use Anubis if JWT has wrong algorithm, is expired, restrictions don't match or isn't signed with the correct key
|
||||||
|
use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore !{ var(txn.anubis_jwt_alg) -m str HS512 }
|
||||||
|
use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore { var(txn.anubis_jwt_exp),sub(txn.now) -m int lt 0 }
|
||||||
|
use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore !{ var(txn.srcip),digest(sha256),hex,lower,strcmp(txn.anubis_jwt_res) eq 0 }
|
||||||
|
use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore !{ cook(techaro.lol-anubis-auth),jwt_verify(txn.anubis_jwt_alg,"<SECRET-HERE>") -m int 1 }
|
||||||
|
|
||||||
|
# custom routing in HAProxy
|
||||||
|
use_backend BE-app1 if { hdr(host) -i "app1.example.com" }
|
||||||
|
use_backend BE-app2 if { hdr(host) -i "app2.example.com" }
|
||||||
|
use_backend BE-app3 if { hdr(host) -i "app3.example.com" }
|
||||||
|
|
||||||
|
backend BE-app1
|
||||||
|
mode http
|
||||||
|
server app1-server 127.0.0.1:3000
|
||||||
|
|
||||||
|
backend BE-app2
|
||||||
|
mode http
|
||||||
|
server app2-server 127.0.0.1:4000
|
||||||
|
|
||||||
|
backend BE-app3
|
||||||
|
mode http
|
||||||
|
server app3-server 127.0.0.1:5000
|
||||||
|
|
||||||
|
BE-anubis
|
||||||
|
mode http
|
||||||
|
server anubis /run/anubis/default.sock
|
||||||
10
docs/docs/admin/environments/haproxy/simple-config.env
Normal file
10
docs/docs/admin/environments/haproxy/simple-config.env
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# /etc/anubis/default.env
|
||||||
|
|
||||||
|
BIND=/run/anubis/default.sock
|
||||||
|
BIND_NETWORK=unix
|
||||||
|
SOCKET_MODE=0666
|
||||||
|
DIFFICULTY=4
|
||||||
|
METRICS_BIND=:9090
|
||||||
|
COOKIE_DYNAMIC_DOMAIN=true
|
||||||
|
# address and port of the actual application
|
||||||
|
TARGET=http://localhost:3000
|
||||||
22
docs/docs/admin/environments/haproxy/simple-haproxy.cfg
Normal file
22
docs/docs/admin/environments/haproxy/simple-haproxy.cfg
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# /etc/haproxy/haproxy.cfg
|
||||||
|
|
||||||
|
frontend FE-application
|
||||||
|
mode http
|
||||||
|
bind :80
|
||||||
|
# ssl offloading on port 443 using a certificate from /etc/haproxy/ssl/ directory
|
||||||
|
bind :443 ssl crt /etc/haproxy/ssl/ alpn h2,http/1.1 ssl-min-ver TLSv1.2 no-tls-tickets
|
||||||
|
|
||||||
|
# set X-Real-IP header required for Anubis
|
||||||
|
http-request set-header X-Real-IP "%[src]"
|
||||||
|
|
||||||
|
# redirect HTTP to HTTPS
|
||||||
|
http-request redirect scheme https code 301 unless { ssl_fc }
|
||||||
|
# add HSTS header
|
||||||
|
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||||
|
|
||||||
|
# route to Anubis backend by default
|
||||||
|
default_backend BE-anubis-application
|
||||||
|
|
||||||
|
BE-anubis-application
|
||||||
|
mode http
|
||||||
|
server anubis /run/anubis/default.sock
|
||||||
@@ -203,6 +203,7 @@ To get Anubis filtering your traffic, you need to make sure it's added to your H
|
|||||||
- [Kubernetes](./environments/kubernetes.mdx)
|
- [Kubernetes](./environments/kubernetes.mdx)
|
||||||
- [Nginx](./environments/nginx.mdx)
|
- [Nginx](./environments/nginx.mdx)
|
||||||
- [Traefik](./environments/traefik.mdx)
|
- [Traefik](./environments/traefik.mdx)
|
||||||
|
- [HAProxy](./environments/haproxy.mdx)
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
|
|
||||||
|
|||||||
@@ -143,3 +143,4 @@ For more details on particular reverse proxies, see here:
|
|||||||
|
|
||||||
- [Apache](./environments/apache.mdx)
|
- [Apache](./environments/apache.mdx)
|
||||||
- [Nginx](./environments/nginx.mdx)
|
- [Nginx](./environments/nginx.mdx)
|
||||||
|
- [HAProxy](./environments/haproxy.mdx)
|
||||||
|
|||||||
Reference in New Issue
Block a user