diff --git a/haproxy/errors/400.http b/haproxy/errors/400.http new file mode 100644 index 0000000..7d957d1 --- /dev/null +++ b/haproxy/errors/400.http @@ -0,0 +1,32 @@ +HTTP/1.0 400 Bad request +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + + + 403 + + + +

Bad Request.

+ + + + + diff --git a/haproxy/errors/403.http b/haproxy/errors/403.http new file mode 100644 index 0000000..92fc696 --- /dev/null +++ b/haproxy/errors/403.http @@ -0,0 +1,32 @@ +HTTP/1.0 403 Forbidden +Cache-Control: no-cache +Connection: close +Content-Type: text/html; charset=utf-8 + + + + + + 403 + + + +

You look like a robot.

+ + + + + diff --git a/haproxy/errors/408.http b/haproxy/errors/408.http new file mode 100644 index 0000000..1ae5a00 --- /dev/null +++ b/haproxy/errors/408.http @@ -0,0 +1,31 @@ +HTTP/1.0 408 Request Time-out +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + + + 408 + + + +

Request Time-out.

+ + + + diff --git a/haproxy/errors/429.http b/haproxy/errors/429.http new file mode 100644 index 0000000..69d20eb --- /dev/null +++ b/haproxy/errors/429.http @@ -0,0 +1,31 @@ +HTTP/1.0 429 Too Many Requests +Cache-Control: no-cache +Connection: close +Content-Type: text/html; charset=utf-8 + + + + + + 429 + + + +

Slow down, you look like a robot.

+ + + + diff --git a/haproxy/errors/500.http b/haproxy/errors/500.http new file mode 100644 index 0000000..9c07984 --- /dev/null +++ b/haproxy/errors/500.http @@ -0,0 +1,31 @@ +HTTP/1.0 500 Internal Server Error +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + + + 500 + + + +

Internal Server Error, please try again later.

+ + + + diff --git a/haproxy/errors/502.http b/haproxy/errors/502.http new file mode 100644 index 0000000..2127b67 --- /dev/null +++ b/haproxy/errors/502.http @@ -0,0 +1,30 @@ +HTTP/1.0 502 Bad Gateway +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + + + 502 + + + +

Bad Gateway.

+ + + diff --git a/haproxy/errors/503.http b/haproxy/errors/503.http new file mode 100644 index 0000000..889eb28 --- /dev/null +++ b/haproxy/errors/503.http @@ -0,0 +1,31 @@ +HTTP/1.0 503 Service Unavailable +Cache-Control: no-cache +Connection: close +Content-Type: text/html; charset=utf-8 + + + + + + 503 + + + +

Service Unavailable.

+

Sorry, the backend is unreachable or down for essential maintenance. Try again soon!

+ + + diff --git a/haproxy/errors/504.http b/haproxy/errors/504.http new file mode 100644 index 0000000..f133882 --- /dev/null +++ b/haproxy/errors/504.http @@ -0,0 +1,31 @@ +HTTP/1.0 504 Gateway Time-out +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + + + 503 + + + +

Gateway Time-out.

+

Sorry, the backend is unreachable or down for essential maintenance. Try again soon!

+ + + diff --git a/haproxy/haproxy.cfg b/haproxy/haproxy.cfg index bac0583..188bc6f 100644 --- a/haproxy/haproxy.cfg +++ b/haproxy/haproxy.cfg @@ -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 diff --git a/src/scripts/hcaptcha.lua b/src/scripts/hcaptcha.lua index 33e3433..87c2ea1 100644 --- a/src/scripts/hcaptcha.lua +++ b/src/scripts/hcaptcha.lua @@ -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 = [[ -

Checking your browser for robots...

+

Checking your browser for robots 🤖

@@ -116,8 +116,7 @@ local pow_section_template = [[ -- message, hcaptcha form and submit button local captcha_section_template = [[ -

We have registered suspicious traffic coming from your network.

-

Please solve the captcha to continue.

+

Please solve the captcha to continue.