Skip to content

nashcom/open-blocklist

Repository files navigation

Open Blocklist

HCL Ambassador Nash!Com Blog License: Apache 2.0

Open Blocklist is a distributed IP reputation and blocklist platform providing DNS blocklists (RBL/DNSBL), reverse DNS responses, and high-performance HTTP APIs for reputation lookups and authorization.

The system is designed for high-throughput environments and modern container-based deployments. It combines CoreDNS, etcd, and the Open Blocklist service written in Go to provide scalable blocklist management and high-performance querying. Open Blocklist can be used by mail systems, security gateways, reverse proxies, firewalls, and other reputation or abuse detection services.

Use Cases

Open Blocklist can be used for:

  • Mail server reputation checks
  • DNS blocklists (RBL / DNSBL)
  • Reverse DNS reputation responses (for example with NGINX $remote_host)
  • Subrequest authentication (for example with NGINX passing $remote_addr)
  • API-based reputation checks
  • Security gateways and abuse detection systems
  • Integration with intrusion detection tools such as CrowdSec

Components

Open Blocklist consists of three containers.

Container Purpose
open-blocklist-main Blocklist API and lookup service
open-blocklist-dns CoreDNS DNS blocklist and reverse DNS service
open-blocklist-etcd Distributed key-value storage backend

Architecture

CoreDNS Server

CoreDNS provides the DNS interface for the blocklist. It implements the DNS blocklist functionality using a forwarder configuration to a small DNS server provided only for RBL and IN-ARPA queries. An earlier version used built-in etcd integration. This allows DNS queries to be answered directly from the blocklist entries stored in etcd.

etcd Backend Storage

etcd provides the distributed key-value storage used by the platform.

Blocklist entries are stored in etcd for:

  • persistence
  • synchronization between services
  • integration with CoreDNS

The entries are stored in SkyDNS-compatible layout in order to allow integration with Etcd.

Go Based Application

The Open Blocklist service is written in Go. The application provides the glue between the components and exposes REST API endpoints. It maintains an in-memory copy of all blocklist entries using a high-performance map to ensure extremely fast API lookups and updates. In addition it provides a small DNS server written in Go provide RBL and IN-ARPA replies directly from an in memory map.

Data Flow

  1. At startup, all data is loaded from etcd into memory.
  2. API lookups are served directly from the in-memory map for maximum performance.
  3. Updates are applied in memory and persisted to etcd.
  4. CoreDNS uses a forwarder configuration to send requests directly to a DNS server, which is hosted by the open-blocklist container.
  5. A background process enforces expiration policies and removes expired entries from both memory and etcd.
                    +----------------------------------+
                    |        In-Memory Store           |
                    |    (shared fast lookup map)      |
                    +---------+-----------+------------+
                              |           |
                              |           |
        +---------------------+           +---------------------+
        |                                               |
        v                                               v
+---------------------------+               +---------------------------+
|   Lookup / Auth API       |               |   Block Management API    |
|        (port 8090)        |               |        (port 8091)        |
+-------------+-------------+               +-------------+-------------+
              |                                           |
              |                                           |
              +-------------------+-----------------------+
                                  |
                                  v
                             +----------+
                             |  etcd    |
                             | store    |
                             +----------+

                                  ^
                                  |
                    (load on startup + persist updates)
                                  |
                     +-----------------------------+
                     | Background Expiration Worker|
                     +-----------------------------+
                                  |
                                  v
                             (cleanup both)

   +------------------+       forward        +----------------------+
   |     CoreDNS      | -------------------> |   DNSBL Server       |
   |  (DNS frontend)  |                      | (open-blocklist)     |
   +--------+---------+                      +----------+-----------+
            |                                           |
            v                                           v
       DNS Clients                              Uses In-Memory Store

Quick Start

The repository contains a Docker Compose setup to quickly start the service.

Start the system:

docker compose up -d

Example output:

[+] up 4/4
 ✔ Network open-blocklist_default Created
 ✔ Container open-blocklist-etcd  Started
 ✔ Container open-blocklist-dns   Started
 ✔ Container open-blocklist-main  Started

Service Ports

Service Port Purpose
Lookup API 8090 blocklist lookup and authorization
Block management API 8091 add/remove block entries
DNS service 8053 DNSBL and reverse DNS lookups

Example endpoints:

http://localhost:8091
http://localhost:8091
DNS: localhost:8053

Note: Ports can be changed in the configuration if they are already in use.

Building the Image

The project includes a build.sh script. By default, an Alpine-based image is used.

./build.sh

Functionality

Blocking an IP

Add an IP address to the blocklist:

curl -X PUT localhost:8091/block/1.2.3.4

