mirror of
https://github.com/MayersScott/rkn-block-checker.git
synced 2026-08-04 14:47:08 +00:00
171 lines
6.3 KiB
Markdown
171 lines
6.3 KiB
Markdown
# RKN Block Checker
|
|
|
|
[](https://github.com/MayersScott/rkn-block-checker/actions/workflows/ci.yml)
|
|
[](https://www.python.org/downloads/)
|
|
[](LICENSE)
|
|
|
|
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
|
|
|
|
```text
|
|
======================================================================
|
|
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+.
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
pip install -e .
|
|
rkn-check
|
|
```
|
|
|
|
## Usage
|
|
|
|
```text
|
|
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`:
|
|
|
|
```bash
|
|
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
|
|
|
|
```text
|
|
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
|
|
|
|
```bash
|
|
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.
|