- Plugin version
- 1.0.1
- WordPress
- 5.8 or newer
- PHP
- 7.4 or newer
- Feed used
- Full blocklist
Download threathive-firewall.zip
Before you start
- The web server user must be able to write to
wp-content/. The plugin stores its data inwp-content/threathive-firewall/. - The server needs outbound HTTPS to
threathive.net, and towww.cloudflare.comif the site is behind Cloudflare. - WP-Cron must run, or a system cron must call
wp-cron.php(see step 6).
Setup
-
Install and activate the plugin
In the WordPress admin, go to
Plugins › Add New › Upload Plugin, choosethreathive-firewall.zip, then clickInstall NowandActivate. The first blocklist download starts within a few seconds.- Multisite: install it from
Network Admin › Pluginsand clickNetwork Activate. One configuration protects the whole network, so activating on a single subsite is refused. Settings are underNetwork Admin › ThreatHive Firewall. - Manual install: unzip so the files end up in
wp-content/plugins/threathive-firewall/, then activate it from the Plugins screen.
- Multisite: install it from
-
Check the status page
Open
ThreatHive Firewallin the admin menu and check three things:- The status badge in the top right says
Protecting. If it saysWaiting for first download, wait a minute and reload, or clickUpdate now. IPs on blocklistmatches the size of the full blocklist.Your IPshows your real public address andnot listed. If it sayslisted, add your address to the Allowlist and save before doing anything else, or you can lock yourself out.
ThreatHive.net Firewalldashboard widget shows the same status and the 20 most blocked addresses to administrators. - The status badge in the top right says
-
Confirm the plugin sees real visitor addresses
Leave
Client IP sourceonAutomaticand read theConnectionrow on the status page:
If the proxy test fails, configure the proxy to set the forwarded header itself:Via Cloudflare, using CF-Connecting-IP The site is behind Cloudflare. Nothing to do; Cloudflare's IP ranges are built in and refreshed weekly. Via trusted proxy, using forwarded header Requests come through a proxy you trust, such as Cloudflare Tunnel, a local nginx or Varnish. Click Re-test proxyonce; it should reportProxy test passed.Requests arrive with proxy headers, but that address is not trusted A separate proxy or load balancer sits in front of WordPress. If it is your own server-side proxy, click Trust <address> as my proxy. The plugin tests it first. Don't trust addresses that belong to an office network, VPN or browser proxy.Direct (REMOTE_ADDR) No proxy in front of the site. Nothing to do. # nginx proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # HAProxy option forwardfor -
Optional: block before the page cache
The firewall loads as the first plugin, but a page cache (WP Super Cache, W3 Total Cache, LiteSpeed Cache and similar) serves cached pages before any plugin runs. Early loading from
wp-config.phpblocks those requests too.- Copy the lines shown under
Early loadingon the status page. Always copy them from there, because they contain your site's real paths. They look like this:if ( ! defined( 'THFW_DATA_DIR' ) ) { define( 'THFW_DATA_DIR', '/var/www/.../wp-content/threathive-firewall' ); } if ( is_file( '/var/www/.../wp-content/plugins/threathive-firewall/early.php' ) ) { require_once '/var/www/.../wp-content/plugins/threathive-firewall/early.php'; } - Paste them into
wp-config.phpbetween/* Add any custom values between this line and the "stop editing" line. */and/* That's all, stop editing! Happy publishing. */. - Restart PHP so OPcache picks up the change, for example
sudo systemctl restart php8.3-fpm(use your PHP version), or restart the web server. - Reload the status page.
Early loadingshould sayActive via wp-config.php. If it saysNot active, follow the reason shown; usually PHP needs another restart.
- Copy the lines shown under
-
Nginx only: protect the data directory
Nginx ignores
.htaccess. The plugin checks daily whether its data directory is reachable from the web and shows a red notice if it is. Add this to the site'sserver { }block, then runsudo nginx -t && sudo systemctl reload nginx:
Apache and IIS are protected automatically.location ^~ /wp-content/threathive-firewall/ { deny all; return 404; } -
Recommended on quiet sites: use a real cron
WP-Cron only runs when someone visits, so list updates can be late on low-traffic sites. Disable it in
wp-config.phpwithdefine( 'DISABLE_WP_CRON', true );and add a cron job for the web server user:*/5 * * * * curl -fsS -o /dev/null https://example.com/wp-cron.php?doing_wp_cron # or with WP-CLI */5 * * * * cd /var/www/example && wp cron event run --due-now --quiet
Settings
| Mode | Enforce (block with HTTP 403), Monitor (log only) or Off. On busy sites, run Monitor for a day first. |
|---|---|
| Auto-update | From every 15 minutes (recommended) to daily. |
| Client IP source | Automatic (recommended). See step 3. |
| Trusted proxies | Your own proxies and load balancers, one per line. |
| Also trust this server's own address | On by default. Needed for Cloudflare Tunnel and local reverse proxies. |
| Allowlist | Addresses or CIDR ranges that are never blocked, one per line. # comments are allowed. |
| Keep IP-level logs | 1 to 90 days, 30 by default. Older logs containing IP addresses are deleted; daily totals without addresses are kept. |
| Block page link | Off by default. When on, the block page links to ThreatHive.net for delisting. |
Upgrading
Upload the new zip under Plugins › Add New › Upload Plugin and choose Replace current with uploaded. Settings, statistics and the downloaded list are kept. Open the firewall page once afterwards, and click Re-test proxy if you use a proxy or tunnel.
Coming from 1.0.0: the old runtime.php is replaced by runtime.json.php automatically. If you use early loading, replace the wp-config.php lines with the new ones from the status page and restart PHP.
Troubleshooting
| You locked yourself out | Add define( 'THFW_DISABLE', true ); to wp-config.php, or rename wp-content/plugins/threathive-firewall over SFTP. Log in, add your address to the Allowlist, save, then undo the change. THFW_DISABLE also turns off early loading. |
|---|---|
| Not protecting: data directory is not writable | Make wp-content writable by the web server user, or set a writable path with define( 'THFW_DATA_DIR', '/path/to/writable/dir/threathive-firewall' );. |
| Could not reach threathive.net | Check outbound HTTPS from the server with curl -I https://threathive.net/hiveblocklist.txt. The last good list stays active in the meantime. |
| Download rejected, use Force update | The new list shrank by more than 80% or grew more than tenfold. Check the feed, then click Force update if it is correct. The previous list stays active until then. |
| Protecting, list outdated | No successful update for 3 days. Check WP-Cron (step 6) and the Last result row. |
| Your IP shows a proxy or server address | See step 3. |
Uninstalling
If you enabled early loading, remove its lines from wp-config.php first. Then deactivate and delete the plugin (from Network Admin on multisite). Deleting removes all settings, statistics, logs and the wp-content/threathive-firewall directory.