# MikroTik Blocklist

Automatically generated MikroTik firewall blocklists for IPv4 and IPv6, built from multiple public threat intelligence sources.

The repository contains plain-text network lists and MikroTik-ready `.rsc` files for both full imports and diff-based updates.

## Files

### IPv4

- `mt-blocklist_v4.txt`: Plain CIDR/IP list
- `mt-blocklist_v4.rsc`: Full MikroTik import for `/ip firewall address-list`
- `mt-blocklist_ga_v4.rsc`: MikroTik global array export for diff-based updates (`newips`)

### IPv6

- `mt-blocklist_v6.txt`: Plain CIDR/IP list
- `mt-blocklist_v6.rsc`: Full MikroTik import for `/ipv6 firewall address-list`
- `mt-blocklist_ga_v6.rsc`: MikroTik global array export for diff-based updates (`newipv6`)

### Generator

- `mt-blocklist.sh`: Aggregates sources, validates entries, removes duplicates, excludes reserved ranges, and writes all output formats

## Features

- Aggregates multiple public blocklist sources
- Supports IPv4 and IPv6
- Deduplicates and collapses CIDR ranges
- Excludes private, reserved, and explicitly whitelisted ranges
- Produces MikroTik-ready import scripts
- Supports diff-based update workflows through global array exports

## Output Formats

### Full import

The `.rsc` files can be imported directly into MikroTik:

```routeros
/ip firewall address-list
add list=mt-blocklist address=...
```

Use:

- `mt-blocklist_v4.rsc` for IPv4
- `mt-blocklist_v6.rsc` for IPv6

### Diff-based update

The `_ga.rsc` files export arrays that can be consumed by an update script:

```routeros
:global newips [:toarray ""]
:set newips ($newips,"1.2.3.4")
```

Use:

- `mt-blocklist_ga_v4.rsc` for IPv4 (`newips`)
- `mt-blocklist_ga_v6.rsc` for IPv6 (`newipv6`)

## MikroTik Integration

### Download script

```routeros
:log info "blocklist-DL: started"

/tool fetch url="https://www.robingroppe.de/media/mt-blocklist/mt-blocklist_ga_v4.rsc" mode=https dst-path=mt-blocklist_ga_v4.rsc
/tool fetch url="https://www.robingroppe.de/media/mt-blocklist/mt-blocklist_ga_v6.rsc" mode=https dst-path=mt-blocklist_ga_v6.rsc

:log info "blocklist-DL: finished"
```

### Diff update script

```routeros
:log info "blocklist-DIFF: === STARTED ==="

# Disable logging to prevent flood
/system logging disable 0

# IPv4
:local listName4 "mt-blocklist"
:local removed4 0
:local added4 0

/import file-name=mt-blocklist_ga_v4.rsc
:global newips

:if ([:typeof $newips] != "array" || [:len $newips] = 0) do={
    :error "Empty or invalid IPv4 blocklist import"
}

/ip firewall address-list
:foreach entryId in=[find list=$listName4] do={
    :local addr [get $entryId address]
    :local idx [:find $newips $addr]
    :if ([:typeof $idx] != "nil") do={
        :set ($newips->$idx) ""
    } else={
        remove $entryId
        :set removed4 ($removed4 + 1)
    }
}

:foreach addr in=$newips do={
    :if ($addr != "") do={
        add list=$listName4 address=$addr
        :set added4 ($added4 + 1)
    }
}

:set newips
:log info ("blocklist-DIFF: IPv4 added=" . $added4 . " removed=" . $removed4)

# IPv6
:local listName6 "mt-blocklist-v6"
:local removed6 0
:local added6 0

/import file-name=mt-blocklist_ga_v6.rsc
:global newipv6

:if ([:typeof $newipv6] != "array" || [:len $newipv6] = 0) do={
    :error "Empty or invalid IPv6 blocklist import"
}

/ipv6 firewall address-list
:foreach entryId in=[find list=$listName6] do={
    :local addr [get $entryId address]
    :local idx [:find $newipv6 $addr]
    :if ([:typeof $idx] != "nil") do={
        :set ($newipv6->$idx) ""
    } else={
        remove $entryId
        :set removed6 ($removed6 + 1)
    }
}

:foreach addr in=$newipv6 do={
    :if ($addr != "") do={
        add list=$listName6 address=$addr
        :set added6 ($added6 + 1)
    }
}

:set newipv6
:log info ("blocklist-DIFF: IPv6 added=" . $added6 . " removed=" . $removed6)

:log info "blocklist-DIFF: completed"
```

