IP-DB Shield · free and open source

Put your own check screen in front of your site

The check screen you know from the big CDNs, carrying your name instead of theirs and running on your own server. A visitor arrives, a one-second check runs, and they are through; an address on the shared threat list never reaches your application at all. No DNS change, no traffic routed through anyone else.

  • Free
  • MIT licence
  • PHP 7.0+
  • No dependencies
  • Static sites too

Install it and your daily API quota goes to 30,000 lookups — nothing to apply for. Pricing →

Addresses on the list39,208ip-db.com
Outbound calls per visit0in list mode
File to install1one PHP file
Visitor languages4tr · en · de · es

What your visitor sees

There are three screens and all three carry your brand. The controls below feed the real template: the colour, name and language you pick render the page your visitor will actually get — not a screenshot of it, the running page.

Open the template: theme/screen.html →
Site name Accent colour
Logo URL (optional)
example-shop.com/checkout 503

Live — the proof of work really runs in your browser

How a request is decided

Top to bottom, first match wins. Each rung is cheaper than the one below it, so most decisions end in a single disk read.

  1. 01 Not a page request Assets, XHR, webhooks, wp-cron — untouched
  2. 02 Your own allow list Through
  3. 03 Your own deny list Refused
  4. 04 A trap path (/.env, /.git/…) Refused, and reported if you opted in
  5. 05 A verified search crawler Through — reverse DNS, forward-confirmed
  6. 06 Listed, or score ≥ block threshold The branded 403 page
  7. 07 Score ≥ verify threshold, or a flood Press and hold + proof of work (+ captcha)
  8. 08 Everyone else The one-second automatic check, then a signed cookie

POST requests are never interrupted — a form submission cannot survive an interstitial. A refused address is refused whatever the method.

Where the decision comes from

Two sources, either or both. In list mode — the default — nothing leaves your server while a visitor waits.

List (feed)API (/check)Both
Outbound calls per visit01 per address (cached)only for addresses not on the list
Latencybinary search, microsecondsone round-trip on first sightzero on most visits
Spends the daily quotanoyescapped by a budget
Freshnessrefreshed every few hourslivelive
Anything leaves your servernothe IP address onlyonly addresses not on the list
What you get backscore + categoryscore, country, network, labelboth combined

The list is capped by your tier: 5,000 addresses for a new account, 50,000 once your email is verified. It is written to disk as a sorted index — a lookup in a 39,208-address list is about 17 reads.

Install

Three minutes, and you can do it without touching a line of application code.

Version 1.0.0 · Size 48 KB · Files 12
  1. 1
    Get a free API key
    https://ip-db.com/en/account/register
  2. 2
    Download the kit
    cd /home/you/public_html
    curl -fsSL https://ip-db.com/shield/ipdb-shield.zip -o ipdb-shield.zip
    unzip ipdb-shield.zip && rm ipdb-shield.zip
  3. 3
    config.php
    php ipdb-shield/ipdb-shield.php --secret
    php ipdb-shield/ipdb-shield.php --refresh
    php ipdb-shield/ipdb-shield.php --status
  4. 4
    Install
    # either, as the first line your site runs:
    require __DIR__ . '/ipdb-shield/ipdb-shield.php';
    
    # or, without touching any code, in .htaccess:
    php_value auto_prepend_file "/home/you/public_html/ipdb-shield/ipdb-shield.php"
  1. 1
    wp-content/mu-plugins/
    examples/wordpress-mu-plugin.php  →  wp-content/mu-plugins/ipdb-shield-loader.php
  2. 2
    config.php · skip_paths
    'skip_paths' => array('/wp-cron.php', '/wp-json/**', '/xmlrpc.php',
                           '/wp-admin/admin-ajax.php'),
  3. 3
    WordPress

    The plugin runs inside WordPress and protects WordPress. The shield runs at the very start of PHP: the decision is made before WordPress loads at all, and it covers your non-WordPress files too. You can run both.

    Integrations →
Get your site token It is bound to your domain and is not a secret; the endpoint only ever answers about the caller’s own address.
<script src="/ipdb-shield.js"
        data-token="YOUR-SITE-TOKEN"
        data-brand="Example"
        data-accent="#2563eb"
        data-block="75" data-verify="40"></script>

