create a golang reverse proxy? I have a JS challenge and how I would like to use it (as in the URL), I just dont know how to do it.

Mitigation methods:
UA checks: if theres a sudden increase in specific flagged UAs (containing X11), start to do custom challenges on these.
Append a script tag to every response returned, if an IP does 2 requests and never accesses our script, block it.
If an IP changes UA 2 times within 20s~, block it.

Here is all i have:

Mitigation methods:
UA checks: if theres a sudden increase in specific flagged UAs (containing X11), start to do custom challenges on these.
Append a script tag to every response returned, if an IP does 2 requests and never accesses our script, block it.
If an IP changes UA 2 times within 20s~, block it.

all of this will be done by returning a blank page where it would add a script tag for a .js script which will not load anything, it would just be a check on the server to see if the user loaded that .js script correctly.

It would also add headless browser mitigation methods:

navigator.webdriver
WebGL Canvas Fingerprinting
Plugins/MimeTYPEs
Audio Context
Screen Size/Res
Font Checker
Empty language
Code Snippet below
Click function tampering
window.chrome && window.chrome.webstore

```
<script>
const detectBot = () => {
            var isBot = false;
            const isFunctionTampered = fn => fn.toString().includes('[native code]') === false;
            var e = new Error();
            Object.defineProperty(e, "stack", {
                get() {
                    isBot = true;
                    alert("Detected: Tampered stack trace");
                }
            });
            if (window.chrome && chrome.loadTimes && !chrome.csi) {
                isBot = true;
                alert("Detected: Chrome load times present");
            }
            if (console.debug.toString().includes("puppeteer")) {
                isBot = true;
                alert("Detected: Puppeteer in console.debug");
            }
            if (window.__nightmare || window.__puppeteer_evaluation_script) {
                isBot = true;
                alert("Detected: Nightmare or Puppeteer evaluation script present");
            }
            if (window.open.toString().indexOf("native code") === -1) {
                isBot = true;
                alert("Detected: window.open has been tampered");
            }
            const _0x5aa80b = Function.prototype.toString;
            Function.prototype.toString = function () {
                if (this === _0x5aa80b) {
                    isBot = true;
                    alert("Detected: Bad Browser - Function.prototype.toString modified");
                    return "Bad Browser";
                }
                return _0x5aa80b.apply(this, arguments);
            };
            if ("__nightmare" in window || "__puppeteer" in window || "__chrome" in window) {
                isBot = true;
                alert("Detected: Nightmare, Puppeteer, or Chrome object present");
            }
            if (navigator.webdriver) {
                isBot = true;
                alert("Detected: WebDriver is active");
            }
            // Needs to ignore WebDriver on Edge UserAgents (they use it?? should be updated each time it updates, only support the latest version bypass // further challenge unupdated clients)
            const canvas = document.createElement("canvas");
            var gl = canvas.getContext("webgl");
            if (!gl) {
                isBot = true;
                alert("Detected: WebGL context not available");
            }

            const gldbg = gl.getExtension("WEBGL_debug_render_info");
            if (gldbg) {
                var renderer = gl.getParameter(gldbg.UNMASKED_RENDERER_WEBGL);
                if (renderer.toLowerCase().includes("swiftshader")) {
                    isBot = true;
                    alert("Detected: SwiftShader renderer in use");
                }
            }
            if (!window.AudioContext || !navigator.mediaDevices) {
                isBot = true;
                alert("Detected: Missing AudioContext or media devices");
            }
            if (window.outerWidth === 0 || window.outerHeight === 0) {
                isBot = true;
                alert("Detected: Window dimensions are zero");
            }
            if (navigator.languages === "") {
                isBot = true;
                alert("Detected: No languages present");
            }
            if (isFunctionTampered(HTMLElement.prototype.click)) {
                isBot = true;
                alert("Detected: HTMLElement.prototype.click has been tampered");
            }
            if (window.chrome && window.chrome.webstore) {
                isBot = true;
                alert("Detected: Chrome Web Store is accessible");
            }

            return isBot;
        }

        window.onload = () => {
            const isBot = detectBot();
            if (isBot) {
                alert("Bot Detected");
                document.body.innerHTML = "<h1>Bot Detected</h1>";
            } else {
                alert("No Bot Detected");
                document.body.innerHTML = "<h1>No Bot Detected</h1>";
            }
        }
    </script>
```

(Not complete)

Status Codes
Return Code 0 (Server Side)
Will hard block any requests.
Why does this occur:
Blacklists

Return Code 0 (Client Side)
Error occured regarding upstream.
Why does this occur:
Upstream is invalid
Upstream is offline/unreachable

Return Code 1 (Server Side)
Will pass any requests.
Why does this occur:
Passes all checks

Return Code 429 (Server/Client Side)
Will return a ratelimit message.
Why does this occur:
Is over the ratelimit set in config.json for the zone

