rkn-block-checker/README.md
2026-04-29 22:31:04 +03:00

6.3 KiB

RKN Block Checker

CI Python License: MIT

A small CLI that figures out whether the connection you're sitting on is in an RKN/TSPU-blocked zone — and, more usefully, what kind of block it is (DNS poisoning, TCP reset, TLS DPI on SNI, or an ISP stub page).

The point isn't "site X doesn't open." Browsers already tell you that. The point is to look at each layer of the stack independently and report where it broke. That tells you a lot more about your situation than a generic "this site can't be reached" page.

Example output

======================================================================
  RKN Block Checker
======================================================================
  IP:       95.165.xxx.xxx
  ISP:      AS12389 Rostelecom
  Location: Moscow, Moscow, RU
----------------------------------------------------------------------

Whitelist (should always work)
  name          verdict            TCP     TLS     PLT  status
  ------------------------------------------------------------
  gosuslugi     ✓ OK              18ms    42ms   380ms  200
  yandex        ✓ OK               8ms    25ms    95ms  200
  sberbank      ✓ OK              12ms    38ms   250ms  200
  vk            ✓ OK               9ms    28ms   180ms  200
  ...

Blacklist (RKN-restricted)
  name          verdict            TCP     TLS     PLT  status
  ------------------------------------------------------------
  instagram     ✗ TLS BLOCK       22ms       —       —  —
    └ TLS reset — DPI cutting on SNI (typical RKN/TSPU)
  twitter/x     ✗ TLS BLOCK       24ms       —       —  —
    └ TLS timeout — silent drop after ClientHello
  rutracker     ✗ HTTP STUB       18ms    45ms   120ms  200
    └ response body matches an ISP stub-page marker
  protonvpn     ✗ DNS BLOCK          —       —       —  —
    └ system DNS doesn't resolve, DoH does — DNS poisoning
  ...

======================================================================
  Summary
----------------------------------------------------------------------
  Whitelist: 21/21 working
  Blacklist: 3/15 open, 12/15 blocked

  → You ARE in an RKN-blocked zone.

  Block types in the blacklist:
    ✗ TLS BLOCK: 8
    ✗ DNS BLOCK: 2
    ✗ HTTP STUB: 2
======================================================================

Install

Python 3.10+.

git clone https://github.com/MayersScott/rkn-block-checker.git
cd rkn-block-checker
pip install -r requirements.txt
python -m rkn_checker

Or as a package:

pip install -e .
rkn-check

Usage

rkn-check [-h] [--json] [--white] [--black] [--timeout TIMEOUT]
          [--workers WORKERS] [-v]
flag what it does
--json machine-readable JSON instead of the colored report
--white only the control (whitelist) targets
--black only the blacklist targets
--timeout per-probe timeout in seconds (default 5.0)
--workers thread pool size for parallel checks (default 10)
-v / -vv logging at INFO / DEBUG

JSON output pipes nicely into jq:

rkn-check --json | jq '.blacklist[] | select(.verdict != "OK") | .name'

How it works

For each target the tool walks DNS → TCP → TLS → HTTP and stops at the first thing that fails. Whichever layer broke becomes the verdict.

layer probe what a failure means
DNS system resolver vs Cloudflare DoH if only the system fails, the ISP is poisoning DNS — the cheapest, oldest form of blocking
TCP plain TCP handshake on :443 a RST is IP-level blackholing. Rare — most ISPs don't bother
TLS TLS handshake with SNI = target host reset/timeout here (with TCP working fine) is the classic TSPU/DPI signature: the middlebox sees the SNI and tears the connection down
HTTP GET after handshake completes 451, or an ISP stub page returning 200 with a "blocked by RKN" body

Two probes are worth calling out:

System DNS vs DoH. The cheapest way to "block" a site is to make the ISP's DNS lie. Every host is resolved twice — once via socket (which uses whatever resolver the OS is configured for, usually the ISP's) and once via Cloudflare's DoH endpoint, which the ISP can't intercept. Disagreement is the smoking gun.

TLS handshake with SNI. Modern TSPU equipment doesn't drop the TCP connection — it lets you connect, reads the SNI extension out of the ClientHello, and then sends a RST or simply stops responding. So we have to actually start the TLS handshake to see this. A TLS_BLOCK after a clean TCP_OK is the unambiguous fingerprint of DPI-based blocking.

Layout

rkn_checker/
  __main__.py     # python -m rkn_checker
  cli.py          # argparse + entry point
  core.py         # orchestrates DNS -> TCP -> TLS -> HTTP
  dns.py          # system resolver + Cloudflare DoH
  network.py      # raw TCP and TLS probes
  http.py         # HTTP GET + stub-page detection
  output.py       # colored CLI report
  targets.py      # whitelist, blacklist, stub markers
  models.py       # CheckResult, Verdict
tests/            # pytest, all network calls mocked

Tests

pip install -r requirements-dev.txt
pytest

No network calls in the test suite — every probe is mocked, so it runs the same in CI, on a plane, or behind a corporate proxy.

Caveats

  • IPv4 only. Some Russian ISPs treat IPv6 differently (often less filtered) but the v4 path is what users actually experience in practice.
  • The target lists are hard-coded (~20 sites per category). That's enough for a verdict but won't catch a block that affects only one specific resource. To extend — rkn_checker/targets.py.
  • One-shot snapshot, no retries, no longitudinal tracking. If you want to monitor a connection over time, run rkn-check --json from cron.
  • Stub markers are mostly Russian-language phrases; false positives on unrelated sites that happen to contain the same words are theoretically possible but I haven't seen one yet.

License

MIT.