Files
Kontrollverlust/middleware.go
T
2026-06-23 18:26:51 +02:00

66 lines
1.9 KiB
Go

package main
import (
"context"
"log"
"net"
"net/http"
)
type ctxKey string
const uidKey ctxKey = "uid"
// torNet ist das interne Netz, über das TOR-Anfragen beim Backend ankommen:
// der Onion-Hidden-Service reicht über einen lokalen Proxy weiter, eine echte
// Client-IP gibt es dabei nicht -> die Anfragen erscheinen mit einer IP aus
// diesem Netz (siehe Impression-Log: 10.89.0.0). Beiträge von dort werden
// vorerst komplett abgewiesen; eine Moderations-/Freigabeseite kommt später.
// Per KVER_TOR_NET (CIDR) konfigurierbar; leer schaltet die Sperre ab.
var torNet *net.IPNet
func init() {
cidr := envOr("KVER_TOR_NET", "10.89.0.0/16")
if cidr == "" {
return
}
if _, n, err := net.ParseCIDR(cidr); err == nil {
torNet = n
} else {
log.Printf("KVER_TOR_NET ignoriert (ungültiges CIDR %q): %v", cidr, err)
}
}
// blockTOR weist Anfragen aus dem TOR-Netz ab (siehe torNet). Die volle IP wird
// hier nur für diese Zugriffsentscheidung geprüft, nicht gespeichert oder
// geloggt. Ist kein Netz konfiguriert, ist die Middleware ein No-op.
func blockTOR(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if torNet != nil {
if ip := clientIP(r.RemoteAddr); ip != nil && torNet.Contains(ip) {
writeError(w, http.StatusForbidden, "Beiträge über TOR sind derzeit nicht möglich.")
return
}
}
next.ServeHTTP(w, r)
})
}
// requireAuth lehnt Anfragen ohne gültige Session ab und legt die uid in den Context.
func requireAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s, ok := getSession(r)
if !ok {
writeError(w, http.StatusUnauthorized, "Nicht angemeldet")
return
}
ctx := context.WithValue(r.Context(), uidKey, s.UID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func uidFromContext(ctx context.Context) int64 {
uid, _ := ctx.Value(uidKey).(int64)
return uid
}