Add a block with expiration:

curl -X PUT "localhost:8091/block/1.2.3.4?duration=24h"

Add a block with a custom source:

curl -X PUT "localhost:8091/block/1.2.3.4?duration=2h&source=crowdsec"

Set a fixed expiration timestamp:

curl -X PUT "localhost:8091/block/1.2.3.4?expiration=2026-03-20T12:00:00Z"

Remove a block:

curl -X DELETE localhost:8091/block/1.2.3.4

Blocking a Network (CIDR)

Add a network range to the blocklist:

curl -X PUT localhost:8091/block-network/192.168.1.0/24

Add with expiration and source:

curl -X PUT "localhost:8091/block-network/10.0.0.0/8?duration=24h&source=manual"

IPv6 networks are supported the same way:

curl -X PUT "localhost:8091/block-network/2001:db8::/32?duration=12h"

Remove a network block:

curl -X DELETE localhost:8091/block-network/192.168.1.0/24

The host bits of the supplied address are masked automatically, so 192.168.1.55/24 is stored as 192.168.1.0/24.

HTTP Lookup API

Query the blocklist by IP address:

curl localhost:8090/lookup/1.2.3.4

Example response (exact IP match):

{
  "blocked": true,
  "expiration": 0,
  "expiration_iso": "",
  "first_seen": 1773602647,
  "first_seen_iso": "2026-03-15T19:24:07Z",
  "ip": "1.2.3.4",
  "remaining_duration": "permanent",
  "remaining_seconds": 0,
  "return_code": "127.0.0.2",
  "source": "open-blocklist"
}

If the IP is not individually blocked but falls within a blocked network range, the lookup still returns blocked and includes the matching CIDR:

{
  "blocked": true,
  "ip": "192.168.1.55",
  "matched_cidr": "192.168.1.0/24",
  "source": "manual",
  "remaining_duration": "23h59m12s",
  ...
}

HTTP Metadata Headers

The lookup endpoint also returns useful metadata via HTTP headers.

curl -I localhost:8090/lookup/1.2.3.4

Example:

HTTP/1.1 200 OK
X-Blocklist-Status: blocked
X-Blocklist-Ip: 1.2.3.4
X-Blocklist-Return: 127.0.0.2
X-Blocklist-Source: open-blocklist
X-Blocklist-Remaining-Duration: permanent

When the match is a CIDR network block, an additional header is returned:

X-Blocklist-Matched-CIDR: 192.168.1.0/24

Authorization Endpoint

The /auth endpoint provides a fast allow/deny check.

Blocked address:

curl -I localhost:8090/auth/1.2.3.4

Response:

HTTP/1.1 403 Forbidden

Allowed address:

curl -I localhost:8090/auth/1.2.3.5

Response:

HTTP/1.1 204 No Content

This endpoint is useful for integration with reverse proxies or network gateways.

DNS Blocklist (RBL)

Query the DNS blocklist:

dig @127.0.0.1 -p 55 4.3.2.1.open-blocklist.internal +short

Response:

127.0.0.2

Reverse DNS Lookup

Blocked IPs can also be queried via reverse DNS.

dig @127.0.0.1 -p 55 -x 1.2.3.4 +short

Example response:

blocked.internal.

IPv6 Support

IPv6 addresses can also be blocked.

curl -X PUT "localhost:8091/block/2001:db8::1?duration=24h"

Reverse lookup:

dig @127.0.0.1 -p 55 -x 2001:db8::1

Direct DNSBL query:

dig @127.0.0.1 -p 55 \
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.open-blocklist.internal +short

Troubleshooting

Inspecting Stored Entries

Blocklist entries are stored in etcd using a SkyDNS-compatible layout.

List entries:

docker exec open-blocklist-etcd \
etcdctl get /skydns/internal/open-blocklist --prefix

Example:

/skydns/internal/open-blocklist/1/2/3/4
{"v":1,"host":"127.0.0.2","ttl":300,"source":"open-blocklist","first_seen":1773602647,"expiration":0}

Watching Updates

You can watch blocklist changes in real time.

docker exec open-blocklist-etcd \
etcdctl watch /skydns/internal/open-blocklist --prefix

Network (CIDR) blocks are stored under a separate prefix:

docker exec open-blocklist-etcd \
etcdctl get /skydns/internal/open-blocklist-cidr --prefix

Example:

/skydns/internal/open-blocklist-cidr/192.168.1.0_24
{"v":1,"host":"127.0.0.2","ttl":120,"source":"manual","first_seen":1773602647,"expiration":0}

This streams updates whenever entries are created, modified, or deleted.

About

An open blocklist tool

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors