Plugins

IP Intelligence

Geolocation, ASN, and threat detection enrichment for every request — all data embedded in the binary.

IP Intelligence Plugin

The IP Intelligence plugin enriches every request with geolocation, ASN, and threat detection data. All data is embedded in the binary — zero external dependencies.

Configuration

{
  "plugins": {
    "ip_intel": {
      "enabled": true
    }
  }
}

That's it. No URLs, no storage directories, no refresh intervals. Everything is baked in.

What it provides

FieldTypeSourceDescription
countrystringDB-IP City MMDBISO 3166-1 alpha-2 country code
regionstringDB-IP City MMDBRegion/state code
citystringDB-IP City MMDBCity name
asnnumberDB-IP ASN MMDBAutonomous System Number
as_orgstringDB-IP ASN MMDBASN organization name
providerstringProvider ASN registryHosting/cloud provider label (e.g. "Hostinger", "Hetzner")
is_vpnboolX4BNet VPN listIP belongs to a known VPN provider
is_torboolTor ProjectIP is a current Tor exit node
is_datacenterboolASN-basedIP's ASN is a known datacenter/hosting provider
is_proxyboolFireHOLIP is a known anonymous proxy
is_mobilebool—Reserved (currently null)
is_residentialbool—Reserved (currently null)
is_residential_proxybool—Reserved (currently null)
network_typestringComputedNetwork classification
risk_scorenumberComputedRisk score 0-100

Network type classification

The network_type field is determined by the first matching flag:

PriorityConditionnetwork_type
1is_tor = true"tor"
2is_vpn = true"vpn"
3is_datacenter = true"datacenter"
4is_residential_proxy = true"residential_proxy"
5is_proxy = true"proxy"
6is_mobile = true"mobile"
7is_residential = true"residential"
8None matchnull

Risk score

The risk_score is a 0-100 integer calculated from threat flags:

FactorScore Added
Tor exit node+40
Residential proxy+30
VPN+25
Anonymous proxy+20
Datacenter/hosting+10

Scores are capped at 100. A clean residential IP gets 0.

Risk score thresholds

RangeInterpretation
0Clean residential IP
10Datacenter/hosting
20-25Proxy or VPN
35VPN + datacenter
40Tor exit node
50+Multiple threat indicators
70+High risk (Tor + VPN + proxy)

Edge detection

The plugin detects the request edge type based on the peer IP:

Edge TypeDetectionDescription
CloudflarePeer IP in Cloudflare CIDR rangesRequest came via Cloudflare
ProxyPeer IP is private (RFC 1918)Behind a reverse proxy
DirectNeither of aboveDirect connection

This is used to determine which IP headers to trust.

How it works

Request arrives
    │
    ▼
1. Check LRU cache (65,536 entries)
    │
    ├── Cache HIT → return cached result (~1μs)
    │
    └── Cache MISS → full lookup:
        │
        ├── 2. MMDB city lookup → country, region, city
        ├── 3. MMDB country fallback (if city missed)
        ├── 4. MMDB ASN lookup → asn, as_org
        ├── 5. ASN registry lookup: provider-asns.txt → is_datacenter, provider
        │        (fallback: hosting-asns.txt → is_datacenter)
        ├── 6. CIDR check: vpn.txt → is_vpn
        ├── 7. CIDR check: tor.txt → is_tor
        ├── 8. CIDR check: proxy.txt → is_proxy
        ├── 9. Classify network_type
        ├── 10. Calculate risk_score
        │
        └── Cache result (~5μs total)

Embedded data sources

MMDB databases (MaxMind format)

FileSizeRecordsSource
dbip-city-lite.mmdb122 MB~2.8M networksDB-IP CC-BY 4.0
dbip-asn-lite.mmdb9.2 MB~1.1M networksDB-IP CC-BY 4.0
dbip-country.mmdb8.0 MB~2.8M networksDB-IP CC-BY 4.0

CIDR lists

FileSizeEntriesSourceRefresh
vpn.txt177 KB11,271 CIDRsX4BNetDaily
tor.txt19 KB1,358 IPsTor ProjectHourly
cloudflare.txt336 B22 CIDRsCloudflareDaily
proxy.txt0 B0FireHOLWeekly

ASN lists (datacenter / hosting detection)

FileSizeEntriesSourceRefresh
provider-asns.txt~1.5 KB38 ASNsVersioned registry (ASN|Label) — add one line per providerManual (one-line edit)
hosting-asns.txt4.3 KBASNsbrianhama/bad-asn-listWeekly

Datacenter detection is ASN-based: the ASN MMDB resolves the client IP to its ASN (already part of the ~5 μs lookup), and these lists classify the network. No datacenter IP ranges are embedded — the ASN identifies the provider regardless of which blocks it announces.

Performance

MetricValue
Cache hit latency~1 μs
Cache miss latency~5 μs
Cache size65,536 entries
Cache memory~13 MB
Startup time~200 ms

Environment variables

VariableDefaultDescription
QUAYEL_IP_INTEL_CACHE_SIZE65536LRU cache size for IP lookups

Using in firewall rules

IP intel fields can be used in firewall conditions:

{
  "conditions": [
    { "left": "ip.country", "operator": "in", "value": ["US", "CA"] }
  ]
}
{
  "conditions": [
    { "left": "ip.is_tor", "operator": "equals", "value": true }
  ]
}
{
  "conditions": [
    { "left": "ip.risk_score", "operator": "greater_than", "value": 30 }
  ]
}
{
  "conditions": [
    { "left": "ip.asn", "operator": "in", "value": [13335, 16509] }
  ]
}

Updating data

To update the embedded data:

# 1. Copy fresh MMDB files
cp /path/to/dbip-city-lite-2026-01.mmdb src/data/dbip-city-lite.mmdb
cp /path/to/dbip-asn-lite-2026-01.mmdb src/data/dbip-asn-lite.mmdb

# 2. Copy fresh CIDR lists
cp /var/lib/quayel/ip-intel/lua/*.txt src/data/

# 3. Rebuild
cargo build --release
strip target/release/quayel-gateway

# 4. Deploy
systemctl restart quayel-gateway

See Data Sources — Updating Embedded Data for the full update procedure with source URLs.

Log output

Every request produces an ip_intel section in the JSONL log:

{
  "ip_intel": {
    "country": "US",
    "region": "CA",
    "asn": 16509,
    "network_type": "datacenter",
    "is_vpn": false,
    "is_proxy": false,
    "is_datacenter": true,
    "is_mobile": null,
    "is_tor": false,
    "risk_score": 10
  }
}
Copyright © 2026