An Nginx implementation of the 8G Firewall by Perishable Press. This provides robust, server-level protection against common web attacks and malicious traffic.
nginx-8g-firewall/
├── nginx/
│ ├── snippets/
│ │ ├── firewall.conf ← RECOMMENDED: map-based version, include in http {} block
│ │ └── 8G_firewall.conf ← ALTERNATIVE: if-based version, include in server {} block
│ └── nginx.conf ← Example nginx.conf reference configuration
├── apache/
│ ├── 8g_firewall.txt ← Original Apache .htaccess source (reference only)
│ └── 8G-Changelog.txt ← Upstream changelog
├── install.sh ← Automated installation script
├── QUICKSTART.md ← 5-minute setup guide
└── README.md ← This file
| File | Include location | Approach | Best for |
|---|---|---|---|
nginx/snippets/firewall.conf |
http {} block |
map/geo directives |
Most deployments (recommended) |
nginx/snippets/8G_firewall.conf |
server {} block |
if/set directives |
Simple setups or per-vhost inclusion |
nginx/snippets/firewall.conf (recommended) uses Nginx's map and geo directives to define detection rules and a combined $block_all variable. Because map and geo are evaluated lazily and at the http level, this version performs better under load and is easier to extend. Rate-limiting zones and security headers are also defined in this file.
nginx/snippets/8G_firewall.conf (alternative) is a more direct port of the original Apache rules using sequential if blocks. It is self-contained and can be included directly inside any server {} block — useful if you only want to protect specific virtual hosts or prefer keeping all rules local to the server context.
This file is a lossless-style functional translation of the original 8G Firewall v1.5 (Apache) by Perishable Press into NGINX syntax.
The 8G Firewall protects against:
- SQL Injection (SQLi) - Blocks common SQL injection patterns
- Cross-Site Scripting (XSS) - Prevents JavaScript injection attempts
- Remote Code Execution (RCE) - Stops shell command injection
- Directory Traversal - Blocks attempts to access sensitive files
- Bad Bots & Scanners - Identifies and blocks malicious user agents
- Spam Referrers - Filters suspicious referrer domains
- Dangerous HTTP Methods - Blocks TRACE, TRACK, and other risky methods
- Rate Limiting - Prevents brute force and DoS attacks
- Security Headers - Adds modern security headers to responses The goal of this version is to preserve the spirit, detection logic, and protection coverage of the original Apache implementation while adapting it to the architectural and performance characteristics of NGINX.
This version maintains:
- Query string attack detection
- Malicious URI filtering
- User-Agent exploit detection
- Referrer spam & exploit filtering
- Cookie injection protection
- Dangerous HTTP method blocking
The rule logic is intentionally kept close to the original Apache version to ensure behavioral parity, not redesign.
Original Apache version:
8G Firewall v1.5
https://perishablepress.com/8g-firewall/
This NGINX version was created from that reference to preserve equivalent protections in NGINX environments.
Because Apache and NGINX operate differently internally, some adjustments were necessary.
Apache uses mod_rewrite with sequential conditional evaluation.
NGINX does not behave the same way, so rules are grouped using variables and conditional checks.
The protection coverage remains equivalent, but execution flow differs.
Apache can block based on REMOTE_HOST using reverse DNS lookups.
NGINX cannot do this efficiently without enabling:
This drops malicious connections without responding, reducing noise and scan feedback.
This is recommended but optional depending on logging and monitoring preferences.
his causes major performance degradation and is intentionally disabled in this version.
Apache evaluates many sequential rewrite conditions.
NGINX performs better when patterns are grouped, so regex rules are consolidated to reduce processing overhead while maintaining detection coverage.
The original 8G blocks all curl.
This version blocks only malicious curl usage (scanner/exploit patterns), allowing legitimate curl usage for APIs, health checks, and automation.
By default, 8G returns HTTP 403.
NGINX supports a stealth option:
return 444;
This drops malicious connections without responding, reducing noise and scan feedback. This is recommended but optional depending on logging and monitoring preferences.
Because this firewall relies heavily on regex evaluation, enabling PCRE JIT significantly improves performance.
Add to your main nginx.conf:
pcre_jit on;
Benefits:
-
Faster regex execution
-
Lower CPU usage under attack
-
Better throughput under load
Compared to Apache 8G:
| Metric | Apache | This NGINX Version |
|---|---|---|
| CPU Usage | Higher | Lower |
| Throughput | Lower | Higher |
| Regex Performance | Moderate | Faster (with PCRE JIT) |
| Attack Handling | Strong | Stronger |
| Memory Usage | Higher | Lower |
This firewall is intended to be included in the http {} block (recommended firewall.conf):
include /etc/nginx/snippets/8g-firewall.conf;
Or, for the if-based alternative, inside a server {} block:
include /etc/nginx/snippets/8G_firewall.conf;
Ensure the http {}-level include loads before your server {} blocks, and the server {}-level include loads after basic server directives but before application routing.
-
With
403, blocked requests appear in access/error logs. -
With
444, connections are dropped silently (reduced log noise).
Choose based on operational preference.
This file is designed as a behaviorally faithful conversion, not a redesign.
Because Apache and NGINX differ fundamentally:
-
Execution order is adapted
-
Reverse DNS blocking is disabled
-
Rewrite chaining is approximated
Despite these differences, attack detection coverage matches the original 8G Firewall.
This version intentionally preserves original structure.
Possible future optimizations include:
-
Replacing
ifwithmapfor higher performance -
Precompiled detection tables
-
Adaptive rate/connection blocking
-
Dynamic intelligence-based filtering
-
Modular NGINX-native firewall architecture
Clone this repository:
git clone https://github.com/MaximillianGroup/nginx-8g-firewall.git
cd nginx-8g-firewallsudo mkdir -p /etc/nginx/snippets
sudo cp nginx/snippets/firewall.conf /etc/nginx/snippets/8g-firewall.confNote: If you prefer the
if-based alternative, copynginx/snippets/8G_firewall.confto/etc/nginx/snippets/8G_firewall.confinstead and include it inside yourserver {}block (see Option B in step 3).
Option A — Recommended (firewall.conf, map-based):
Add the following line to your nginx.conf file inside the http {} block:
http {
# ... other configurations ...
# Include 8G Firewall (map-based — must be in http {} block)
include /etc/nginx/snippets/8g-firewall.conf;
# ... rest of your configuration ...
}Option B — Alternative (8G_firewall.conf, if-based):
Include the file directly inside your server {} block:
server {
listen 443 ssl;
server_name example.com;
# Include 8G Firewall (if-based — included per server block)
include /etc/nginx/snippets/8G_firewall.conf;
location / { ... }
}Option B users: skip this step.
8G_firewall.confis self-contained — it uses internalif/returnblocks and issuesreturn 403;directly. Once theincludeis inside yourserver {}block (step 3 Option B), no additional activation directives are needed.
For Option A (firewall.conf, map-based), add the blocking logic to your server blocks. The variables $block_all, $bad_bot, $block_referer, and the limit_req/limit_conn zones are all defined by firewall.conf in the http {} context:
server {
listen 443 ssl http2;
server_name example.com;
# Apply rate limiting (zones defined in firewall.conf / 8g-firewall.conf)
limit_conn 8g_conn 20;
limit_req zone=8g_global burst=50 nodelay;
# Block malicious requests (variable set by firewall.conf / 8g-firewall.conf)
if ($block_all) {
return 444; # Close connection without response
}
# Optional: Block bad bots explicitly
if ($bad_bot = 1) {
return 444;
}
# Optional: Block bad referers with 403
if ($block_referer = 1) {
return 403;
}
# Your normal location blocks
location / {
root /var/www/html;
index index.html;
}
}Before reloading Nginx, test the configuration:
sudo nginx -tIf the test is successful, reload Nginx:
sudo systemctl reload nginxAdd stricter rate limiting for WordPress login pages:
location = /wp-login.php {
limit_req zone=8g_login burst=3 nodelay;
fastcgi_pass unix:/run/php-fpm/www.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}location ^~ /admin/ {
# Require authentication
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# Apply firewall rules
if ($block_all) {
return 444;
}
# Your PHP or proxy configuration
try_files $uri $uri/ /admin/index.php?$query_string;
}Add your own IP blocks in the installed /etc/nginx/snippets/8g-firewall.conf file (copied from firewall.conf in this repository), in the geo $blocked_ip section:
geo $blocked_ip {
default 0;
# Block specific IPs or ranges
192.0.2.123 1;
203.0.113.0/24 1;
}The firewall creates three rate limiting zones:
8g_global- 10 requests/second per IP (global baseline)8g_login- 2 requests/second per IP (for login pages)8g_conn- Connection limit per IP
Adjust these in nginx/snippets/firewall.conf (or /etc/nginx/snippets/8g-firewall.conf if you have already installed the snippet) if needed:
limit_req_zone $binary_remote_addr zone=8g_global:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=8g_login:10m rate=2r/s;Logging of blocked requests is disabled by default. To enable logging, uncomment the following line in nginx/snippets/firewall.conf (or /etc/nginx/snippets/8g-firewall.conf if you have already installed the snippet):
# Remove the leading "#" from this line:
access_log /var/log/nginx/8g-blocked.log blocked_8g if=$block_all;Security headers are enabled by default. To customize, edit the headers section in nginx/snippets/firewall.conf (or /etc/nginx/snippets/8g-firewall.conf if you installed the snippet there):
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# ... customize as neededIf legitimate tools are being blocked, modify the $bad_bot map:
map $http_user_agent $bad_bot {
default 0;
# Comment out tools you want to allow
# "~*(?i)curl" 1; # Allow curl
"~*(?i)nikto" 1; # Still block nikto
}Create a whitelist before the firewall rules:
geo $whitelisted_ip {
default 0;
192.0.2.100 1; # Your trusted IP
}
# Then modify blocking logic
# Use a helper variable to avoid nested if-statements (not supported in Nginx)
set $block_request 0;
if ($block_all) {
set $block_request 1;
}
# Whitelisted IPs bypass the block
if ($whitelisted_ip) {
set $block_request 0;
}
if ($block_request) {
return 444;
}If legitimate requests are being blocked:
- Check
/var/log/nginx/8g-blocked.logto see what triggered the block - Review the specific map in
nginx/snippets/firewall.confthat caused the block - Adjust the regex patterns or comment out overly aggressive rules
Test specific patterns:
# Test for blocked user agent
curl -A "sqlmap" https://example.com
# Test for blocked query string
curl "https://example.com/?q=<script>alert(1)</script>"The 8G Firewall is lightweight and uses Nginx's efficient map and geo modules. Typical overhead is negligible (< 1ms per request).
- Original 8G Firewall: Jeff Starr @ Perishable Press
- Nginx Implementation: This repository
MIT License - See LICENSE file for details.
The 8G Firewall rules are based on the work by Jeff Starr (Perishable Press). Please maintain attribution when using or redistributing.
Contributions are welcome! Please submit pull requests or open issues for:
- Additional security patterns
- Performance improvements
- Documentation enhancements
- Bug fixes
This firewall provides a strong layer of security but should be part of a comprehensive security strategy. Always keep your software updated and follow security best practices.
For issues specific to this Nginx implementation, please open an issue on GitHub.
For questions about the original 8G Firewall, visit Perishable Press.