6.3 KiB
RKN Block Checker
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 --jsonfrom 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.