Return Code 502 (Server/Client Side)
Will return bad gateway.
Why does this occur:
Domain is not setup in config.json
Domain is not configured properly

Return Code 1000 (Server Side)
JS challenge embedded in webpage
Why does this occur:
Unused

Return Code 1001 (Server Side)
JS challenge before hitting backend
Why does this occur:
Flagged User Agent
User Agent has changed >3 times in

this only works as async:
```
package main

import (
    "fmt"
    "log"
    "strings"
    "time"

    "github.com/valyala/fasthttp"
)

var (
    targetHost = "example.com:80"

    client = &fasthttp.HostClient{
        Addr:                          targetHost,
        MaxConns:                      1024,
        ReadTimeout:                   10 * time.Second,
        WriteTimeout:                  10 * time.Second,
        DisableHeaderNamesNormalizing: true,
    }
)

func ProxyHandler(ctx *fasthttp.RequestCtx) {
    req := new(fasthttp.Request)
    resp := new(fasthttp.Response)

    ctx.Request.CopyTo(req)

    req.SetHost(strings.Split(targetHost, ":")[0])

    err := client.Do(req, resp)
    if err != nil {
        ctx.Error(fmt.Sprintf("Error: %v", err), fasthttp.StatusBadGateway)
        log.Printf("Error forwarding request: %v", err)
        return
    }

    resp.CopyTo(&ctx.Response)
}

func main() {
    log.Println("Starting reverse proxy server on :8080...")

    err := fasthttp.ListenAndServe(":8080", ProxyHandler)
    if err != nil {
        log.Fatalf("Error in ListenAndServe: %v", err)
    }
}
```

utils.go:

```
package firewall

import (
    "strings"
    "sync/atomic"
)

func containsUA(userAgent, flaggedUA string) bool {
    return strings.Contains(userAgent, flaggedUA)
}

func (f *Firewall) resetFlaggedUACount(tracker *requestTracker, flaggedUA string) {
    tracker.mu.Lock()
    defer tracker.mu.Unlock()
    
    atomic.StoreInt64(tracker.flaggedUACount[flaggedUA], 0)
    delete(tracker.uaResetTimers, flaggedUA)
}

func (f *Firewall) resetRequestCount(tracker *requestTracker, ip string) {
    tracker.mu.Lock()
    defer tracker.mu.Unlock()
    
    atomic.StoreInt64(tracker.requestCount[ip], 0)
    delete(tracker.resetTimers, ip)
}

func (f *Firewall) uaChangeStage(tracker *requestTracker, ip string, currentUA string, uaChangeLimit int64) int {
    previousUA, exists := tracker.previousUserAgent[ip]

    if !exists {
        tracker.previousUserAgent[ip] = currentUA
        return 1
    }

    if previousUA != currentUA {
        uaChangeCount := atomic.AddInt64(tracker.requestCount[ip], 1)
        log.Printf("UA change detected for %v: prev: %v, curr: %v, cc: %v", ip, previousUA, currentUA, uaChangeCount)

        if uaChangeCount > uaChangeLimit && uaChangeLimit != 0 {
            return 1003
        }

        tracker.previousUserAgent[ip] = currentUA
    }
    return 1
}
```

```
// Has passed all checks but it is not in the whitelist, do the embedded JS challenge (BotDetection.html).
if tracker.challengeFailures[ip] >= backend.challengeFailure {
    tracker.blacklist[ip] = time.Now().Add(tracker.blacklistDuration)
    log.Printf("IP %s has been blacklisted for exceeding challenge limit", ip)
    return 403
}
tracker.challengeFailures[ip]++
return 1001
```

this stops intrusive browser methods because this loads script directly:
```
if filter == 1001 {
        contentType := resp.Header.Peek("Content-Type")
        if strings.Contains(string(contentType), "text/html") {
            challengeID := challenge.CreateUniqueChallengeID(ctx, cloudflare)
            challengeScript := `<script src="/rproxy/` + challengeID + `.js"></script>`
            body := resp.Body()
            modifiedBody := strings.ReplaceAll(string(body), "</body>", challengeScript+"</body>")

            ctx.SetStatusCode(resp.StatusCode())
            resp.Header.VisitAll(func(k, v []byte) {
                ctx.Response.Header.Set(string(k), string(v))
            })
            ctx.SetBodyString(modifiedBody)
            logger.AddEntry(logger.AccessLog{Action: "Invisible Challenge", SourceIP: ip, Timestamp: time.Now(), UserAgent: string(ctx.Request.Header.Peek("User-Agent")), Referer: string(ctx.Request.Header.Peek("Referer")), Host: string(ctx.Request.Host()), Path: string(ctx.Request.URI().String())})
        } else {
            ctx.SetBody(resp.Body())
        }
        return
    }
```