Skip to content
steponeerrorPublic

About

One verdict per IP, in plain words — evidence, confidence, geo & ASN fused from 49 public intel sources. 44/49 need no API key. One command, fully self-hosted.

Topics

Resources

Stars

24 stars

Watchers

0 watching

Forks

Latest commit

 

History

1,745 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

logo IP Radar

English | 简体中文

IP Radar — self-hosted IP intelligence

Pull 49 public sources into your own box — a full IP profile, not just a threat verdict. Every lookup comes back with a plain-words verdict — evidence, confidence, geo · city · ASN, cloud/hosting, proxy · VPN · Tor, service identity, all at once. One command, self-hosted.

License: AGPL v3 Docker Python 3.12+ FastAPI React 19

Live Demo

The live demo runs in read-only mode (sources & updates disabled; queries fully working). Self-host to unlock everything.

Malicious IP lookup result
☠️ Malicious IP — per-source evidence + confidence-scored verdict
Clean IP geo enrichment
🌱 Clean IP — geo · city · ASN enrichment

🚀 Try it in the live demo — click a sample:
☠️ Malicious IP · 🕵️ Tor/VPN exit · 🌱 Clean IP

Quick Start

The whole stack — FastAPI backend + built frontend — runs in one container. Docker Compose v2.24+ required (docker compose version to check).

git clone https://github.com/steponeerror/ip-radar.git
cd ip-radar
docker compose up -d --build

Open http://127.0.0.1:8000. The container is reachable within seconds — a banner at the top tracks the keyless feeds' download/build progress live (all but the 5 keyed sources, including geo/city/ASN, the major blocklists and cloud ranges), and queries unlock automatically once the build settles. Subsequent starts load from the ipradar-data volume in seconds.

All but 5 feeds need zero API keys. To light up the 5 keyed sources, drop the keys into .env.local (gitignored, overrides .env):

cp .env .env.local   # then open .env.local in any editor, fill keys
docker compose up -d
Source Variable Get a key
ipinfo_lite IPINFO_TOKEN https://ipinfo.io/account/token
abuseipdb ABUSEIPDB_API_KEY https://www.abuseipdb.com/account
otx OTX_API_KEY https://otx.alienvault.com/settings
otx_subscribed OTX_API_KEY(与 otx 共用) https://otx.alienvault.com/settings
ip2proxy IP2PROXY_TOKEN https://www.ip2location.com/
threatfox / urlhaus ABUSECH_AUTH_KEY(两源共用) https://auth.abuse.ch/ 注册 Auth-Key;钥在导出 URL 路径内,日志已打码

Slow npm/pip downloads (common on CN networks)? Pass mirror build-args:

docker compose build --build-arg PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
                      --build-arg NPM_REGISTRY=https://registry.npmmirror.com

