diff --git a/main.go b/main.go index 3e467f2..b77f32e 100644 --- a/main.go +++ b/main.go @@ -1,67 +1,120 @@ package main import ( + "bytes" "context" + "io" "log" "net" "net/http" + "os" "strings" "github.com/redis/go-redis/v9" ) var ( - ctx = context.Background() - redisClient *redis.Client - hashName = "bl:sendnrw" + ctx = context.Background() + redisClient *redis.Client + hashName = "bl:cat" + blocklistMode string + masterURL string ) func main() { - // Redis Client initialisieren - redisClient = redis.NewClient(&redis.Options{ - Addr: "10.10.5.249:6379", // ggf. anpassen - Password: "", // falls Passwort benötigt wird - DB: 0, // Standard DB - }) - - // Testverbindung - if err := redisClient.Ping(ctx).Err(); err != nil { - log.Fatalf("Keine Verbindung zu Redis: %v", err) + // Modus und Master-URL aus ENV + blocklistMode = os.Getenv("BLOCKLIST_MODE") + if blocklistMode != "master" && blocklistMode != "slave" { + log.Fatal("BLOCKLIST_MODE muss 'master' oder 'slave' sein") } - http.HandleFunc("/", logIPHandler) + if blocklistMode == "slave" { + masterURL = os.Getenv("MASTER_URL") + if masterURL == "" { + log.Fatal("MASTER_URL muss gesetzt sein im slave Modus") + } + } - log.Println("Server startet auf :8082") - if err := http.ListenAndServe(":8082", nil); err != nil { + if blocklistMode == "master" { + // Redis initialisieren + redisAddr := os.Getenv("REDIS_ADDR") + if redisAddr == "" { + redisAddr = "localhost:6379" + } + redisClient = redis.NewClient(&redis.Options{ + Addr: redisAddr, + Password: "", + DB: 0, + }) + if err := redisClient.Ping(ctx).Err(); err != nil { + log.Fatalf("Keine Verbindung zu Redis: %v", err) + } + } + + // Endpunkte registrieren + http.HandleFunc("/", handleRoot) + http.HandleFunc("/add", handleAdd) + + log.Println("Server läuft im Modus:", blocklistMode) + log.Println("Server startet auf :8080") + if err := http.ListenAndServe(":8080", nil); err != nil { log.Fatal("ListenAndServe: ", err) } } -func logIPHandler(w http.ResponseWriter, r *http.Request) { +func handleRoot(w http.ResponseWriter, r *http.Request) { ip := getClientIP(r) if ip == "" { http.Error(w, "Ungültige IP", http.StatusBadRequest) return } - ipKey := ip + "/32" + processIP(ip, w) +} - // IP in Redis Hash speichern - err := redisClient.HSet(ctx, hashName, ipKey, 1).Err() - if err != nil { - log.Printf("Fehler beim Schreiben in Redis: %v", err) - http.Error(w, "Interner Fehler", http.StatusInternalServerError) +func handleAdd(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil || len(body) == 0 { + http.Error(w, "Ungültiger Body", http.StatusBadRequest) + return + } + ip := strings.TrimSpace(string(body)) + if !isValidIP(ip) { + http.Error(w, "Ungültige IP", http.StatusBadRequest) return } - log.Printf("IP %s in Redis gespeichert", ipKey) + processIP(ip, w) +} - w.WriteHeader(http.StatusOK) - w.Write([]byte("IP erfasst: " + ipKey + "\n")) +func processIP(ip string, w http.ResponseWriter) { + ipKey := ip + "/32" + + if blocklistMode == "master" { + err := redisClient.HSet(ctx, hashName, ipKey, 1).Err() + if err != nil { + log.Printf("Fehler beim Schreiben in Redis: %v", err) + http.Error(w, "Interner Fehler", http.StatusInternalServerError) + return + } + log.Printf("IP %s in Redis gespeichert", ipKey) + w.WriteHeader(http.StatusOK) + w.Write([]byte("IP gespeichert: " + ipKey + "\n")) + } else { + // Slave: an Master weiterleiten + resp, err := http.Post(masterURL+"/add", "text/plain", bytes.NewBuffer([]byte(ip))) + if err != nil { + log.Printf("Fehler beim Weiterleiten an Master: %v", err) + http.Error(w, "Fehler beim Weiterleiten", http.StatusBadGateway) + return + } + defer resp.Body.Close() + w.WriteHeader(resp.StatusCode) + io.Copy(w, resp.Body) + } } func getClientIP(r *http.Request) string { - // X-Forwarded-For prüfen xff := r.Header.Get("X-Forwarded-For") if xff != "" { parts := strings.Split(xff, ",") @@ -71,13 +124,11 @@ func getClientIP(r *http.Request) string { } } - // X-Real-IP prüfen xrip := r.Header.Get("X-Real-Ip") if xrip != "" && isValidIP(xrip) { return xrip } - // RemoteAddr als Fallback host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { return ""