# dnstt_exporter Prometheus exporter for DNSTT client/session metrics. `dnstt_exporter` observes DNSTT DNS traffic on a local Linux host and exports aggregate Prometheus metrics. It does not proxy, terminate, or configure DNSTT; it passively decodes DNSTT session IDs from DNS query names. ## Usage ```sh sudo dnstt_exporter \ -dnstt.domain tunnel.example.com \ -dnstt.port 53 \ -geoip.country-database /path/to/GeoLite2-Country.mmdb \ -geoip.asn-database /path/to/GeoLite2-ASN.mmdb \ -web.listen-address :9713 ``` The exporter needs permission to open an `AF_PACKET` raw socket. Run it as root or grant the binary `CAP_NET_RAW`. Metrics are served at `http://127.0.0.1:9713/metrics` by default. ## How It Works `dnstt_exporter` opens a Linux `AF_PACKET` raw socket and passively watches UDP DNS traffic on the configured DNSTT port. It parses IPv4 and IPv6 packets, matches DNS query names against the configured DNSTT domain, and decodes the DNSTT session ID from the query-name prefix. The exporter treats a session as active when it has seen a query for that session within the last 30 seconds. Peak client counts are the highest active session counts observed since the exporter started. GeoIP labels are based on the resolver address seen by the server. For incoming queries this is the packet source address; for outgoing responses it is the packet destination address. This may be a recursive resolver such as an ISP DNS server, Cloudflare, Google, or Quad9, not the original DNSTT client. The exporter does not run `dnstt-server`, proxy traffic, terminate DNSTT, or decrypt tunnel payloads. ## Metrics All DNSTT metrics use a `domain` label. If `-geoip.country-database` is set, metrics also include `country`. If `-geoip.asn-database` is set, metrics also include `asn`. Unmapped countries use `ZZ`; unmapped ASNs use `0`. - `dnstt_active_clients` - `dnstt_peak_clients` - `dnstt_queries_total` - `dnstt_bytes_in_total` - `dnstt_bytes_out_total` - `dnstt_sessions_total` ## Grafana Queries Use `$domain` as a Grafana variable for the DNSTT domain, for example `t2.bypasscensorship.org`. Replace `$__rate_interval` with a fixed range such as `5m` if you are not using Grafana's built-in interval variables. - Title: Current active clients - Description: Current number of active DNSTT sessions for the selected domain. - Visualization: Stat or gauge. ```promql sum(dnstt_active_clients{domain="$domain"}) ``` - Title: Peak active clients - Description: Highest active DNSTT session count observed since the exporter started. - Visualization: Stat. ```promql sum(dnstt_peak_clients{domain="$domain"}) ``` - Title: Active clients by country - Description: Current active DNSTT sessions grouped by resolver country. - Visualization: Geomap, bar chart, or table. ```promql sum by (country) (dnstt_active_clients{domain="$domain"}) ``` - Title: Top countries by active clients - Description: Countries with the most active DNSTT sessions right now. - Visualization: Bar chart. ```promql topk(10, sum by (country) (dnstt_active_clients{domain="$domain"})) ``` - Title: Active clients by ASN - Description: Current active DNSTT sessions grouped by resolver ASN. - Visualization: Bar chart or table. ```promql sum by (asn) (dnstt_active_clients{domain="$domain"}) ``` - Title: Top ASNs by active clients - Description: Resolver ASNs with the most active DNSTT sessions right now. - Visualization: Bar chart. ```promql topk(10, sum by (asn) (dnstt_active_clients{domain="$domain"})) ``` - Title: Active clients by country and ASN - Description: Current active DNSTT sessions split by both resolver country and resolver ASN. - Visualization: Table. ```promql sum by (country, asn) (dnstt_active_clients{domain="$domain"}) ``` - Title: Top country/ASN pairs by active clients - Description: Country and ASN combinations with the most active DNSTT sessions right now. - Visualization: Bar chart or table. ```promql topk(20, sum by (country, asn) (dnstt_active_clients{domain="$domain"})) ``` - Title: DNS query rate - Description: Total observed DNSTT DNS queries per second for the selected domain. - Visualization: Time series. ```promql sum(rate(dnstt_queries_total{domain="$domain"}[$__rate_interval])) ``` - Title: DNS query rate by country - Description: Observed DNSTT DNS queries per second grouped by resolver country. - Visualization: Stacked time series or bar chart. Use stacked time series for trends over time, and bar chart for current top countries. ```promql sum by (country) (rate(dnstt_queries_total{domain="$domain"}[$__rate_interval])) ``` - Title: Top ASNs by DNS query rate - Description: Resolver ASNs producing the highest DNSTT DNS query rates. - Visualization: Bar chart. ```promql topk(10, sum by (asn) (rate(dnstt_queries_total{domain="$domain"}[$__rate_interval]))) ``` - Title: Inbound DNS traffic rate - Description: Bytes per second received in DNSTT DNS queries. - Visualization: Time series. ```promql sum(rate(dnstt_bytes_in_total{domain="$domain"}[$__rate_interval])) ``` - Title: Outbound DNS traffic rate - Description: Bytes per second sent in DNSTT DNS responses. - Visualization: Time series. ```promql sum(rate(dnstt_bytes_out_total{domain="$domain"}[$__rate_interval])) ``` - Title: DNS traffic rate by country - Description: Combined inbound and outbound DNSTT DNS bytes per second grouped by resolver country. - Visualization: Geomap, stacked time series, or bar chart. ```promql sum by (country) ( rate(dnstt_bytes_in_total{domain="$domain"}[$__rate_interval]) + rate(dnstt_bytes_out_total{domain="$domain"}[$__rate_interval]) ) ``` - Title: Total observed sessions - Description: Total unique DNSTT sessions observed since the exporter started. - Visualization: Stat. ```promql sum(dnstt_sessions_total{domain="$domain"}) ``` - Title: New session rate - Description: New DNSTT sessions observed per second. - Visualization: Time series. ```promql sum(rate(dnstt_sessions_total{domain="$domain"}[$__rate_interval])) ``` - Title: New session rate by country - Description: New DNSTT sessions per second grouped by resolver country. - Visualization: Stacked time series, geomap, or bar chart. ```promql sum by (country) (rate(dnstt_sessions_total{domain="$domain"}[$__rate_interval])) ``` ## Development ```sh go test ./... go build ./cmd/dnstt_exporter ```