rkn-block-checker: diagnose RKN/TSPU blocks layer by layer
Diagnose RKN/TSPU internet blocks layer by layer (DNS, TCP, TLS, HTTP)
At a glance
- What is it?
- A Python CLI that walks DNS, TCP, TLS and HTTP for each target and reports which layer broke, so you can tell DNS poisoning from SNI-based DPI. It is a diagnostic, not a circumvention tool, and its own README says a single vantage point cannot prove censorship.
- Who is it for?
- Adopt it if you want a per-layer verdict on a connection you already suspect is filtered, or if you need machine-readable snapshots of block type over time. Skip it if you need a bypass tool or a legally defensible measurement: the README itself notes that TLS DPI and TCP reset signals can also come from server-side problems, and a single vantage point cannot separate the two.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: "site X doesn't open" tells you nothing actionable
A browser failure page collapses four different failures into one sentence. rkn-block-checker's README makes the case directly: the point is not that a site does not open, it is to look at each layer of the stack independently and report where it broke. That distinction matters because the remedy differs. A poisoned DNS answer is fixed by a different resolver. An SNI-triggered TLS teardown is not fixed by anything at the resolver level. An ISP stub page returning HTTP 200 is not a network failure at all, it is a substituted response.
The tool is aimed at people who need that layer information rather than a yes or no. The README names three: someone choosing a circumvention tool, someone filing a useful bug report, and someone who simply wants to know what is happening to their traffic. It is a command line program, packaged on PyPI as rkn-block-checker with the entry point rkn-check, and it targets Python 3.10 and above. It is not a consumer app and not a browser extension.
How rkn-check walks DNS, TCP, TLS and HTTP
The mechanism is a sequential probe per target. According to the README, rkn-check walks DNS, then TCP, then TLS, then HTTP for each target and stops at the first thing that fails. Whichever layer broke becomes the verdict. That stop-at-first-failure design is what makes the output readable: you get one label per site instead of a matrix of four booleans to interpret yourself.
The classification depends on matching known fingerprints. The README lists four. DNS poisoning is the cheapest and oldest, where the ISP resolver lies about a domain; the example output shows it as a case where system DNS does not resolve but DoH does. TCP reset is IP-level blackholing, which the README calls rare in practice. TLS DPI on SNI is described as the modern TSPU/RKN signature, where a middlebox watches the SNI extension in the TLS ClientHello and tears the connection down. HTTP stub pages are an ISP-controlled page served back with a blocked-by-RKN body, often with status 200 or the rarer 451.
Confidence is encoded in the label rather than hidden. A cross mark means a high-confidence diagnosis such as DNS poisoning confirmed by DoH, HTTP 451, or a known stub-page marker. A tilde with LIKELY means a known censorship pattern matched but one signal cannot rule out a server-side issue. A question mark means the symptom is ambiguous. The summary line carries the same calibration, printing high confidence, medium confidence or inconclusive, and the README states it never claims more certainty than the underlying signals support.
The scan compares two groups. There are roughly 21 control sites expected to always work (gosuslugi, yandex, sberbank, vk in the sample output) and roughly 15 RKN-restricted targets. The control group is the part that gives the summary its meaning: if the whitelist is failing too, the problem is not selective filtering.
Install and first run
Installation is one pip command, and the tool needs no configuration file to produce a first result.
pip install rkn-block-checker
rkn-checkThe README states this probes a built-in list of sites, classifies each failure by layer, and prints a verdict, with no config and nothing to edit. Expect a header with your public IP, ISP and location, then a whitelist table, a blacklist table, and a summary that counts block types in the blacklist.
For a single URL without the built-in lists, pass --url. It can be repeated.
rkn-check --url https://example.com
rkn-check --url example.com --url google.comThe README notes this skips the built-in lists and runs an ad-hoc check, and that there is no summary verdict because there is no control group to compare against.
Machine-readable output goes through --json, which the README pairs with jq. This one lists only DPI-style blocks, where TCP succeeded and TLS died:
rkn-check --json | jq '.blacklist[] | select(.verdict == "TLS_BLOCK" and .tcp_ok)'For repeated runs, the README gives a cron-oriented form that skips the public IP lookup so the tool does not hit ipinfo.io on every tick and the JSON does not carry your address:
rkn-check --json --no-self-info > "snapshots/$(date -I).json"There is also a local web dashboard, started with rkn-check startweb, which the README says listens on http://127.0.0.1:7777 and accepts a custom port such as --port 8080. A Dockerfile and docker-compose.yml ship in the repository; the compose file builds the image and runs the container with --help as its default command.
Verdict confidence is the honest part, and the weakest part
The confidence calibration is the most defensible design decision in the project, and it also bounds what the tool can prove. The README is explicit that most blacklist failures matching censorship patterns can also be caused by server-side issues, and that a control vantage point would confirm. That is a real limitation, not a disclaimer bolted on for modesty: a TLS handshake dropped after ClientHello looks the same whether a middlebox is filtering SNI or the origin is simply unhealthy.
So the output is a hypothesis ranking, not a measurement. The medium-confidence summary in the example output says as much in its own text. If you need to distinguish censorship from an outage, this tool alone will not do it, and the README does not claim otherwise.
There are structural constraints worth noting. The whitelist and blacklist are built-in, which means the verdict's baseline drifts as the lists age; the version history shows releases at v0.5.0, v0.5.1 and v0.6.0, so list updates arrive with releases rather than on their own. The tool also depends on requests, and the optional proxy extra pulls in PySocks, which suggests proxy-routed checks are supported but the README excerpt does not document how to select one. The usage block also lists an --identify flag whose behaviour is not described in the README excerpt. Treat both as things to read the full usage text for before relying on them.
One more boundary: this is a client-side probe from a single network. It cannot tell you what a site looks like from outside the filtered zone, and it cannot tell you whether a block is national or specific to your ISP.
Where it fits next to OONI and plain curl
The obvious comparison is OONI Probe, and the difference is scope and infrastructure. OONI is a measurement platform: probes submit results to a central collector, so many vantage points can be compared and a finding can be corroborated across networks and countries. rkn-block-checker runs locally, prints to your terminal or a JSON file you own, and does not upload anything. That is a genuine advantage for privacy and for offline or air-gapped use, and a genuine disadvantage for evidentiary weight, because a single local result has no corroboration built in.
The lower-tech alternative is doing it by hand: dig for DNS, curl for TCP and TLS, and read the response body. That works, and it is exactly the sequence rkn-check automates. What you get from the tool is the stop-at-first-failure logic, the fingerprint matching for stub pages and SNI teardown, the control group, and the calibrated labels. What you give up is the ability to script an arbitrary probe the tool does not know about.
Between those two, the choice is about whether you want a repeatable verdict vocabulary. If you are collecting snapshots over weeks and want to count block types, the JSON output and fixed verdict strings are the reason to use it. If you need a defensible, multi-vantage-point measurement, this is the wrong instrument.
Maintenance, licence and what upgrades cost you
The repository is not archived, and the last push was on 2026-09-12, the same day as the v0.6.0 release. Earlier releases landed on 2026-05-09 and 2026-06-12, so the cadence is release-driven rather than continuous. The practical consequence is that the built-in target lists change only when you upgrade; a pinned older version will keep probing a stale set of domains.
The dependency surface is small, which keeps upgrades cheap. The only runtime dependency is requests>=2.31, with PySocks>=1.7.1 as an optional proxy extra and pytest plus pytest-cov for development. Python 3.10 or newer is required per pyproject.toml. If you install from PyPI you are pulling a wheel built by the maintainer; the Dockerfile in the repository builds from source on python:3.12-slim, installs ca-certificates, and runs the container as a non-root rkncheck user, which is the more reproducible path if you care about the exact build.
The licence is MIT, declared both in pyproject.toml and as a LICENSE file at the repository root. MIT permits commercial and private use, modification and redistribution provided the copyright notice and permission notice are retained. That is a permissive arrangement with few obligations, but it is not legal advice and does not address what your jurisdiction allows you to do with the results.
Editorial conclusion
Adopt it if you want a per-layer verdict on a connection you already suspect is filtered, or if you need machine-readable snapshots of block type over time. Skip it if you need a bypass tool or a legally defensible measurement: the README itself notes that TLS DPI and TCP reset signals can also come from server-side problems, and a single vantage point cannot separate the two. Before trusting a verdict, run rkn-check --json once with --no-self-info on a connection you know is unfiltered and compare the same target list against the filtered one.
Frequently asked questions
How can I check if a website is blocked on my internet?
Run rkn-check, which probes a built-in list of roughly 21 control sites and roughly 15 RKN-restricted targets and prints a per-site verdict plus a summary. For one site only, pass it with --url, though the README notes there is then no summary verdict because there is no control group.
How to tell if a website is blocking your IP?
The tool reports the layer that failed rather than a yes or no: DNS poisoning, TCP reset, TLS DPI on SNI, or an ISP stub page. A cross mark is a high-confidence diagnosis and a tilde with LIKELY means a censorship pattern matched but a server-side issue cannot be ruled out from one vantage point.
Can a website block you?
rkn-block-checker focuses on network-level interference by an ISP or middlebox, not on a website refusing you. Its documented fingerprints are DNS poisoning, TCP reset, TLS DPI on the SNI extension, and ISP stub pages served with status 200 or 451.
Community notes