8G for nginxrules v1.5runs in your browser

8G Firewall Rule Finder

Paste an 8G log line to see the rule that fired, its exact pattern, and the text it matched. On GridPane, run 8G in watch mode beside 7G first, so you find the false positives before 8G blocks anything.

8g.logexample.com

2026-10-21T14:02:11+00:00 200 "GET /pricing/" cookie=0 method=0 referer=0 bot=3 querystring=0 request=0 ip=203.0.113.20 ua="Mozilla/5.0 (compatible; AhrefsSiteAudit/6.1; +http://ahrefs.com/robot/site-audit)"

bot 3User agent rules

Matched Ahrefs in the user agent. Ahrefs Site Audit checks your site for SEO problems: likely one you want.

8g-firewall.confline 130
map $http_user_agent $bad_bot_ng {
    "~*ahrefs|archiver|curl|libwww-perl|pycurl|scan" 3;
}
8g.logempty

On GridPane it is /var/www/<site>/logs/8g.log. A line from any access log works too.

How it works

From a log line to the exact rule in three steps

  1. Copy the line

    8G logs every request it blocks, or in watch mode would block, with the rule that fired. A line from any nginx or Apache access log works too. For the latest from one site:

    tail /var/www/<site>/logs/8g.log
  2. See the rule

    You get the group and number, such as bot=3, its pattern, the text it matched, and any other rule in that group that matches too.

  3. Decide

    An attack, or something you want? For something you want, you get the documented way to let it through for now, and what it costs.

7G to 8G on GridPane

Run 8G beside 7G first, then switch

