package main import ( "bytes" "context" "io" "log" "net" "net/http" "os" "strconv" "strings" "github.com/redis/go-redis/v9" ) var ( ctx = context.Background() redisClient *redis.Client hashName = "bl:manual" blocklistMode string masterURL string ) func main() { // Modus und Master-URL aus ENV blocklistMode = os.Getenv("BLOCKLIST_MODE") hashName = os.Getenv("HASH_NAME") if hashName == "" { hashName = "bl:manual" } //DEBUG //blocklistMode = "master" //DEBUG if blocklistMode != "master" && blocklistMode != "slave" { log.Fatal("❌ BLOCKLIST_MODE has to be 'master' or 'slave'") } else { log.Println("✅ BLOCKLIST_MODE set to:", blocklistMode) } if blocklistMode == "slave" { masterURL = os.Getenv("MASTER_URL") log.Println("✅ MASTER_URL set to:", masterURL) //DEBUG //masterURL = "http://127.0.0.1:8081" //DEBUG if masterURL == "" { log.Fatal("❌ MASTER_URL has to be set in slave mode") } } if blocklistMode == "master" { // Redis initialisieren redisAddr := os.Getenv("REDIS_ADDR") if redisAddr == "" { redisAddr = "localhost:6379" } log.Println("✅ Redis Connection set to:", redisAddr) redisClient = redis.NewClient(&redis.Options{ Addr: redisAddr, Password: "", DB: 0, }) if err := redisClient.Ping(ctx).Err(); err != nil { log.Fatalf("❌ No connection to redis-server: %v", err) } } /* TCP- and UDP-Honeypods */ portsTCP := []string{"135", "139", "445", "389", "636", "3268", "3269", "88", "3389", "3306", "27017", "5432", "25", "123", "5900"} for _, port := range portsTCP { go startTCPListener(port) } portsUDP := []string{"135", "137", "138", "389", "3389", "88"} for _, port := range portsUDP { go startTCPListener(port) } // Endpunkte registrieren http.HandleFunc("/", handleRoot) http.HandleFunc("/add", handleAdd) log.Println("✅ Server running in mode:", blocklistMode) log.Println("🚀 Server listening at :8080") if err := http.ListenAndServe(":8080", nil); err != nil { log.Fatal("⚠️ ListenAndServe: ", err) } } func handleRoot(w http.ResponseWriter, r *http.Request) { ip := getClientIP(r) if ip == "" { http.Error(w, "Wrong IP", http.StatusBadRequest) return } processIP(ip, w) } func handleAdd(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil || len(body) == 0 { http.Error(w, "Wrong Body", http.StatusBadRequest) return } ip := strings.TrimSpace(string(body)) if !isValidIP(ip) { http.Error(w, "Wrong IP", http.StatusBadRequest) return } processIP(ip, w) } func startTCPListener(port string) { ln, err := net.Listen("tcp", ":"+port) if err != nil { log.Fatalf("❌ Could not listen on TCP port %s: %v", port, err) } log.Printf("🚀 TCP Honeypod listening on port %s", port) for { conn, err := ln.Accept() if err != nil { log.Printf("⚠️ Error accepting TCP connection: %v", err) continue } go handleTCPConn(conn) } } func handleTCPConn(conn net.Conn) { defer conn.Close() ip, _, err := net.SplitHostPort(conn.RemoteAddr().String()) if err != nil { log.Printf("⚠️ Could not parse remote address: %v", err) return } log.Printf("👀 TCP connection from %s", ip) processIP(ip, nil) // Anpassung nötig: processIP muss nil w als Option haben } func startUDPListener(port string) { addr := net.UDPAddr{ Port: portInt(port), IP: net.ParseIP("0.0.0.0"), } conn, err := net.ListenUDP("udp", &addr) if err != nil { log.Fatalf("❌ Could not listen on UDP port %s: %v", port, err) } log.Printf("🚀 UDP Honeypod listening on port %s", port) buf := make([]byte, 1024) for { n, remoteAddr, err := conn.ReadFromUDP(buf) if err != nil { log.Printf("⚠️ Error reading UDP packet: %v", err) continue } if n > 0 { ip := remoteAddr.IP.String() log.Printf("👀 UDP packet from %s", ip) processIP(ip, nil) // ebenfalls anpassen } } } func portInt(port string) int { p, _ := strconv.Atoi(port) return p } 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("❌ Error writing to redis: %v", err) if w != nil { http.Error(w, "Interner Fehler", http.StatusInternalServerError) } return } log.Printf("✅ IP %s in saved to redis", ipKey) if w != nil { w.WriteHeader(http.StatusServiceUnavailable) w.Write([]byte("Temporary unavailable")) } } else { // Slave: an Master weiterleiten resp, err := http.Post(masterURL+"/add", "text/plain", bytes.NewBuffer([]byte(ip))) if err != nil { log.Printf("❌ Error relaying to Master: %v", err) if w != nil { http.Error(w, "Error relaying", http.StatusBadGateway) } return } defer resp.Body.Close() if w != nil { w.WriteHeader(resp.StatusCode) io.Copy(w, resp.Body) } } } func getClientIP(r *http.Request) string { xff := r.Header.Get("X-Forwarded-For") if xff != "" { parts := strings.Split(xff, ",") ip := strings.TrimSpace(parts[0]) if isValidIP(ip) { return ip } } xrip := r.Header.Get("X-Real-Ip") if xrip != "" && isValidIP(xrip) { return xrip } host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { return "" } if isValidIP(host) { return host } return "" } func isValidIP(ip string) bool { return net.ParseIP(ip) != nil }