English | 简体中文
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.
The live demo runs in read-only mode (sources & updates disabled; queries fully working). Self-host to unlock everything.
![]() ☠️ Malicious IP — per-source evidence + confidence-scored verdict |
![]() 🌱 Clean IP — geo · city · ASN enrichment |
🚀 Try it in the live demo — click a sample:
☠️ Malicious IP · 🕵️ Tor/VPN exit · 🌱 Clean IP
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 --buildOpen 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.comNotes:
- The port binds to
127.0.0.1by default; to go LAN/public, editportsindocker-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 indocker-compose.yml). - Behind a reverse proxy set
IP_RADAR_PROXY_HEADERS=1(trusted proxies default172.16.0.0/12, override viaIP_RADAR_FORWARDED_ALLOW_IPS, seedocker-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 (简体中文).

🖥️ 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.
- 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 withstix2pre-installed (requirements.txt), so the export works out of the box.
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"]
Fused, stored, and queried on your own machine — your lookups never leave it.
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-statusThe 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.
- 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 aHost-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.jsonare disabled by default; setIP_RADAR_ENABLE_DOCS=1to enable (dev convenience — keep off on public deployments).
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.
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.
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.
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.
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" |
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.
| 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 |
| 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 | 🔑 |
| 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) |
Dev mode (frontend hot-reload on :5173, backend API on :8000):
./dev.shOr 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 devProduction-style (builds frontend, serves everything on :8000):
./start.shThe 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.
# 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 testgit pull && docker compose up -d --buildThe 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.
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.
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.
© 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.
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.
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.
IP Radar has joined 404Starlink



