GeoIP and world map of network traffic: visualizing where attacks come from
Understanding GeoIP network traffic in real time is no longer optional for server operators who need to distinguish legitimate users from coordinated attack campaigns. When inbound packets arrive at line rate, knowing their geographic origin—mapped onto an interactive world visualization—turns raw connection logs into actionable intelligence, revealing whether a spike originates from a single region or a distributed botnet spanning continents.
Modern DDoS attacks and brute-force campaigns rarely announce themselves politely. A sudden surge of SYN packets might look identical whether it comes from five thousand residential proxies in Southeast Asia or a handful of misconfigured legitimate clients in Frankfurt. A GeoIP traffic map overlays geographic metadata onto connection events, letting operators spot patterns that numeric logs alone will never surface: a tightly clustered assault from a single ASN, a slow credential-stuffing wave moving westward across time zones, or the telltale polygon of a booter service's favorite exit nodes.
This article explains how GeoIP visualization works at the kernel level, which data feeds power the lookups, and how platforms like PAKKT.io combine XDP/eBPF packet inspection with TimescaleDB time-series storage to render live attack geography on a centralized dashboard—without adding measurable latency to the traffic path itself.
How GeoIP Network Traffic Mapping Works Under the Hood
A GeoIP lookup translates a 32-bit IPv4 address (or 128-bit IPv6 prefix) into a geographic record: country code, autonomous system number, city, latitude, and longitude. This translation relies on periodically updated databases—MaxMind GeoLite2 and IP2Location are the two most common—that partition the global IP space into hierarchical ranges, each annotated with location metadata.
The challenge for high-throughput environments is performing these lookups fast enough to keep pace with millions of packets per second. Three architectural choices dominate:
- User-space log enrichment: the kernel accepts or drops packets; a separate daemon tails connection logs, performs GeoIP lookups, and writes enriched records to a database. Simple but introduces seconds of delay.
- In-kernel BPF map: the XDP or tc-bpf program carries a radix trie or LPM (longest-prefix-match) BPF map preloaded with GeoIP ranges. Lookup happens in nanoseconds, but map size is constrained (kernel 5.x supports maps up to ~500 MB, enough for coarse country-level data but tight for city granularity).
- Hybrid telemetry stream: XDP samples a fraction of packets (1:100 or 1:1000), extracts source IPs, and sends them via a perf ring buffer to user space, where a lightweight Go or Rust collector performs full-resolution GeoIP lookup and pushes results into TimescaleDB or ClickHouse for dashboard rendering.
PAKKT adopts the hybrid model: the XDP engine running on each interface maintains per-rule counters (packets, bytes, top source IPs) in BPF maps, and the Go agent reads those maps every 30 seconds, enriches the top-N IPs with MaxMind GeoLite2 lookups, then transmits the time-series records over mTLS to the central panel. The panel aggregates data across all monitored agents and projects it onto a Leaflet.js world map with heatmap clustering.
Why Kernel-Level Telemetry Beats Syslog Parsing
Traditional approaches parse /var/log/auth.log or application access logs, run each IP through a GeoIP library, and update a dashboard every few minutes. This works for post-mortem forensics but fails during live attacks:
- Log I/O becomes a bottleneck above ~10k events/s; the filesystem cache churns, and the log daemon (rsyslog, journald) drops entries.
- Application logs record only accepted connections; XDP sees every packet before the network stack, including SYN floods that never reach the application.
- Regex parsing and string manipulation in Python or Bash consume orders of magnitude more CPU than BPF map reads in a compiled Go binary.
By embedding telemetry collection in the same eBPF program that enforces firewall rules, you guarantee that every blocked packet contributes to the geographic heatmap, with sub-microsecond per-packet overhead and zero risk of log truncation.
Key Metrics a GeoIP Traffic Map Should Surface
A static choropleth showing "requests by country" is pretty but operationally shallow. A production-grade GeoIP network traffic dashboard must answer tactical questions in real time:
| Metric | Why It Matters | PAKKT Implementation |
| Top source IPs (sorted by packet count) | Identify the heaviest hitters; single IP sending >100k pps is trivial to null-route. | XDP BPF map pakkt_top_ips, read every 30s by the agent, displayed in panel. |
| Top countries (sorted by packet count) | Reveals geographic concentration; 90% traffic from one country suggests targeted campaign. | Agent performs GeoIP lookup, panel aggregates by ISO country code. |
| Packets per second by destination port | Distinguishes game-server flood (port 25565) from SSH brute-force (port 22). | Per-rule counters in pakkt_rules map; TimescaleDB stores port × timestamp × pps. |
| Blocked vs. rate-limited vs. allowed | Confirms firewall efficacy; spike in allowed packets means rules need tightening. | Each XDP rule has rule_type (block/rate_limit/allow_only); agent exports separate counters. |
| ASN (Autonomous System Number) | Differentiates residential ISP from datacenter/VPN; ASN 24940 (Hetzner) hosting a botnet is noteworthy. | GeoLite2-ASN database included in agent lookup; displayed in "Top ASNs" panel widget. |
Interactive drill-down is equally critical. Clicking a country polygon should filter the "Top IPs" list to show only sources from that region, and clicking an IP should display its recent packet history (5-minute resolution), protocol breakdown (TCP/UDP/ICMP), and whether it appears on public threat feeds.
Real-Time vs. Historical Views
The "live" map refreshes every 30 seconds, showing the current 5-minute window. For incident response, you also need a time-machine: a date-range picker that re-renders the map for any historical interval stored in TimescaleDB. This lets you compare last Tuesday's attack geography with today's, correlate spikes with upstream route leaks, or generate compliance reports showing that 99.7% of blocked traffic originated outside your service region.
PAKKT's centralized panel retains per-agent metrics for 90 days by default (configurable; longer retention requires more PostgreSQL storage). The query engine uses TimescaleDB hypertables with automatic chunk compression, so even agents handling several million packets per second generate only a few megabytes of telemetry per day.
Dual-Layer Architecture: XDP + nftables + GeoIP
Effective geographic filtering requires stitching together three components: a fast stateless layer (XDP) for packet-rate limiting and coarse IP blacklists, a stateful layer (nftables) for connection tracking and per-source rate limits, and an enrichment layer (GeoIP) for visibility and policy decisions.
Layer 1: XDP Stateless Filtering
The PAKKT Engine—a single XDP program attached to the ingress interface—consults up to 256 simultaneous rules stored in a BPF map. Each rule specifies a port range, protocol, action (XDP_DROP, XDP_PASS, or rate-limit via token bucket), and optional min/max packet size. For example:
{
"port_start": 25565,
"port_end": 25565,
"protocol": "tcp",
"rule_type": "rate_limit",
"max_port_pps": 50000,
"min_packet_size": 60,
"max_packet_size": 1500
}
Every packet is evaluated in sub-microsecond time. If the source IP exists in the pakkt_blacklist BPF map (a hash map of IPv4/IPv6 addresses), the packet is dropped immediately—before the kernel allocates an skb, before conntrack, before iptables. This is the only defense that scales to multi-million-pps floods without kernel soft-lockups.
Layer 2: nftables Stateful Rules
XDP cannot track TCP connection state or enforce per-connection byte limits. For that, PAKKT provisions a dedicated inet pakkt nftables table with conntrack-aware rules. A typical SSH hardening rule looks like:
nft add rule inet pakkt input tcp dport 22 ct state new \
limit rate over 5/minute burst 10 packets \
add @ratelimit_ssh { ip saddr limit rate 3/minute } drop
Because the pakkt table lives in its own netfilter namespace, it never collides with Docker's DOCKER-USER chain, fail2ban's dynamic sets, or iptables-persistent rules. The agent synchronizes IP blacklist/whitelist entries into both the XDP map and an nftables set, ensuring that an IP blocked in the panel is rejected at both layers within one heartbeat cycle (30 seconds).
Layer 3: GeoIP Enrichment and Policy
Once telemetry flows into TimescaleDB, the panel's GeoIP module performs two tasks:
- Visualization: render source IPs as latitude/longitude markers on a Leaflet.js map, with color intensity proportional to packet count.
- Policy hints: flag when >80% of blocked traffic originates from countries where you have zero legitimate users, suggesting a blanket nftables geo-block (e.g.,
nft add rule inet pakkt input ip saddr @geoip_cn drop) might be appropriate.
Note that PAKKT does not auto-apply geographic blocks—operators retain full control. The panel highlights anomalies ("Last hour: 94% of drops from ASN 12345") and provides a one-click template to generate the corresponding nftables or XDP map update, which the operator reviews and deploys via the UI or the PAKKT public API.
Interpreting the Map: Attack Patterns and False Positives
Not every geographic cluster signals malice. Legitimate traffic exhibits patterns that novice operators sometimes mistake for attacks:
- CDN egress concentration: if your application sits behind Cloudflare or Fastly, inbound connections will appear to originate from a handful of data centers (San Jose, Frankfurt, Singapore). The true client IP is in the
X-Forwarded-Forheader, invisible to XDP. Solution: whitelist the CDN's published IP ranges in the XDP map. - University / corporate NAT: a single public IP representing 10,000 students will generate high packet counts from one geolocation. Check ASN; if it's an academic or enterprise network, rate-limit per connection (nftables
ct state new limit) rather than blocking the IP. - Mobile carrier CG-NAT: residential ISPs in India, Brazil, and Southeast Asia often place thousands of subscribers behind one IPv4 address. High packet count + residential ASN = probable legitimate traffic; high packet count + datacenter ASN = probable botnet.
Distinguishing Botnets from Flash Crowds
A flash crowd (sudden spike in legitimate users, e.g., a popular streamer joining your game server) and a DDoS botnet can produce similar packet-rate curves. The GeoIP map reveals the difference:
| Characteristic | Flash Crowd | Botnet |
| Geographic distribution | Follows your user base (e.g., 70% North America, 20% Europe, 10% Oceania) | Uniform global scatter or tight cluster in regions with cheap VPS (Eastern Europe, Southeast Asia) |
| ASN diversity | Mix of residential ISPs (Comcast, BT, Telstra) | Dominated by hosting ASNs (OVH, DigitalOcean, Alibaba Cloud) |
| Packet size distribution | Normal TCP handshake (60–1500 bytes) | Often minimum-size packets (40–60 bytes) to maximize pps |
| Connection duration | Established connections (nftables ct state established) |
Flood of SYN or ACK with no ESTABLISHED state |
Cross-reference the map with the "Protocol Breakdown" chart: a flash crowd will show a healthy mix of TCP handshakes completing into ESTABLISHED state, while a SYN flood will peg the NEW connection counter without corresponding ESTABLISHED increments.
Using the Map for Incident Triage
When an alert fires ("Agent eu-game-01: ingress >500k pps on port 25565"), the operator's workflow becomes:
- Open the GeoIP map filtered to that agent and port.
- Identify the top 3 countries by packet count. If one country dominates, click to drill down into top IPs from that country.
- Check ASN for those IPs. Datacenter ASN + no historical legitimate traffic = high-confidence block candidate.
- Add the top offending IPs to the blacklist via the panel UI; the agent updates the XDP map within 30 seconds.
- If the attack persists from new IPs in the same /24 or ASN, escalate to an nftables prefix block:
nft add rule inet pakkt input ip saddr 203.0.113.0/24 counter drop. - Monitor the "Blocked Packets" time-series graph; a successful mitigation shows the curve flattening while "Allowed Packets" (legitimate traffic) remains steady.
This loop—observe, correlate, block, verify—takes under two minutes with a visual map. Without geography, operators waste hours grepping logs and guessing whether 198.51.100.42 is a customer or an attacker.
Deploying GeoIP-Aware Protection in Your Stack
If you operate your own bare-metal or VPS infrastructure (Hetzner, OVH, Vultr, Linode, or any provider that grants root and kernel 5.x+), integrating GeoIP network traffic telemetry into your firewall is straightforward:
- Install the PAKKT agent: a single static Go binary, ~8 MB, no dependencies. It auto-detects network interfaces, compiles and loads the XDP program, and establishes mTLS to the central panel.
- Define XDP rules in the panel UI: specify which ports to protect, whether to block or rate-limit, and global/per-port packet-per-second thresholds.
- Enable nftables integration: the agent provisions the
inet pakkttable and synchronizes blacklist/whitelist sets. Existing iptables or Docker rules remain untouched. - Review the GeoIP dashboard: within 60 seconds of the first packets, the world map populates with source locations, and the "Top Countries" widget appears.
- Iterate rules: observe which countries/ASNs generate blocked traffic; tighten XDP rate limits or add nftables geo-blocks as needed.
Because PAKKT is kernel-level protection on your server, it complements—rather than replaces—upstream DDoS scrubbing (Cloudflare Magic Transit, OVH VAC, Path.net). The scrubbing service absorbs volumetric floods that saturate your uplink; PAKKT's XDP engine stops application-layer and low-volume sophisticated attacks that slip through volumetric filters, and the GeoIP map shows you exactly where those residual threats originate.
Integration with Pterodactyl and Other Panels
Game-server operators using Pterodactyl v1.x can deploy PAKKT via the official integration, which provisions one PAKKT agent per physical node and maps Pterodactyl's allocation ports to XDP rules automatically. When a new game server spins up on port 25565, the integration API creates a corresponding rate-limit rule; when the server stops, the rule is removed. The GeoIP map aggregates traffic across all allocations, so you see a single world view of attacks hitting your entire fleet.
Pelican (Pterodactyl's successor) and WHMCS integrations are in development. For custom setups, the PAKKT public API accepts RESTful calls (API key authentication) to create/update/delete rules, add IPs to blacklist/whitelist, and retrieve time-series metrics in JSON, enabling you to build your own orchestration.
Conclusion
A GeoIP network traffic map transforms opaque packet counters into spatial intelligence, letting operators distinguish coordinated attacks from organic user growth in seconds. By fusing XDP's line-rate filtering, nftables' stateful connection tracking, and MaxMind's continuously updated geolocation databases into a single pane of glass, platforms like PAKKT deliver the visibility and control that modern high-throughput environments demand—without the latency, cost, or vendor lock-in of cloud-based scrubbing services.
FAQ
Can I block entire countries using the GeoIP map data in PAKKT?
PAKKT's panel highlights which countries generate the most blocked traffic, but it does not auto-block by geography. You can manually add nftables rules (e.g., nft add rule inet pakkt input ip saddr @geoip_cn drop) or use the public API to maintain a custom GeoIP set. This design ensures you retain full policy control and avoid accidentally blocking legitimate users who appear to originate from unexpected regions due to VPNs or mobile roaming.
How accurate is GeoIP location for IPv6 traffic?
IPv6 geolocation accuracy varies by region. In North America and Western Europe, MaxMind GeoLite2 achieves country-level accuracy above 95% and city-level accuracy around 60–70%. In regions with sparse IPv6 deployment (parts of Africa, South Asia), accuracy drops because ISPs allocate large prefixes dynamically. PAKKT displays both the country code and ASN; cross-referencing ASN (which is authoritative from RIR data) with GeoIP often resolves ambiguities, especially for datacenter traffic.
Does rendering the GeoIP map on every dashboard refresh slow down the PAKKT agent or consume extra bandwidth?
No. The agent performs GeoIP lookups in user space on the top-N source IPs (default N=100) once per heartbeat cycle (30 seconds), using a local copy of the MaxMind database (~50 MB memory-mapped file). The lookup itself takes microseconds per IP. The agent then transmits only the enriched summary records (IP, country, ASN, packet count) over mTLS to the panel—typically a few kilobytes per cycle. The map rendering happens entirely in the browser (Leaflet.js) using cached tiles; the backend serves JSON, not images, so dashboard refreshes impose negligible load.
Deploy PAKKT in 30 seconds
Dual-layer kernel protection. XDP + nftables. Driven from a central panel. 7-day free trial.