Tor Analysis

Identifies Tor relay nodes, exit nodes, guard nodes, and obsolete Tor versions from the compiled relay directory.

The Tor analysis checker matches the client IP against the compiled Tor relay directory. Tor exit nodes are the most significant signal: they are the point at which anonymized traffic re-enters the public internet, and they are widely used by bots to avoid IP-based blocking. Guard and relay nodes carry lower risk but still indicate deliberate anonymization.

This checker runs in the cheap phase using the pre-loaded tor.mmdb database built from the Onionoo dataset.


How It Works

The checker looks up the client IP in tor.mmdb. When a match is found, it reads the relay record and evaluates several properties:

Running node: any active Tor relay applies runningNode as a base penalty.

Exit node: relays flagged as exit nodes apply an additional exitNode penalty. Exit nodes are the primary source of anonymized bot traffic because they are the visible egress point for Tor circuits.

Web exit capable: exit nodes with a policy that allows connections to ports 80 and 443 apply webExitCapable. An exit node that can reach web ports is more dangerous than one restricted to other protocols.

Guard node: relays flagged as guard nodes apply guardNode. Guard nodes are entry points to the Tor network and carry lower risk than exits.

Bad exit: relays flagged BadExit by the Tor directory authority apply badExit. These are nodes the Tor Project has marked as behaving maliciously or incorrectly.

Obsolete version: relays running an outdated Tor software version apply obsoleteVersion. Outdated relays may indicate misconfiguration or compromised infrastructure.


Configuration

server.ts
await defineConfiguration({
  store: { main: { driver: 'sqlite', name: './bot-detector.db' } },
  checkers: {
    enableTorAnalysis: {
      enable: true,
      penalties: {
        runningNode: 15,
        exitNode: 20,
        webExitCapable: 15,
        guardNode: 10,
        badExit: 40,
        obsoleteVersion: 10,
      },
    },
  },
})

All weights live inside the penalties: {} sub-object.

runningNode
number
Base penalty for any active Tor relay node. Default: 15.
exitNode
number
Additional penalty for relays with the Exit flag. Applied on top of runningNode. Default: 20.
webExitCapable
number
Additional penalty for exit nodes whose exit policy permits connections to ports 80 or 443. Default: 15.
guardNode
number
Additional penalty for relays with the Guard flag. Default: 10.
badExit
number
Penalty for relays marked BadExit by the Tor directory authority. Default: 40.
obsoleteVersion
number
Penalty for relays running an outdated Tor software version. Default: 10.

Reason Codes

CodeTrigger
TOR_ACTIVE_NODEIP is an active Tor relay.
TOR_EXIT_NODERelay has the Exit flag.
TOR_WEB_EXIT_CAPABLEExit relay allows connections to ports 80/443.
TOR_GUARD_NODERelay has the Guard flag.
TOR_BAD_EXITRelay is flagged BadExit by the directory authority.
TOR_OBSOLETE_VERSIONRelay is running an outdated Tor version.

A single web-capable exit node match produces runningNode + exitNode + webExitCapable = 50 points with default penalties. Combined with other cheap-phase signals such as a missing Accept-Language header or a hosting ASN, this can reach banScore without the heavy phase running.
Keep the tor.mmdb database current by running bot-detector refresh regularly. The Tor relay directory changes frequently as relays join and leave the network.
Logo