R-753: the box tells visitors apart — cloudflared at a fixed address, traefik trusts only it, the controller reads the hop traefik saw
- felhom-tunnel network 172.16.253.0/29 (ip-range .4/30): cloudflared alone at .2, traefik at .3; traefik's websecure trusts forwarded headers from 172.16.253.2/32 only, and every request passes felhom-forwarded@file, which removes the client-writable host/path/address headers (X-Forwarded-Host/-Uri/-Method/-Prefix, Forwarded, True-Client-Ip, …) and fixes X-Forwarded-Port to 443 (measured: Cloudflare passes a client's X-Forwarded-Host/-Port). - EnsureBaseStack reconciles a RUNNING traefik/cloudflared whose rendered files changed (recreate), refuses a rewrite that would drop a certificate resolver, and moves cloudflared only once traefik is on the tunnel network. - clientIP: believed only when the TCP peer is traefik; the rightmost X-Forwarded-For entry (the hop traefik saw); the tunnel hop → CF-Connecting-IP (the edge refuses a client-sent one, measured 403). rateKey: IPv6 per /64. Dashboard login, claim, share and escrow counters key on it; the setup gate logs it. - Dashboard login messages: keys, informal voice, both languages. Red-proofs: RP-A1 (leftmost hop), RP-A2 (shared tunnel key), RP-A3 (no reconcile) — felhom.eu audits/visitors-2026-10-01/A. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -220,7 +220,7 @@ func (s *Server) ServeGateAuth(w http.ResponseWriter, r *http.Request) {
|
||||
if u, err := url.Parse(uri); err == nil && u.Path == gateCallbackURI {
|
||||
rd, err := s.takeGateToken(u.Query().Get("t"), host)
|
||||
if err != nil {
|
||||
s.logger.Printf("[WARN] [web] setup gate %s: a sign-in token was refused (%v)", app, err)
|
||||
s.logger.Printf("[WARN] [web] setup gate %s: a sign-in token was refused (%v) — visitor %s", app, err, clientIP(r))
|
||||
gateRefuse(w, http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
@@ -229,7 +229,7 @@ func (s *Server) ServeGateAuth(w http.ResponseWriter, r *http.Request) {
|
||||
Name: gateCookieName, Value: exp + "." + s.gateMAC("cookie", host, exp), Path: "/",
|
||||
MaxAge: int(gateCookieLife.Seconds()), HttpOnly: true, Secure: true, SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
s.logger.Printf("[INFO] [web] setup gate %s: the household passed (a dashboard session vouched for this browser)", app)
|
||||
s.logger.Printf("[INFO] [web] setup gate %s: the household passed (a dashboard session vouched for this browser) — visitor %s", app, clientIP(r))
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
http.Redirect(w, r, rd, http.StatusFound)
|
||||
return
|
||||
@@ -245,7 +245,7 @@ func (s *Server) ServeGateAuth(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if s.isDebug() {
|
||||
s.logger.Printf("[DEBUG] [web] setup gate %s: %s %s without a pass — 401", app, method, uri)
|
||||
s.logger.Printf("[DEBUG] [web] setup gate %s: %s %s without a pass — 401 (visitor %s)", app, method, uri, clientIP(r))
|
||||
}
|
||||
gateRefuse(w, http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user