### Clear both address lists

```routeros
:log info "blocklist-CLEAR: started"

/ip firewall address-list remove [find list=mt-blocklist]
/ipv6 firewall address-list remove [find list=mt-blocklist-v6]

:log info "blocklist-CLEAR: completed"
```

## Requirements

The generator script expects these commands to be available in `PATH`:

- `curl`
- `python3`
- `iprange`

If you want to use the optional publish block at the end of the script, `git` is needed as well.

## Script Configuration

The generator can be configured via environment variables without editing the script.

Common variables:

- `OUTDIR`: target directory for generated output files
- `TMPDIR`: working directory for downloads and intermediate files
- `LOCKDIR`: lock directory to prevent concurrent runs
- `LISTNAME_V4`: RouterOS address-list name for IPv4 exports
- `LISTNAME_V6`: RouterOS address-list name for IPv6 exports
- `OUTPUT_TXT_V4`, `OUTPUT_TXT_V6`: output filenames for the plain-text lists
- `OUTPUT_RSC_V4`, `OUTPUT_RSC_V6`: output filenames for the RouterOS import files
- `OUTPUT_GA_V4`, `OUTPUT_GA_V6`: output filenames for the RouterOS global-array files
- `CURL_CONNECT_TIMEOUT`: `curl` connect timeout in seconds
- `CURL_MAX_TIME`: `curl` maximum runtime per source in seconds
- `DOWNLOAD_JOBS`: number of parallel downloads
- `PUBLISH_GIT`: set to `1` to enable Git add/commit/push in `OUTDIR`

Examples:

```sh
./mt-blocklist.sh
```

```sh
PUBLISH_GIT=1 ./mt-blocklist.sh
```

```sh
OUTDIR=/srv/www/mt-blocklist \
TMPDIR=/var/tmp/mt-blocklist \
LISTNAME_V4=mt-blocklist \
LISTNAME_V6=mt-blocklist-v6 \
DOWNLOAD_JOBS=6 \
./mt-blocklist.sh
```

## Data Sources

- `https://www.projecthoneypot.org/list_of_ips.php?t=d&rss=1`
- `http://danger.rulez.sk/projects/bruteforceblocker/blist.php`
- `https://www.spamhaus.org/drop/drop.txt`
- `https://www.spamhaus.org/drop/dropv6.txt`
- `https://cinsscore.com/list/ci-badguys.txt`
- `https://lists.blocklist.de/lists/all.txt`
- `https://blocklist.greensnow.co/greensnow.txt`
- `https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset`
- `https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/stopforumspam_7d.ipset`
- `https://raw.githubusercontent.com/stamparm/ipsum/master/levels/3.txt`
- `https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/ips/tif.txt`
- `https://raw.githubusercontent.com/borestad/blocklist-abuseipdb/refs/heads/main/abuseipdb-s100-7d.ipv4`
- `https://raw.githubusercontent.com/borestad/blocklist-abuseipdb/refs/heads/main/stats/hallofshame/subnets/abuseipdb-s99-hallofshame-7d-25percent.ipv4`

## Notes

- Sources are treated as mixed IPv4/IPv6 input
- Invalid entries are filtered automatically
- IPv4 optimization uses `iprange`
- IPv6 optimization and exclusion handling are implemented in Python

## Disclaimer

This blocklist is compiled from third-party sources.

Use it at your own risk. False positives are possible.