Notes:

  • The port binds to 127.0.0.1 by default; to go LAN/public, edit ports in docker-compose.yml — same-origin web use needs no key; programmatic/API access requires an API key issued from /admin (unlock it via the admin env block in docker-compose.yml).
  • Behind a reverse proxy set IP_RADAR_PROXY_HEADERS=1 (trusted proxies default 172.16.0.0/12, override via IP_RADAR_FORWARDED_ALLOW_IPS, see docker-compose.yml) — otherwise per-IP rate limits only see the proxy IP.
  • Each feed has its own usage terms; commercial use is your responsibility (this repo's AGPL-3.0 covers code only).
  • Upgrade: git pull && docker compose up -d --build — the data volume stays right where it is.
  • Disk: budget ≥6 GB for the data volume.

Everything after docker compose up — reading the results page, the admin console, the full API surface, backup/upgrade/alert runbooks — lives in the User Manual (简体中文).

Desktop Companion

IP Radar Desktop — tray companion
🖥️ Tray-resident companion — hotkey → clipboard IPs → side-by-side verdicts, batch included

IP Radar Desktop takes the same lookups to your desktop: a tray-resident app where one global hotkey looks up whatever IP is on your clipboard — every source's verdict side by side, whole lists in one shot. Installers for Linux / macOS / Windows live on the Releases page.

Features

  • Works out of the box — first start downloads and builds every keyless feed into millions of records (live count: /api/db-status).
  • Cold start doesn't block — the container opens within seconds; queries unlock only when the keyless feeds are fully built. Never a verdict on half a dataset.
  • A verdict, not a pile of lists — one line of conclusion per IP, per-source evidence on the table, 0-100 confidence (log-odds Bayesian fusion: source reliability → logit coefficients, 60-day half-life decay on threat assertions, cross-source corroboration; 0 = no evidence, not innocence; scalar fields don't decay).
  • Geo · City · ASN — dual city sources (GeoLite2 + DB-IP), iptoasn for the ASN, plus CN ISP classification incl. HK/MO/TW.
  • Proxy · VPN · Tor · CDN · cloud, spotted at a glance — live-checked proxy lists, VPN ranges (incl. NordVPN & ProtonVPN), Tor exits, the big three CDNs' edges, and the five cloud providers' hosting ranges (AWS · Google · Azure · Oracle · Alibaba — one fused source, per-feed health), all labeled; known infra also shows its service identity (8.8.8.8 → DNS · Google Public DNS).
  • IPv6 lookups too — bare v6 and small v6 CIDRs resolve with geo · city · ASN · VPN · CDN · DROP ranges; geo/city/ASN, cloud-provider ranges, CDN edges and DROPv6 all carry v6; most threat lists have no v6 upstream — shown honestly as no-records.
  • Day/night theme toggle — light and dark themes one click apart; your choice is remembered and restored before first paint, so no flash of the wrong theme.
  • One container, memory that behaves — concurrency bends to host RAM; background refresh staggered per source: daily feeds 2×/day, weekly 1×/week, each at a fixed offset time.
  • STIX 2.1 export — /api/lookup/{ip}/stix; the image ships with stix2 pre-installed (requirements.txt), so the export works out of the box.

Architecture

flowchart TD
    A["Public sources<br/>(keyless auto + 5 keyed)"] --> B["Cold-start download /<br/>30-min scan · per-source 12h staggered refresh slots"]
    B --> C["Per-source parsers<br/>(classification pipeline)"]
    C --> D["Fusion<br/>(log-odds · corroboration · decay)"]
    D --> E["LMDB store<br/>(named volume · mmap)"]
    E --> F["FastAPI"]
    F --> G["React UI"]
Loading

Fused, stored, and queried on your own machine — your lookups never leave it.

API

Open http://127.0.0.1:8000 and type any IP: verdict, per-source evidence, and geo/ASN come back together. The API works directly too. Programmatic calls need an API key — first unlock the commented-out admin env block in docker-compose.yml and restart, then issue a key at /admin; the same-origin web page needs none (send it as -H "Authorization: Bearer <key>").

# core lookup (needs a key — see above)
curl -s http://127.0.0.1:8000/api/lookup/1.12.0.1
# → {"ip":"1.12.0.1","country":{"value":"CN",..},"city":{"value":"Guangzhou",..},"asn":{"value":132203,..},"classifications":{..},"attributes":{..}}

# record count & status
curl -s http://127.0.0.1:8000/api/db-status

The other management endpoints (sources / eval / update-db / tasks / events, …) are cataloged end-to-end in the User Manual → API reference; the UI triggers refreshes with one click too. Don't expose the port to untrusted networks.

Security notes

  • The same-origin web tier is browser convenience, not an auth boundary: a raw HTTP client can claim any Host/Origin. If the port is reachable from an untrusted network, the real fence is API keys (/admin) or a Host-validating reverse proxy (Caddy/Nginx site match).
  • Source catalog (/api/sources) and eval report cards (/api/eval*) are admin-only — sign in at /admin.
  • /docs / /redoc / /openapi.json are disabled by default; set IP_RADAR_ENABLE_DOCS=1 to enable (dev convenience — keep off on public deployments).

Public-demo guard (opt-in)

For any instance exposed to the public internet, an opt-in guard middleware hides the write/internal surface from anonymous visitors. Three knobs, all off by default (zero behavior change for self-hosting): IP_RADAR_PUBLIC_DEMO=1 enables it; IP_RADAR_DEMO_ADMIN_IPS and IP_RADAR_DEMO_TRUST_XFF=1 control the maintainer bypass. Full endpoint semantics, exemptions, and the XFF-trust security premise: deploy/README.md.

Fail2ban integration: ask before you ban

scripts/fail2ban/ipradar.conf is a fail2ban action that triages every ban against your local IP Radar verdict first: confirmed-malicious IPs (confidence ≥ 70, tunable) go on a persistent long-ban list; CDN/infra edges skip the ban entirely with a loud log line — no more banning Cloudflare. Install & options: scripts/fail2ban/README.md.

Graylog integration: log enrichment

Use Graylog's built-in Lookup Tables (HTTP JSONPath adapter) to turn source IPs into country, ASN, and a fused threat verdict (threat.verdict / threat.confidence) — no plugin, unlimited local lookups, nothing leaves the machine. Step-by-step config + pipeline rules: integrations/graylog/README.md.

Wazuh integration: alert enrichment (local alternative to the VirusTotal integration)

integrations/wazuh/custom-ipradar enriches every IP-bearing Wazuh alert into an ECS threat.indicator follow-up alert — unlimited local lookups, your alert IPs never leave the machine. Install, ossec.conf snippet, and sample alert: integrations/wazuh/README.md.

Adding Sources with AI

The repo ships three AI agent skills (.pi/skills/) — with an agent that loads project-level skills (e.g. pi), one sentence lets AI wire the source in for you:

Skill When Example
discover-intel-sources No source picked yet; want an evaluated shortlist "Find me a few threat-intel sources worth adding"
add-intel-source A specific source is chosen; wire it in end-to-end "Add GreyNoise"
manage-intel-source Manage existing sources: health-check, update, replace "Check the health of all sources"

Data Sources & Acknowledgments

Every dataset below belongs to its provider — thank you for keeping them open and maintained. 🔑 = needs a free/paid API key (where to put it: Quick Start); * = aggregator, credit flows to the upstream list maintainers.

Threat Reputation

Source Provider Contributes 🔑
abuseipdb AbuseIPDB Most-reported attacker IPs 🔑
otx AlienVault OTX Community threat pulses (IPv4 indicators) 🔑
otx_subscribed AlienVault OTX Subscribed pulse library (curated honeypots / C2 lists) 🔑
spamhaus Spamhaus DROP/EDROP hijacked ranges
stopforumspam StopForumSpam Forum-spammer IPs (365-day window, report counts)
threatfox abuse.ch Malware IOC feed (CSV/ZIP; v2 认证导出) 🔑
urlhaus abuse.ch Malicious URLs → IPs (v2 认证导出) 🔑
tweetfeed * TweetFeed Crowd-sourced IOCs from X/Twitter
ipsum * IPsum Daily compile of many public blocklists
firehol * FireHOL Level1/2 + abusers/proxies/webserver sublists
blocklist_de * Blocklist.de 10 attack-type sublists + aggregate
emerging_threats Proofpoint ET Provenance-curated firewall blocklist
binarydefense Binary Defense Honeypot attacker banlist
bruteforce BruteForceBlocker SSH brute-force attacker IPs
ciarm CINS Army Passive-reputation bad-guys list
greensnow GreenSnow Compromised-host blocklist
dataplane Dataplane.org Rolling 7-day sensor signals (merged)
dshield DShield Top-attacker /24 blocks (attack counts)
f3csystems f3cSystems Honeypot scanner blocklist (Sekoia sensors)
reportedip ReportedIP WordPress-honeypot community reputation
siberkapan SiberKapan Turkish honeypot-network sensor blocklist
threatcluster ThreatCluster Curated high-confidence malicious IPs
turris_greylist Turris Sentinel Distributed-router greylist (protocol probes)
drb_ra * C2IntelFeeds Aggregated C2 IPs (30-day hunts)
knock_knock Knock-Knock 13-protocol honeypot attacker blocklist (month window)
rtbh RTBH.com.tr Turkish 54-sensor DDoS-source RTBH list

Geo & ASN

Source Provider Contributes 🔑
geolite_city MaxMind GeoLite2 City / geo per IP
dbip_city DB-IP City-lite — 2nd city voting source
iptoasn IPtoASN ASN + AS-name ranges
cn_isp clang.cn ISP ranges China ISP classification (mainland + HK/MO/TW)
ipinfo_lite IPinfo Country / ASN / ranges enrichment 🔑

Asset & Network Surface

Source Provider Contributes 🔑
ip2proxy IP2Location PX2 LITE proxy ranges 🔑
proxyscrape ProxyScrape Open proxy IPs
tor_exits Tor Project Tor exit node addresses
danmeuk_tor dan.me.uk Full Tor relay list (~11k nodes) — second is_tor witness
x4bnet_vpn X4BNet VPN ranges
nordvpn NordVPN NordVPN server ranges (mirror)
protonvpn ProtonVPN ProtonVPN server ranges (mirror)
hookzof hookzof Live-checked SOCKS5 proxies
thespeedx TheSpeedX Live-checked HTTP proxies
cdn_edges CloudFront · Cloudflare · Fastly CDN edge ranges
cloud_ranges AWS · Google · Azure · Oracle · Alibaba Cloud / hosting ranges — five publisher feeds behind one source; partial-failure tolerant (a failed feed keeps its last snapshot)
infra_services curated Public DNS resolvers / NTP infrastructure (root servers moved to root_servers)
root_servers IANA IANA root hints (named.root)
dns_public DNSCrypt Community public DNS resolver endpoints (public-resolvers.md, sdns stamps decoded)

Development

Dev mode (frontend hot-reload on :5173, backend API on :8000):

./dev.sh

Or run each side yourself (mind: --host 0.0.0.0 exposes the API to your LAN/public network — web visitors query keylessly, programmatic callers need a key; use only if you know what you're doing):

# backend (first run: python3 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt)
cd backend && source .venv/bin/activate
uvicorn main:app --reload --host 0.0.0.0 --port 8000

# frontend
cd frontend && npm run dev

Production-style (builds frontend, serves everything on :8000):

./start.sh

Eval layer

The eval layer emits two kinds of reliability numbers side by side: the declared r (hand-set per source, production-authoritative) and measured θ (independent-corroboration posterior, advisory). θ is never an accuracy claim and never feeds the production weights automatically — adopting a measured value requires a human-reviewed PR referencing the eval report.

Run it from backend/ via python -m ipdb._eval: --audit (lineage audit — copying-direction verdicts over persisted model history, advisory), --anchors (known-answer regression gate; exit 1 on any failure), and --dsem (DS-EM fair fight: market vs declared vs π̂, advisory). The admin console's Sources tab mirrors this dual track — measured θ (90% CI) beside each source's declared r.

Tests

# backend
cd backend
[ -d .venv ] || python3 -m venv .venv
.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest -q

# frontend
cd frontend && npm test

Updating

git pull && docker compose up -d --build

The data volume stays in place — no data migration on upgrades. The banner at the top tells you when a new release lands (hit "Check for updates" to refresh) with this exact command; an in-page "Update now" button can be enabled via the self-update mounts. The opt-in setup, its security caveats (docker.sock), and the maintainer release traps: User Manual → Operations.

Backup & restore

All state lives in a single named volume (ipradar-data → /app/data): per-source raw downloads, LMDB epoch dirs with their sidecars, and the SQLite pair auth.db/alerts.db — rebuilds never write in place, so a volume copy taken with the container stopped is a complete, consistent backup. Stopped-copy recipe, hot-copy rules, restore verification, and what is (ir)replaceable: User Manual → Operations.

Source alerts (optional)

Notifications are silent by default. Set IP_RADAR_ALERT_URLS (any environment block, or .env.local) to a comma-separated list of apprise-style URLs — mailto:, Discord/Telegram/Lark webhooks — and you'll get one combined message when a source stops updating, keeps failing, or fails to load. Details: User Manual → Operations.

License

© 2026 steponeerror, licensed under AGPL-3.0; each intelligence feed keeps its own terms.

If you cite, build on, or fork this project, please follow AGPL-3.0: keep this license and the copyright notice, and mark what you changed; if you offer a network service built on it, its source must also be released under AGPL-3.0. If this project helps your research, writing, or product, a citation is appreciated: https://github.com/steponeerror/ip-radar.

About This Code

This project was written by vibe coding. It surely has its quirks and rough edges; please be understanding, and file an issue when you spot one.

Epilogue

My previous employer — a certain TJ threat-intelligence company: the atmosphere was friendly, the pace was gentle; they simply owed me over half a year of wages, and after labor arbitration, still did not pay.

To be honest, I hold no grudge against them — as a worker, we simply stand on different sides. That said, the way the company handled it was not right.

And banning my account — a perfectly normal one, using nothing but their free basic services? That was a bit much.

This project is dedicated to the legitimate rights of every worker — and to one simple belief: basic IP intelligence should be available to everyone.

404Starlink

IP Radar has joined 404Starlink

Friendly Links

About

One verdict per IP, in plain words — evidence, confidence, geo & ASN fused from 49 public intel sources. 44/49 need no API key. One command, fully self-hosted.

Topics

Resources

Stars

24 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages