traefik_classifier

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

README

Traefik Classifier

Traefik plugin that registers a custom middleware for getting data from MaxMind GeoIP databases and classifying traffic by type (datacenter, VPN, Tor, AI crawler).

All results are passed downstream via HTTP request headers.

Features

  • GeoIP lookups — City, Country, ASN data from MaxMind GeoLite2/GeoIP2 databases
  • Datacenter detection — ASN-based, using bad-asn-list
  • VPN detection — CIDR-based, using X4BNet/lists_vpn
  • Tor exit node detection — IP-based, using torproject.org bulk exit list
  • AI crawler detection — User-Agent based (GPTBot, ClaudeBot, Google-Extended, Bytespider, etc.)
  • Fail-safe — Classification errors are caught with recover(); traffic always flows
  • Auto-refresh — Data files are reloaded periodically (default: every 6 hours)

Supports both GeoIP2 and GeoLite2 databases.

Breaking Changes

[!IMPORTANT] Header rename: All GeoIP headers changed from GeoIP-* to X-GeoIP-* (e.g. GeoIP-CountryX-GeoIP-Country). Update any downstream consumers that read these headers.

Headers

GeoIP Headers
Header Description
X-GeoIP-Country Country name (e.g. "Germany")
X-GeoIP-Country-Code ISO country code (e.g. "DE")
X-GeoIP-Region Region name (e.g. "Bavaria")
X-GeoIP-Region-Code Region code (e.g. "BY")
X-GeoIP-City City name (e.g. "Munich")
X-GeoIP-Postal-Code Postal code
X-GeoIP-Latitude Latitude
X-GeoIP-Longitude Longitude
X-GeoIP-Accuracy-Radius Accuracy radius in meters
X-GeoIP-Geohash Geohash
X-GeoIP-Continent Continent name
X-GeoIP-Continent-Code Continent code
X-GeoIP-ASN-System-Number ASN number (e.g. "16509")
X-GeoIP-ASN-Organization ASN organization (e.g. "AMAZON-02")
X-GeoIP-IPAddress Resolved client IP address
Traffic Classification Headers
Header Values Description
X-Traffic-Type residential, datacenter, vpn, tor, ai-crawler Overall traffic classification
X-Traffic-Datacenter true / false IP belongs to a known datacenter ASN
X-Traffic-VPN true / false IP belongs to a known VPN range
X-Traffic-Tor true / false IP is a known Tor exit node
X-Traffic-AI-Bot true / false User-Agent matches a known AI crawler

Priority order for X-Traffic-Type: tor > vpn > ai-crawler > datacenter > residential.

Individual flags are independent — a request can be both X-Traffic-Datacenter: true and X-Traffic-Tor: true.

Installation

Docker Compose

Simple example to run in docker compose with auto download maxmind database

docker-compose.yaml

services:

  traefik:
    image: "traefik:v3.2"
    container_name: "traefik"
    restart: unless-stopped
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entryPoints.web.address=:80"
      - "--experimental.localPlugins.traefikgeoip.moduleName=github.com/WebConcern/traefik-classifier"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "../.:/plugins-local/src/github.com/WebConcern/traefik-classifier"
      - geoipupdate_data:/usr/share/GeoIP
    networks:
      - traefikgeoip_example

  whoami:
    image: "traefik/whoami"
    container_name: "traefik-whoami"
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`localhost`)"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.middlewares.traefikgeoip.plugin.traefikgeoip.cityDbPath=/usr/share/GeoIP/GeoLite2-City.mmdb"
      - "traefik.http.middlewares.traefikgeoip.plugin.traefikgeoip.asnDbPath=/usr/share/GeoIP/GeoLite2-ASN.mmdb"
      - "traefik.http.middlewares.traefikgeoip.plugin.traefikgeoip.lightMode=true"
      - "traefik.http.middlewares.traefikgeoip.plugin.traefikgeoip.ipHeader=X-IP"
      - "traefik.http.middlewares.traefikgeoip.plugin.traefikgeoip.iso88591=true"
      # - "traefik.http.middlewares.traefikgeoip.plugin.traefikgeoip.preferXForwardedForHeader=true"
      # - "traefik.http.middlewares.traefikgeoip.plugin.traefikgeoip.failInError=true"
      - "traefik.http.routers.whoami.middlewares=traefikgeoip"
    networks:
      - traefikgeoip_example

  geoipupdate:
    container_name: cii_geoipupdate
    image: ghcr.io/maxmind/geoipupdate
    restart: unless-stopped
    # restart: on-failure
    env_file:
      - ./maxmind.env
    volumes:
      - geoipupdate_data:/usr/share/GeoIP
    networks:
      - traefikgeoip_example

volumes:
  geoipupdate_data:

networks:
  traefikgeoip_example:
    name: traefikgeoip_example
    driver: bridge

Request your free maxmind credentials in site and up in

maxmind.env

GEOIPUPDATE_ACCOUNT_ID=6025842
GEOIPUPDATE_LICENSE_KEY=abQ2rY_UMmru2Gd6LrbfGcrmKFwvR1duEDPZ_nmw
GEOIPUPDATE_EDITION_IDS=GeoLite2-ASN GeoLite2-City GeoLite2-Country
GEOIPUPDATE_FREQUENCY=72
Kubernetes

The tricky part of installing this plugin into containerized environments, like Kubernetes, is that a container should contain a database within it.

[!WARNING] Setup below is provided for demonstration purpose and should not be used on production. Traefik's plugin site is observed to be frequently unavailable, so plugin download may fail on pod restart.

Tested with official Traefik chart version 26.0.0.

The following snippet should be added to values.yaml:

experimental:
  plugins:
    traefik-classifier:
      moduleName: github.com/WebConcern/traefik-classifier
      version: v0.1.0
deployment:
  additionalVolumes:
    - name: geoip2
      emptyDir: {}
  initContainers:
    - name: download
      image: alpine
      volumeMounts:
        - name: geoip2
          mountPath: /tmp/geoip2
      command:
        - "/bin/sh"
        - "-ce"
        - |
          wget -P /tmp https://raw.githubusercontent.com/thiagotognoli/traefikgeoip/main/geolite2.tgz
          tar --directory /tmp/geoip2 -xvzf /tmp/geolite2.tgz
additionalVolumeMounts:
  - name: geoip2
    mountPath: /geoip2
Create Traefik Middleware

GeoIP only:

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: traefik-classifier
  namespace: traefik
spec:
  plugin:
    traefik-classifier:
      cityDbPath: "/geoip2/GeoLite2-City.mmdb"
      asnDbPath: "/geoip2/GeoLite2-ASN.mmdb"

GeoIP + traffic classification:

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: traefik-classifier
  namespace: traefik
spec:
  plugin:
    traefik-classifier:
      cityDbPath: "/geoip2/GeoLite2-City.mmdb"
      asnDbPath: "/geoip2/GeoLite2-ASN.mmdb"
      datacenterFile: "/data/traffic-classifier/bad-asn-list.csv"
      vpnFile: "/data/traffic-classifier/vpn-ipv4.txt"
      torFile: "/data/traffic-classifier/tor-exits.txt"
      refreshSeconds: 21600

Configuration

Name Description Default
cityDbPath Container path to City GeoIP database. ""
countryDbPath Container path to Country GeoIP database. ""
asnDbPath Container path to ASN GeoIP database. ""
preferXForwardedForHeader Use X-Forwarded-For header to extract IP address. false
ipHeader Alternate header for IP. ""
failInError Fail to start plugin on error. false
debug Enable debug messages. false
iso88591 Encode in ISO-8859-1. false
lightMode Reduce headers to essential fields only. false
datacenterFile Path to CSV file with datacenter ASNs (e.g. bad-asn-list.csv). ""
vpnFile Path to text file with VPN CIDR ranges. ""
torFile Path to text file with Tor exit node IPs. ""
aiBotFile Path to text file with AI bot UA substrings (one per line). Overrides built-in list. ""
refreshSeconds Seconds between data file reloads. 21600

Data Sources

The traffic classifier uses externally maintained lists:

Detection Source Format
Datacenter ASNs bad-asn-list CSV (first column = ASN number)
VPN ranges X4BNet/lists_vpn One CIDR per line
Tor exit nodes torproject.org One IP per line
AI crawlers Built-in (or file via aiBotFile) User-Agent substring match
AI Crawlers Detected

GPTBot, ChatGPT-User, OAI-SearchBot, ClaudeBot, Claude-Web, Google-Extended, Bytespider, CCBot, FacebookBot, anthropic-ai, PerplexityBot, Cohere-ai, meta-externalagent

Development

Install Go, golangci-lint, yaegi and just

brew install go golangci-lint just
go install github.com/traefik/yaegi/cmd/yaegi@latest

To run linter and tests execute this command

just test

Original Plugin

This project is a fork of https://github.com/thiagotognoli/traefikgeoip

which is itself a fork of https://github.com/traefik-plugins/traefikgeoip2

and some parts of https://github.com/Maronato/traefik_geoip

Documentation

Overview

Package traefikgeoip is a Traefik plugin for GeoIP lookups and traffic classification.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateConfig

func CreateConfig() *lib.Config

CreateConfig creates the default plugin configuration.

func New

func New(_ context.Context, next http.Handler, cfg *lib.Config, name string) (http.Handler, error)

New creates a new traefik-classifier plugin instance.

Types

This section is empty.

Directories

Path Synopsis
Package geoip2 is a module for GeoIP
Package geoip2 is a module for GeoIP
package geoip2_iso88591 is a module for GeoIP
package geoip2_iso88591 is a module for GeoIP
Package lib package contains traefikgeoip implementations.
Package lib package contains traefikgeoip implementations.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL