No description
Find a file
2025-06-02 11:28:32 +00:00
.github chore: Release 1.1.2 (#8) 2025-06-02 11:28:32 +00:00
src fix: Catch NftError in state check 2025-06-02 13:26:35 +02:00
tests test: Simplify nft test case 2025-05-12 10:26:56 +02:00
deceptimeed.nimble chore: Release 1.1.2 (#8) 2025-06-02 11:28:32 +00:00
nim.cfg build: Include binary in release 2025-05-11 14:15:20 +02:00

Deceptimeed

Meed (/miːd/), n.
1 : an earned reward or wage
2 : a fitting return or recompense

This utility loads IP lists into nftables from HTTP endpoints serving plain text or JSON feeds, with the aim of achieving automatic, low-level blocking of IP addresses obtained from threat-intelligence sources such as honeypots.

Its purpose is similar to tools like Fail2Ban or CrowdSec, but with significantly reduced risk of false positives and no reliance on brittle, resource-intensive log parsing to distinguish malicious from legitimate traffic.

While primarily meant as a companion helper to the Deceptifeed honeypot server and its /plain and /json endpoints, this tool should be able to support any source feed as long as either of the following criteria are met:

  • Plain text with one IP address per line
  • JSON data with IPs as string values

Example feeds

Plain text:

244.38.32.145
208.206.100.55
216.94.57.114

JSON:

{
  "threat_feed": [
    {
      "ip": "244.38.32.145",
      "added": "2025-04-18T16:53:25.633864571Z",
      "last_seen": "2025-04-19T12:44:40.711376448Z",
      "observations": 5
    },
    {
      "ip": "208.206.100.55",
      "added": "2025-04-18T17:26:01.135873822Z",
      "last_seen": "2025-04-18T17:26:01.135873822Z",
      "observations": 1
    },
    {
      "ip": "216.94.57.114",
      "added": "2025-04-19T04:17:29.122866189Z",
      "last_seen": "2025-04-19T04:17:29.122866189Z",
      "observations": 1
    },
  ]
}

Note

The structure of the JSON data doesn't matter since the parser will extract any strings representing valid IP addresses.


Installation

Using Nimble

nimble install deceptimeed

Compiling from source

nim c -d:release -d:ssl src/deceptimeed.nim

Downloading binary

Pre-built binaries for Linux (AMD64) are available on the release page.

Usage

Requires root.

Usage:
  deceptimeed [options] feed_url

Arguments:
  feed_url         IP feed URL

Options:
  -h, --help
  --version                  Show program version and exit
  --oneshot                  Run once and exit
  -v, --verbose              Show detailed output
  -i, --interval=INTERVAL    Minutes between refreshes (default: 10)
  -c, --config=CONFIG        Path to config file (default: /etc/deceptimeed.conf)

Example:

deceptimeed -c /etc/custom.conf -i 30 -v https://honeypot.mydomain.com/plain

Testing

To test if an IP is successfully blocked, you can simulate traffic using tools like hping3. For example, to test blocking of 1.2.3.4 (assuming it's in your blocklist):

hping3 -S -a 1.2.3.4 <your-server-ip>

Replace <your-server-ip> with the IP of the machine using deceptimeed. The packet will be dropped silently if the blocking is effective.


How It Works

  1. Ruleset Setup
    Creates (if not already existing):

    • table inet blocklist
    • set bad_ip4 (IPv4) and set bad_ip6 (IPv6)
    • chain preraw with drop rules matching source addresses in those sets
  2. Feed Download
    Pulls a plaintext or JSON IP feed from a configured endpoint.

  3. Parsing and Filtering

    • Extracts IP addresses (IPv4 and IPv6) from feed.
    • Removes invalid entries and duplicates.
    • Caps total at 100 000 IPs by default.
  4. Atomic Updates
    Deletes obsolete IP elements and adds new ones in a single nft -f batch.

    The sets are never flushed, so existing blocks stay active for the entire update. If the batch fails, current nftables content remains unchanged.

  5. Periodic Refresh
    Sleeps for <interval> minutes (default: 10), then starts over.


Configuration

The config file (default: /etc/deceptimeed.conf) supports these sections and options:

[nftables]
table = blocklist       ; Table name
set4 = bad_ip4          ; IPv4 set name  
set6 = bad_ip6          ; IPv6 set name
chain = preraw          ; Chain name
priority = -300         ; Chain priority
max_elements = 100000   ; Max IPs to process

[http]
timeout_ms = 10000      ; HTTP request timeout in milliseconds

The above defaults will be used in place of missing values or in the absence of a config file.