GridPane has no 8G switch: its 7G toggle is GridPane’s own build of 7G. On its nginx you run nG-SetEnvIf (opens in a new tab), the nginx version of 8G. Watch mode lets 8G log what it would block for a week or two while 7G keeps protecting the site.

  • Watch

    safe on a live site

    8G checks every request and logs what it would block. It blocks nothing, and 7G stays on.

    It can’t see static files, which GridPane doesn’t log, or anything 7G blocks first. So the log shows what 8G would add on top of 7G.

  • Enforce

    staging first

    8G blocks, with a 403, or a 405 for a method it refuses. Turn 7G off for that site once 8G is on.

    Jeff Starr’s advice is to run 7G or 8G on a site, not both.

  1. Check the server

    Read-only. It confirms nginx (not OpenLiteSpeed), that GridPane loads the site’s own config files, and that nginx records the visitor’s real address behind Cloudflare.

    Show the commands
    step 0: check
    SITE=example.com
    nginx -v
    ls /var/www/$SITE/nginx/
    nginx -T 2>/dev/null | grep -nE "/var/www/$SITE/nginx/\*-(http|main)-context\.conf"
    nginx -T 2>/dev/null | grep -E '^\s*real_ip_header' | sort -u; nginx -T 2>/dev/null | grep -cE '^\s*set_real_ip_from'
    nginx -T 2>/dev/null | grep -E '^\s*set_real_ip_from\s+(0\.0\.0\.0/0|::/0)\s*;'
  2. Download the rules

    Two files from nG-SetEnvIf, pinned to one commit of 8G v1.5, saved in an 8g folder inside the site’s nginx folder. Nothing loads them yet.

    Show the commands
    step 1: download
    SITE=example.com
    mkdir -p /var/www/$SITE/nginx/8g && cd /var/www/$SITE/nginx/8g
    NG=https://raw.githubusercontent.com/t18d/nG-SetEnvIf/344d9c417c02cf065d997059c7491100d0c96797
    curl -fsSLO "$NG/8g-firewall.conf" && curl -fsSLO "$NG/8g.conf"
    head -1 8g-firewall.conf    # 8G FIREWALL v1.5 20251006
  3. Turn on watch mode

    Two small files: one loads the rules and sets the log format, one checks each request and logs what 8G would block. If nginx -t fails, the step removes its own files and reloads nothing.

    Show the commands
    step 2: watch mode
    SITE=example.com
    D=/var/www/$SITE/nginx
    cat > $D/8g-http-context.conf <<'X'
    # 8G test (nG-SetEnvIf): loads the rules and defines this site's 8G log format.
    include /var/www/SITE_NAME/nginx/8g/8g-firewall.conf;
    
    log_format ng8_SITE_NAME '$time_iso8601 $status "$request_method $request_uri" '
        'cookie=$bad_cookie_ng method=$not_allowed_method_ng referer=$bad_referer_ng '
        'bot=$bad_bot_ng querystring=$bad_querystring_ng request=$bad_request_ng '
        'ip=$remote_addr ua="$http_user_agent" ref="$http_referer"';
    X
    cat > $D/8g-watch-main-context.conf <<'X'
    # 8G watch mode: checks every request against 8G and logs what it would block. Blocks nothing.
    # The checks run here, before WordPress rewrites the address to /index.php.
    set $ng8_hit "";
    if ($bad_cookie_ng)         { set $ng8_hit 1; }
    if ($not_allowed_method_ng) { set $ng8_hit 1; }
    if ($bad_referer_ng)        { set $ng8_hit 1; }
    if ($bad_bot_ng)            { set $ng8_hit 1; }
    if ($bad_querystring_ng)    { set $ng8_hit 1; }
    if ($bad_request_ng)        { set $ng8_hit 1; }
    access_log /var/www/SITE_NAME/logs/8g.log ng8_SITE_NAME if=$ng8_hit;
    X
    sed -i "s|SITE_NAME|$SITE|g" $D/8g-http-context.conf $D/8g-watch-main-context.conf
    if nginx -t; then gp ngx reload; else rm $D/8g-http-context.conf $D/8g-watch-main-context.conf; echo "FAILED: files removed, nothing reloaded"; fi
  4. Check that it works

    A request with curl’s own user agent, which 7G allows and 8G would block, should land in the 8G log a few seconds later. The site still answers it normally.

    Show the commands
    step 3: check
    SITE=example.com
    curl -sk -o /dev/null -w '%{http_code}\n' --resolve $SITE:443:127.0.0.1 https://$SITE/   # 200 or 301: nothing blocked
    sleep 5
    grep 'curl/' /var/www/$SITE/logs/8g.log | tail -n 1        # a line with bot=3 and ua="curl/..."
    grep 'curl/' /var/log/nginx/$SITE.access.log | tail -n 1   # the site's normal log has it too
  5. Read the log for a week or two

    Count which rules fire, then paste the lines into 8G Helper above. Each one is an attack, or a person, plugin or service you want. Every “want” is a false positive to fix before you enforce.

    Show the commands
    step 4: read the log
    SITE=example.com
    # which rules fire, most first
    grep -oE '(cookie|method|referer|bot|querystring|request)=[1-9][0-9]*' /var/www/$SITE/logs/8g.log | sort | uniq -c | sort -rn
    tail -n 30 /var/www/$SITE/logs/8g.log
    # show one rule's pattern, e.g. querystring=39
    rule() { sed -n "/\$bad_$1_ng {/,/^}/p; /\$not_allowed_$1_ng {/,/^}/p" /var/www/$SITE/nginx/8g/8g-firewall.conf | grep -E " $2;\$"; }
    rule querystring 39
  6. Enforce, on staging first

    Swap the watch file for the enforce file, prove it blocks, then turn 7G off for that site in GridPane. Try everything a person does on the site, then move on to one low-risk live site.

    Show the commands
    step 5: enforce
    SITE=example.com
    D=/var/www/$SITE/nginx
    cat > $D/8g-main-context.conf <<'X'
    # 8G enforce mode (nG-SetEnvIf): blocks with 403, or 405 for a disallowed method.
    include /var/www/SITE_NAME/nginx/8g/8g.conf;
    access_log /var/www/SITE_NAME/logs/8g.log ng8_SITE_NAME if=$ng_reason;
    X
    sed -i "s|SITE_NAME|$SITE|g" $D/8g-main-context.conf
    mv $D/8g-watch-main-context.conf $D/8g-watch-main-context.conf.off
    if nginx -t; then gp ngx reload; else rm $D/8g-main-context.conf; mv $D/8g-watch-main-context.conf.off $D/8g-watch-main-context.conf; echo "FAILED: still in watch mode, nothing reloaded"; fi
    
    # a few seconds later
    SITE=example.com
    curl -sk -o /dev/null -w '%{http_code}\n' -A 'Mozilla/5.0' --resolve $SITE:443:127.0.0.1 https://$SITE/   # 200 or 301
    curl -sk -o /dev/null -w '%{http_code}\n' --resolve $SITE:443:127.0.0.1 https://$SITE/                   # 403
    tail -n 1 /var/www/$SITE/logs/8g.log    # status 403, bot=3
The rules are shared across the server

nginx keeps one set of 8G rules per server, so when two sites each have a copy, the copy loaded last applies to both. Keep every copy on a server identical, and never edit one site’s copy alone.

What the logs showed on real sites

  • Crawlers, more than attacks. On real sites most of what 8G would add came from search and AI crawlers in its bot rules. Those rules are a choice about which crawlers you want, not attack signatures.
  • Your own tools. bot rule 3 blocks curl, scan and ahrefs: uptime monitors, cron jobs, a payment provider’s security scanner, Ahrefs Site Audit, and your own tests.
  • Site search. querystring rule 39 blocks searches containing words such as get, select or delete between other words.
  • AI agents that sign in. querystring rule 9 blocks localhost in a query string, which OAuth sign-ins for MCP connectors send. Don’t enforce on a site an agent connects to without an exception.
  • The real catch. Probes for shells, backups and config files that 7G let through, nearly all answered 404 already.
Undo: take 8G off a site
undo
SITE=example.com
rm -r /var/www/$SITE/nginx/8g /var/www/$SITE/nginx/8g-* && nginx -t && gp ngx reload

What 8G checks

Six rule groups, each reading one part of the request

nginx reads each group as a list and stops at the first pattern that matches, so the log names one rule per group. 8G Helper checks the whole list, so a second match can’t surprise you after the first is fixed.

  • Query string

    41 rules

    $query_string$bad_querystring_ng

    Injection after the ?: SQL keywords, script tags, file paths, encoded slashes. Read exactly as sent.

    Often blocks by mistake: Site searches with words like get or select, and OAuth sign-ins that send localhost.

  • Request path

    57 rules

    $uri$bad_request_ng

    Paths scanners try: shells, backups, config files, odd characters. Read decoded, without the query string.

    Often blocks by mistake: A real page whose address looks like one, such as /backup/.

  • User agent

    14 rules

    $http_user_agent$bad_bot_ng

    Scanner and script names, fake browser names, and some crawlers.

    Often blocks by mistake: Crawlers you want, uptime monitors and curl, a payment provider’s security scanner.

  • Referrer

    4 rules

    $http_referer$bad_referer_ng

    Spam and injection in the referring address.

    Often blocks by mistake: Rare.

  • Cookie

    1 rule

    $http_cookie$bad_cookie_ng

    Injection hidden in a cookie.

    Often blocks by mistake: Rare. The log names the rule but never records the cookie itself.

  • Method

    1 rule

    $request_method$not_allowed_method_ng

    Methods a WordPress site never needs, such as TRACE and CONNECT.

    Often blocks by mistake: Almost never. It answers 405, and nginx refuses TRACE on its own first.

Questions

Before you change anything

Does the log line I paste leave my browser?

No. Matching runs in your browser against a bundled copy of 8G v1.5 from nG-SetEnvIf, and nothing you paste is sent or stored.

What is watch mode?

A way to try 8G on a live site without risk: 8G checks every request and logs what it would block, while 7G keeps blocking. It is two small files in the site’s own nginx folder. See 7G to 8G.

Why is there no exception file, like 7G Helper’s?

On GridPane, 7G reads update-safe exception files and has a switch for each rule group. 8G has neither yet, and its rules are one shared set per server. Until a scoped exception has been tested in enforce mode, 8G Helper gives the documented fix: comment out the rule, or remove the one word that matched, in every copy on the server.

Will a GridPane update remove 8G?

No. Everything lives in the site’s own nginx folder, which updates leave alone. Downloading a newer 8G replaces the rules, along with any line you commented out, so redo those edits after.

A request got a 403, but no 8G rule matches it.

Then 8G did not block it. A 403 can also come from 7G, Cloudflare, Fail2Ban or a security plugin. In watch mode, 7G runs first, so anything it blocks never reaches the 8G log.

Is this made by GridPane, or by the author of 8G?

No. 8G is Jeff Starr’s firewall, published at Perishable Press (opens in a new tab). nG-SetEnvIf, the nginx version, is by Tonkünstler-on-the-Bund. 8G Helper is an independent tool, so check each change before you make it.

What about Apache?

Jeff’s official 8G is for Apache. An Apache version of this tool comes next, tested against real Apache before it ships.