kikeflare branch customisations and error pages

This commit is contained in:
Thomas Lynch
2022-04-25 14:11:57 +10:00
parent 1857e79137
commit e139b04f4b
10 changed files with 425 additions and 32 deletions

32
haproxy/errors/400.http Normal file
View File

@ -0,0 +1,32 @@
HTTP/1.0 400 Bad request
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>403</title>
<style type="text/css">
:root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#EEE}}
a,a:visited{color:var(--text-color)}
body,html{height:100%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
img,h3,p{margin:0 0 5px 0}
footer{font-size:x-small;margin-top:auto;margin-bottom:20px}.pt{padding-top:30vh}
</style>
</head>
<body>
<h3 class="pt">Bad Request.</h3>
<footer>
<img src="/img/footerlogo.png">
<p>Security and Performance by <a href="https://kikeflare.com">Kikeflare</a></p>
<p>Vey ID: <code>4c286855cff704021006c5cc138aae46</code></p>
</footer>
</body>
</html>

32
haproxy/errors/403.http Normal file
View File

@ -0,0 +1,32 @@
HTTP/1.0 403 Forbidden
Cache-Control: no-cache
Connection: close
Content-Type: text/html; charset=utf-8
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>403</title>
<style type="text/css">
:root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#EEE}}
a,a:visited{color:var(--text-color)}
body,html{height:100%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
img,h3,p{margin:0 0 5px 0}
footer{font-size:x-small;margin-top:auto;margin-bottom:20px}.pt{padding-top:30vh}
</style>
</head>
<body>
<h3 class="pt">You look like a robot.</h3>
<footer>
<img src="/img/footerlogo.png">
<p>Security and Performance by <a href="https://kikeflare.com">Kikeflare</a></p>
<p>Vey ID: <code>4c286855cff704021006c5cc138aae46</code></p>
</footer>
</body>
</html>

31
haproxy/errors/408.http Normal file
View File

@ -0,0 +1,31 @@
HTTP/1.0 408 Request Time-out
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>408</title>
<style type="text/css">
:root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#EEE}}
a,a:visited{color:var(--text-color)}
body,html{height:100%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
img,h3,p{margin:0 0 5px 0}
footer{font-size:x-small;margin-top:auto;margin-bottom:20px}.pt{padding-top:30vh}
</style>
</head>
<body>
<h3 class="pt">Request Time-out.</h3>
<footer>
<img src="/img/footerlogo.png">
<p>Security and Performance by <a href="https://kikeflare.com">Kikeflare</a></p>
<p>Vey ID: <code>4c286855cff704021006c5cc138aae46</code></p>
</footer>
</body>
</html>

31
haproxy/errors/429.http Normal file
View File

@ -0,0 +1,31 @@
HTTP/1.0 429 Too Many Requests
Cache-Control: no-cache
Connection: close
Content-Type: text/html; charset=utf-8
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>429</title>
<style type="text/css">
:root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#EEE}}
a,a:visited{color:var(--text-color)}
body,html{height:100%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
img,h3,p{margin:0 0 5px 0}
footer{font-size:x-small;margin-top:auto;margin-bottom:20px}.pt{padding-top:30vh}
</style>
</head>
<body>
<h3 class="pt">Slow down, you look like a robot.</h3>
<footer>
<img src="/img/footerlogo.png">
<p>Security and Performance by <a href="https://kikeflare.com">Kikeflare</a></p>
<p>Vey ID: <code>4c286855cff704021006c5cc138aae46</code></p>
</footer>
</body>
</html>

31
haproxy/errors/500.http Normal file
View File

@ -0,0 +1,31 @@
HTTP/1.0 500 Internal Server Error
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>500</title>
<style type="text/css">
:root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#EEE}}
a,a:visited{color:var(--text-color)}
body,html{height:100%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
img,h3,p{margin:0 0 5px 0}
footer{font-size:x-small;margin-top:auto;margin-bottom:20px}.pt{padding-top:30vh}
</style>
</head>
<body>
<h3 class="pt">Internal Server Error, please try again later.</h3>
<footer>
<img src="/img/footerlogo.png">
<p>Security and Performance by <a href="https://kikeflare.com">Kikeflare</a></p>
<p>Vey ID: <code>4c286855cff704021006c5cc138aae46</code></p>
</footer>
</body>
</html>

30
haproxy/errors/502.http Normal file
View File

@ -0,0 +1,30 @@
HTTP/1.0 502 Bad Gateway
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>502</title>
<style type="text/css">
:root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#EEE}}
a,a:visited{color:var(--text-color)}
body,html{height:100%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
img,h3,p{margin:0 0 5px 0}
footer{font-size:x-small;margin-top:auto;margin-bottom:20px}.pt{padding-top:30vh}
</style>
</head>
<body>
<h3 class="pt">Bad Gateway.</h3>
<footer>
<img src="/img/footerlogo.png">
<p>Security and Performance by <a href="https://kikeflare.com">Kikeflare</a></p>
<p>Vey ID: <code>4c286855cff704021006c5cc138aae46</code></p>
</footer>
</body>
</html>

31
haproxy/errors/503.http Normal file
View File

@ -0,0 +1,31 @@
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html; charset=utf-8
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>503</title>
<style type="text/css">
:root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#EEE}}
a,a:visited{color:var(--text-color)}
body,html{height:100%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
img,h3,p{margin:0 0 5px 0}
footer{font-size:x-small;margin-top:auto;margin-bottom:20px}.pt{padding-top:30vh}
</style>
</head>
<body>
<h3 class="pt">Service Unavailable.</h3>
<p>Sorry, the backend is unreachable or down for essential maintenance. Try again soon!</p>
<footer>
<img src="/img/footerlogo.png">
<p>Security and Performance by <a href="https://kikeflare.com">Kikeflare</a></p>
<p>Vey ID: <code>4c286855cff704021006c5cc138aae46</code></p>
</footer>
</body>
</html>

31
haproxy/errors/504.http Normal file
View File

@ -0,0 +1,31 @@
HTTP/1.0 504 Gateway Time-out
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>503</title>
<style type="text/css">
:root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#EEE}}
a,a:visited{color:var(--text-color)}
body,html{height:100%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
img,h3,p{margin:0 0 5px 0}
footer{font-size:x-small;margin-top:auto;margin-bottom:20px}.pt{padding-top:30vh}
</style>
</head>
<body>
<h3 class="pt">Gateway Time-out.</h3>
<p>Sorry, the backend is unreachable or down for essential maintenance. Try again soon!</p>
<footer>
<img src="/img/footerlogo.png">
<p>Security and Performance by <a href="https://kikeflare.com">Kikeflare</a></p>
<p>Vey ID: <code>4c286855cff704021006c5cc138aae46</code></p>
</footer>
</body>
</html>

View File

@ -1,38 +1,110 @@
global
daemon
maxconn 256
log stdout format raw local0 debug
lua-load /etc/haproxy/scripts/register.lua
stats socket /var/run/haproxy.sock mode 666 level admin
stats socket *:2000 level admin
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
maxconn 10000
#for haproxy panel
stats socket 127.0.0.1:1999 level operator
stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners
stats timeout 30s
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-options ssl-min-ver TLSv1.2 prefer-client-ciphers
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-ciphers ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:ECDH+AES128:!aNULL:!SHA1:!AESCCM
ssl-default-server-options ssl-min-ver TLSv1.2
ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-server-ciphers ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:ECDH+AES128:!aNULL:!SHA1:!AESCCM
tune.ssl.default-dh-param 2048
defaults
option logasap
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option httplog
# option dontlognull
#timeout slow connection
timeout connect 5000
#timeout slow request headers
timeout http-request 5000
#timeout very very slow clients
timeout client 90000
#timeout if server dead
timeout server 10000
#timeout websockets after long time, not 0 just in case. it wil reconnect anyway.
timeout tunnel 900000
#timeout for tarpitting bots
timeout tarpit 10000
errorfile 429 /etc/haproxy/errors/429.http
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
option forwardfor
option http-keep-alive
program api
command dataplaneapi -f /etc/haproxy/dataplaneapi.hcl --update-map-files
no option start-on-reload
##### Better log format
log-format "%ci %s %ST %{+Q}r %B %ts CONC:[%ac/%fc/%bc/%sc] QUEUE:[%sq/%bq]"
frontend http-in
bind *:80
# necessary to firewall, white_list acl in development
frontend stats-frontend
bind *:2000
option tcplog
mode tcp
acl white_list src xxx.xxx.xxx.xxx
tcp-request connection reject unless white_list
default_backend stats-backend
backend stats-backend
mode tcp
server stats-localhost 127.0.0.1:1999
backend per_ip_rates
stick-table type ip size 100k expire 1h store gpc0,gpc0_rate(30s),http_err_rate(5m)
frontend www-http-https
# Bind and multiple certs in folder
bind :::80
bind :::443 ssl crt /etc/haproxy/certs alpn h2,http/1.1
# HTTPS redirect
http-request redirect scheme https if !{ ssl_fc }
# Tarpit when too many errors
http-request tarpit deny_status 429 if { sc_http_err_rate(0) gt 5 }
# kikeflare ACL for separate backend
acl is_kikeflare hdr(host) -i kikeflare.com www.kikeflare.com
# drop requests with invalid host header
acl is_existing_vhost hdr(host),lower,map_str(/etc/haproxy/hosts.map) -m found
http-request silent-drop unless is_existing_vhost
# debug only, /cdn-cgi/trace
#http-request return status 200 content-type "text/plain; charset=utf-8" lf-file /etc/haproxy/trace.txt if { path /cdn-cgi/trace }
# acl for blocked IPs/subnets
acl blocked_ip_or_subnet src,map_ip(/etc/haproxy/blocked.map) -m found
http-request deny deny_status 403 if blocked_ip_or_subnet
# acl for lua check whitelisted IPs/subnets and some excluded paths
acl is_excluded src,map_ip(/etc/haproxy/whitelist.map) -m found
acl is_excluded path /favicon.ico #add more
acl is_excluded path_end -i .css .js .png .jpg .ico .jpeg .gif .mp4 .webm .bmp .mov .svg .mp3 .ogg .wav .opus .apng .webp .pjpeg .jfif .txt .sid .pdf .webmanifest .xml .flac .m4a .aac
acl is_excluded path /favicon.ico /webring.json #add more
# acl ORs for when ddos_mode_enabled
acl ddos_mode_enabled_override hdr_cnt(xr3la1rfFc) eq 0
@ -42,8 +114,10 @@ frontend http-in
# serve challenge page scripts directly from haproxy
acl is_sha1_js path /js/sha1.js
acl is_worker_js path /js/worker.js
acl is_footerlogo_png path /img/footerlogo.png
http-request return file /var/www/js/sha1.js status 200 content-type "application/javascript; charset=utf-8" hdr "cache-control" "public, max-age=300" if is_sha1_js
http-request return file /var/www/js/worker.js status 200 content-type "application/javascript; charset=utf-8" hdr "cache-control" "public, max-age=300" if is_worker_js
http-request return file /var/www/img/footerlogo.png status 200 content-type "image/png" hdr "cache-control" "public, max-age=300" if is_footerlogo_png
# create acl for bools updated by lua
acl captcha_passed var(txn.captcha_passed) -m bool
@ -60,29 +134,100 @@ frontend http-in
http-request lua.pow-check if !is_excluded !on_captcha_url validate_pow OR !is_excluded !on_captcha_url ddos_mode_enabled_override
http-request redirect location /bot-check?%[capture.req.uri] code 302 if validate_captcha !captcha_passed !on_captcha_url ddos_mode_enabled !is_excluded OR validate_pow !pow_passed !on_captcha_url ddos_mode_enabled !is_excluded OR !pow_passed ddos_mode_enabled_override !on_captcha_url !is_excluded
# redirect handle trailing slash and index.html
acl dont-redirect path_reg ^\/(captcha|randombanner|forms|logout|socket\.io)(\/|$)
acl needs-trailing-slash path_reg ^([^.\?]*[^/])$
acl has-trailing-slash path_end /
http-request redirect scheme https append-slash if !dont-redirect needs-trailing-slash !is_kikeflare
http-request redirect location https://%[req.hdr(host)]%[path]index.html%[query] if !dont-redirect has-trailing-slash !is_kikeflare
# remove www.
http-request redirect location https://%[req.hdr(host),regsub(^www.,)]%[capture.req.uri] if { hdr_beg(host) -i www }
# X-Cache-Status header (may be sent in some non-cache responses because NOSRV can happen for other reasons, but should always be present in responses served by cache-use)
http-response set-header X-Cache-Status HIT if !{ srv_id -m found }
http-response set-header X-Cache-Status MISS if { srv_id -m found }
default_backend servers
# Track client by url32+src (Host header + URL path + src IP), deny if rate abuse
stick-table type binary len 8 size 200k expire 10s store http_req_rate(10s)
http-request track-sc0 url32+src
acl rate_abuse sc0_http_req_rate gt 50
http-request tarpit deny_status 429 if rate_abuse
cache basic_cache
# Send LetsEncrypt requests to alternative backend that handles certs
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
# Socketio backend (doesnt try to upgrade to http2)
acl socketio path_beg /socket.io/
use_backend no-http2-backend if socketio
# Captcha backend with queue/maxconn
acl captcha path -i /captcha /captcha/
use_backend maxconn-20-backend if captcha
# Kikeflare acl separate backend
use_backend basic-cache-backend if is_kikeflare
# Otherwise, send to main backend
default_backend complex-cache-backend
cache long_cache
total-max-size 2500
max-object-size 31457280
max-age 86400
backend servers
cache short_cache
total-max-size 50
max-object-size 1000000
max-age 600
# simple example cache for files
cache micro_cache
total-max-size 50
max-object-size 1000000
max-age 60
backend letsencrypt-backend
server www-1 xxx.xxx.xxx.xxx:80
# a complex backend that has a few different caches, and is catered to work well specifically with jschan
backend complex-cache-backend
http-request set-var(txn.path) path
acl can_cache var(txn.path) -i -m end .png .jpg .jpeg .jpe .ico .webmanifest .xml .apng .bmp .webp .pjpeg .jfif .gif .mp4 .webm .mov .mkv .svg .m4a .aac .flac .mp3 .ogg .wav .opus .txt .pdf .sid
http-request cache-use basic_cache if can_cache
http-response cache-store basic_cache if can_cache
# placeholder servers, activated by LUA or the control panel
server-template websrv 1-100 0.0.0.0:80 check disabled
# use server based on hostname
use-server %[req.hdr(host),lower,map(/etc/haproxy/backends.map)] if TRUE
##### longer cache
acl long_cached_file var(txn.path) -i -m end .css .js .png .jpg .ico .jpeg .gif .mp4 .webm .bmp .mov .svg .mp3 .ogg .wav .opus .apng .webp .pjpeg .jfif .txt .sid .pdf .webmanifest .xml .flac .m4a .m4v .ts .aac
acl long_cached_page var(txn.path) -i -m beg /rules.html /faq.html /robots.txt
http-request cache-use long_cache if long_cached_file or long_cached_page
http-response cache-store long_cache if long_cached_file or long_cached_page
##### shorter cache
acl short_cached_page var(txn.path) -i -m beg /index.html /news.html
http-request cache-use short_cache if short_cached_page
http-response cache-store short_cache if short_cached_page
##### micro cache
acl micro_cached_page var(txn.path) -i -m beg /boards.html /catalog.html /overboard.html /boards.json
http-request cache-use micro_cache if micro_cached_page
http-response cache-store micro_cache if micro_cached_page
server www-1 xxx.xxx.xxx.xxx:443 ssl verify required ca-file /etc/ssl/certs/backend.pem alpn h2
# a simpler backend that caches mostly media and css/js
backend basic-cache-backend
http-request set-var(txn.path) path
##### longer cache
acl long_cached_file var(txn.path) -i -m end .css .js .png .jpg .ico .jpeg .gif .mp4 .webm .bmp .mov .svg .mp3 .ogg .wav .opus .apng .webp .pjpeg .jfif .txt .sid .pdf .webmanifest .xml .flac .m4a .m4v .ts .aac
http-request cache-use long_cache if long_cached_file
http-response cache-store long_cache if long_cached_file
server www-1 xxx.xxx.xxx.xxx:443 ssl verify required ca-file /etc/ssl/certs/backend.pem alpn h2
backend no-http2-backend
server www-1 xxx.xxx.xxx.xxx:443 ssl verify required ca-file /etc/ssl/certs/backend.pem
backend maxconn-20-backend
server www-1 xxx.xxx.xxx.xxx:443 ssl verify required ca-file /etc/ssl/certs/backend.pem maxconn 20 alpn h2
backend hcaptcha
mode http

View File

@ -59,7 +59,7 @@ local body_template = [[
.red{color:red;font-weight:bold}
a,a:visited{color:var(--text-color)}
body,html{height:100%%}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Arial,Helvetica,sans-serif;text-align:center;margin:0}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Helvetica,Arial,sans-serif;text-align:center;margin:0}
details{max-width:80vw;text-align:left;margin:0 auto;}
summary{text-align:center;}
code{background-color:#dfdfdf30;border-radius:3px;padding:0 3px;}
@ -106,7 +106,7 @@ local noscript_extra_template = [[
-- 3 dots animation for proof of work
local pow_section_template = [[
<h3 class="pt">Checking your browser for robots...</h3>
<h3 class="pt">Checking your browser for robots 🤖</h3>
<div class="jsonly">
<div class="b"></div>
<div class="b"></div>
@ -116,8 +116,7 @@ local pow_section_template = [[
-- message, hcaptcha form and submit button
local captcha_section_template = [[
<p class="pt">We have registered suspicious traffic coming from your network.</p>
<p>Please solve the captcha to continue.</p>
<p class="pt">Please solve the captcha to continue.</p>
<form class="jsonly" method="POST">
<div class="h-captcha" data-sitekey="%s"></div>
<script src="https://hcaptcha.com/1/api.js" async defer></script>