The honest limit: this edition runs in the visitor’s browser. It stops automated traffic that executes JavaScript and gives a human a clear explanation, but a crawler that ignores scripts still reads your HTML. Real enforcement happens server-side — if anything on your site is generated by PHP, use the PHP edition.

Requirements

  • PHP 7.0 or newer — shared hosting included
  • cURL or allow_url_fopen, to fetch the list
  • One writable directory (list, counters, log)
  • A free IP-DB API key
  • PHP-GD only if you want the image captcha

Verify what you downloaded

The zip is rebuilt from the source tree with fixed entry metadata: the same sources always produce the same bytes, and therefore the same digest.

764da798ab8deeb81c17002d2f9ac726ee43750049752329c0ad4bccc9980e4d

Build your configuration

These fields write config.php live. Your API key never leaves your browser — the file is assembled here, on your machine.

config.php

Your own panel

The kit derives a URL only you know. It shows the mode, the age and size of the local list, today’s counters, the last seven days and the most recent decisions with the reason for each. No login, no database — the URL comes from your secret.

Command line
$ php ipdb-shield.php --status
IP-DB Shield 1.0.0 · mode protect · source feed · PHP 8.2.12
blocklist: 39,208 entries, 42 min old
today: {"checked":7412,"blocked":1284,"solved":7390,"traps":38}
panel: https://example-shop.com/?ipdb_shield=status&t=…

$ php ipdb-shield.php --test 203.0.113.42
203.0.113.42  score=96  listed=yes  category=ssh_brute_force
              source=feed  -> BLOCK

So it cannot go wrong

Your search rankings

Googlebot and friends are let through — but only when the address really belongs to them: the reverse DNS name must end in the operator’s domain and resolve back to the same address. A user agent claiming to be Googlebot proves nothing. The check screen answers 503 with noindex, never a 200 page carrying your title.

Failure leaves the site up

No list, an unreachable API, an unwritable cache directory: the visitor goes through and the reason lands in the PHP error log. A gate must never become an outage.

The address cannot be forged

REMOTE_ADDR is the only authority. A forwarded header is read only when the connection itself came from a proxy you listed.

One-shot challenges

Every check is signed, expires in ten minutes, is bound to the browser and can be solved once. A captured proof of work is worthless the second time.

Accessible

Keyboard-operable, announced to screen readers, respects reduced motion and dark mode, works at phone width. A visitor without JavaScript is told so in their own language instead of being left on a spinner.

Privacy

In list mode nothing about a visitor leaves your server. In API mode a single IP address is sent: no URL, no user agent, no cookie, no content. The screen tells the visitor which of the two is happening.

Questions

Will it slow my site down?
In list mode there is no network call per visit. The address lookup is a binary search over a sorted index: about seventeen disk reads in a hundred-thousand-entry list, with nothing held in memory. A visitor who passes the check gets a signed cookie and is not checked again for hours.
Will it hurt my Google rankings?
No. Verified search engines are never stopped, and the verification is reverse DNS that must belong to the operator and resolve back to the same address — not a user agent. The check screen answers 503 with noindex, which tells a crawler exactly what it is: a temporary gate.
What if it blocks the wrong person?
Run it in monitor mode first: nobody is stopped, every decision is logged, and you tune the thresholds from the panel. The refusal page shows the visitor their address, the reason and a link to that address’s public profile — and you can add a link for them to write to you.
I use Cloudflare. Does it conflict?
No, they work together. Just fill in proxy_header and trusted_proxies in config.php for Cloudflare, otherwise every visitor looks like a Cloudflare address.
Is it free, or free for now?
Free. IP-DB has no paid tier, not even for commercial use. The kit is MIT licensed: read it, change it, install it for your own clients.
How is this different from your WordPress plugin?
The plugin runs inside WordPress and protects WordPress. The shield runs at the very start of PHP: the decision is made before WordPress loads at all, and it covers your non-WordPress files too. You can run both.

Goes well with

Five minutes from now your site has a doorman

Open a free account, copy your key, download the kit. There is no paid tier — not for business use either.