fix: login u Web GUI izbacivao van panela + nginx rate limit prenizak

1) Nakon uspjesnog logina redirect je isao na sirovi 'next' parametar.
   'next' dolazi iz request.path, dakle bez SCRIPT_NAME prefiksa, pa je
   /guacadmin/login?next=/ nakon prijave vodio na / -> /guacamole/.
   Korisnik bi se prijavio i zavrsio na Guacamole login ekranu umjesto
   na dashboardu. Sad se dodaje request.script_root, uz provjeru da je
   next relativna putanja (open-redirect).

2) limit_req_zone je bio rate=10r/m - deset zahtjeva po MINUTI.
   Guacamole je Angular SPA i na jedno otvaranje ispali desetke
   zahtjeva, pa je nginx redom vracao 503 na app.js, app.css,
   api/tokens i translations. Podignuto na 10r/s, burst 50.
   Brute-force i dalje pokrivaju basic auth + fail2ban.

Provjereno: /guacadmin/ -> login -> /guacadmin/dashboard (200), svih
osam GUI stranica 200, 40 paralelnih zahtjeva na Guacamole API sve 200.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 20:15:17 +02:00
parent 0d96852947
commit d54bb27021
2 changed files with 19 additions and 5 deletions
+12 -4
View File
@@ -352,7 +352,9 @@ map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
limit_req_zone $binary_remote_addr zone=guac_req:10m rate=10r/m;
# Guacamole je Angular SPA i na jedno otvaranje ispali desetke
# zahtjeva; 10r/m je rusilo ucitavanje. Brute-force pokriva fail2ban.
limit_req_zone $binary_remote_addr zone=guac_req:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=guac_ws:10m rate=30r/m;
EOF
@@ -381,7 +383,7 @@ server {
location /guacamole/ {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.guac_htpasswd;
limit_req zone=guac_req burst=20 nodelay;
limit_req zone=guac_req burst=50 nodelay;
proxy_pass http://127.0.0.1:${GUAC_PORT}/guacamole/;
proxy_buffering off;
@@ -530,7 +532,7 @@ server {
location /guacamole/ {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.guac_htpasswd;
limit_req zone=guac_req burst=20 nodelay;
limit_req zone=guac_req burst=50 nodelay;
proxy_pass http://127.0.0.1:${GUAC_PORT}/guacamole/;
proxy_buffering off;
@@ -781,7 +783,13 @@ def login():
request.form.get('password') == cfg['password']):
session.permanent = True
session['logged_in'] = True
return redirect(request.args.get('next') or url_for('dashboard'))
# 'next' je PATH_INFO bez prefiksa; bez script_roota redirect
# izlazi izvan GUI_PATH-a i korisnik zavrsi na Guacamole loginu.
target = request.args.get('next') or ''
if not target.startswith('/') or target.startswith('//'):
target = ''
return redirect(request.script_root + target if target
else url_for('dashboard'))
flash('Pogrešno korisničko ime ili lozinka', 'danger')
return render_template('login.html')