История о том, как сисадмин борется с конторой с бюджетом в 60 млрд.
В продолжение комментария.

Введение
Есть грандиозный проект, и для его существования нужны 3 вещи:
- сервера
- люди
- vpn
Компания зарубежная, и мы с удовольствием используем AWS.
Требования регуляторов привели нас к OpenVPN.
А компания любит дешёвую рабочую силу, поэтому часть сотрудников живёт в РФ.
Получилась простая схема, на которой хотелось бы жить вечно.

client -> openvpn://bastion.example.com:1194
Казалось бы, что может пойти не так? Именно тут появляется наш великолепный цензор в виде РКН и ставит палки в колёса.

Глава 1. Первые блокировки, obfs4proxy
В какой-то момент, клиенты в РФ начали отваливаться. Анализ быстро привёл нас к пониманию, что происходит обрыв tcp соединения на этапе подключения. Но только для OpenVPN, остальной траффик ходил как положено.
Значит нам нужно замаскировать траффик, и сделать это:
- максимально удобно для сотрудников, далеко не все кулхацкеры
- безопасно для инфры, лишных дырок появиться не должно
Так у нас появился obfs4proxy c связке с Viscosity

client -> obfs://127.0.0.1:1080 -> obfs://bastion.example.com:1195 -> openvpn://bastion.example.com:1194Конечно же никто не мог тогда предвидеть, на какую интересную дорожку мы встали.

Глава 2. Вынос части инфры из AWS.
Недолго мы испытывали счастье, и в какой-то момент траффик до AWS начал ходить с перебоями. На благоприятную рабочую обстановку это похоже не было, поэтому обфускацию решили вынести.

client -> obfs://127.0.0.1:1080 -> obfs://tunnel.example.com:1195 -> openvpn://bastion.example.com:1194Логика была банальна:
- поставщики виртуалок не обязаны ставить ТСПУ
- у хороших вендоров есть свой канал
- серваки светятся как отечественные в россии, но имеют зарубежный IP
Такое должно прожить долго и лавочку не прикроют, верно ведь?

Глава 3. Попытка попасть в белые списки.
Играть в кошки-мышки с государством интересно, но хотелось иногда просто поработать.
Поэтому следующим этапом была попытка попасть в белые списки. Мы легальные, аудионаркотики не продаём, неужели не мы можем работать как белые люди?
Спустя несколько месяцев ответ был получен, но результата это не дало.

Глава 4. Появление cloak/trojan/hysteria/vless
В какой-то момент часть сотрудников начала жаловаться на недоступность. Снова.
Ещё одна пачка анализов и приходим к пониманию, что траффик режется. Симпомы идентичны обычному использованию OpenVPN, всё намекает на то, что протокол не столь надёжен, как хотелось бы.
Начинаем искать альтернативы. Так в течении пологода у нас заводятся shadowsocks/amnezia/ipsec/cloak/trojan/hysteria/vless/vkturnproxy.

client -> ck-client://127.0.0.1:1080 -> ck-server://tunnel.example.com:443 -> openvpn://bastion.example.com:1194Решения которые прекрасно работали для меня одного, начинают отваливаться в разных регионах страны, на разных провайдерах, в разных случаях. И в этом чёрном ящике абсолютно не понятно:
- то ли накатывают белые списки
- то ли РКН сломал часть интернета
- то ли их DPI научился детектить протокол
- то ли мы провинились
- то ли кривые руки сотрудников
Всё приходит к тому, что у нас поднята пачка методов обхода блокировок (уже 10 в документации), а на сотрудниках я тестирую.

Глава 5. Белые списки, поднятие серверов в РФ
Научились обходить блокировки? Вот вам задачка со звёздочкой.
Видимо так решило моё любимое министерство цифрового отрицательного развития.
Появилась нужда резко найти IP из белых списков и использовать их. Решение пришло также быстро - обратный король мидас отечественного IT. cloud.vk.com позвляет быстро поднять VPS, а на их серваках внезапно доступны instagram/youtube/etc.

client -> ck-client://127.0.0.1:1080 -> ck-server://subway.example.com:443 -> openvpn://bastion.example.com:1194Появилось ложное ощущение, что вот он конец, решение всех проблем, один сервер чтобы обходить их все. Сотрудники получили отличную скорость, я получил спокойствие.

Глава 6. Отрыв IP, резервирование
В какой-то момент работа остановилась, и пришлось вспоминать основы high availability - наличие запасного сервера.

Сложно сказать, что послужило причиной блокровки:
- кто-то из сотрудников сидел в max с рабочего VPN'a
- DPI действительно научился палить vless
- мои кривые руки в конфигурации сервера
- активные пробы прошлись по всем портам и нашли лишнее
Причины были уже не важны, главное стало понимание, что нужно что-то делать. И самым простым оказалось поднять ещё чуть-чуть виртуалок.

client -> ck-client://127.0.0.1:1080 -> ck-server://{subway|underground}.example.com:443 -> openvpn://bastion.example.com:1194Я в своем познании настолько преисполнился, что я как будто бы уже сто триллионов миллиардов лет обхожу блокировки.

Глава 7. Multi-hop
Появление вестей о шпионском ПО, которое будет сливать данные IP выходного сервера дало ясно понять, что входной и выходной адреса должны различаться. Так в арсенале появился gost.

client -> ck-client://127.0.0.1:1080 -> gost://subway.example.com:443 -> ck-server://tunnel.example.com:443 -> openvpn://bastion.example.com:1194Latency слегка подрос, зато наши сотрудники живут в стабильных условиях (надолго ли?).

Конфиги
Для настройки всего этого счастья в любом случае придётся прильнуть к официанльной документации, но небольшую шапарглку оставлю.
Скрытый текст
gost.yaml
services: - name: cloak-tcp addr: :443 handler: type: tcp listener: type: tcp forwarder: nodes: - name: cloak-tcp addr: {{ gost_target }}:443
obfs4proxy.conf
TOR_PT_MANAGED_TRANSPORT_VER=1 TOR_PT_STATE_LOCATION=/var/lib/obfs4 TOR_PT_SERVER_TRANSPORTS=obfs4 TOR_PT_SERVER_BINDADDR=obfs4-0.0.0.0:{{ obfs4_port }} TOR_PT_ORPORT={{ obfs4_target }}
ck-server.json
{ "ProxyBook": { "openvpn": [ "tcp", "{{ cloak_remote }}" ] }, "BindAddr": [ ":443" ], "BypassUID": [ {{ cloak_uid }} ], "RedirAddr": "www.example.com", "PrivateKey": "{{ cloak_private }}" }
ck-client.json
{ "RemoteHost": "subway.example.com", "Transport": "direct", "ProxyMethod": "openvpn", "EncryptionMethod": "plain", "UID": "{{ cloak_uid }}", "PublicKey": "{{ cloak_public }}", "ServerName": "www.example.com", "NumConn": 4, "BrowserSig": "chrome", "StreamTimeout": 300 }
xray-server.json
{ "log": { "loglevel": "info" }, "routing": { "rules": [], "domainStrategy": "AsIs" }, "inbounds": [ { "listen": "0.0.0.0", "port": {{ xray_port }}, "protocol": "vless", "tag": "vless_tls", "settings": { "clients": [ { "id": "{{ xray_client }}", "email": "{{ xray_email }}", "flow": "xtls-rprx-vision" } ], "decryption": "none" }, "streamSettings": { "network": "tcp", "security": "reality", "realitySettings": { "show": false, "dest": "www.example.com:443", "xver": 0, "serverNames": [ "www.example.com", "example.com" ], "mldsa65Seed": "", "privateKey": "{{ xray_private }}", "minClientVer": "", "maxClientVer": "", "maxTimeDiff": 0, "shortIds": [ {{ xray_short }} ] } }, "sniffing": { "enabled": true, "destOverride": [ "http", "tls" ] } } ], "outbounds": [ { "protocol": "freedom", "tag": "direct" }, { "protocol": "blackhole", "tag": "block" } ] }
xray-client.json
{ "log": { "level": "info" }, "inbounds": [ { "listen": "127.0.0.1", "port": 1080, "protocol": "socks", "settings": { "udp": true }, "sniffing": { "enabled": true, "destOverride": [ "http", "tls" ] } } ], "outbounds": [ { "domain_strategy": "ipv4_only", "flow": "xtls-rprx-vision", "packet_encoding": "xudp", "server": "subway.example.com", "server_port": 8443, "tag": "proxy", "tls": { "alpn": [ "h2" ], "enabled": true, "insecure": true, "reality": { "enabled": true, "public_key": "{{ xray_public }}", "short_id": "{{ xray_short }}" }, "server_name": "www.example.com", "utls": { "enabled": true, "fingerprint": "chrome" } }, "type": "vless", "uuid": "{{ xray_uuid }}" }, { "tag": "direct", "protocol": "freedom" }, { "tag": "block", "protocol": "blackhole" } ] }
ss-server.json
{ "server": "0.0.0.0", "server_port": {{ ss_port }}, "password": "{{ ss_pass }}", "method": "aes-256-gcm", "mode":"tcp_and_udp", "fast_open":false }
ss-client.json
{ "server": "tunnel.example.com", "server_port": {{ ss_port }}, "password": "{{ ss_pass }}", "method": "aes-256-gcm", "local_address": "127.0.0.1", "local_port": 1080 }
hysteria-server.yaml
listen: :{{ hysteria_port }} tls: cert: /etc/ssl/wildcard.crt key: /etc/ssl/wildcard.key auth: type: userpass userpass: {{ hysteria_client }}: {{ hysteria_pass }} masquerade: type: proxy proxy: url: https://www.example.com rewriteHost: true obfs: type: salamander salamander: password: {{ hysteria_obfs }} resolver: type: udp tcp: addr: 8.8.8.8:53 timeout: 4s udp: addr: 8.8.4.4:53 timeout: 4s tls: addr: 1.1.1.1:853 timeout: 10s sni: cloudflare-dns.com insecure: false https: addr: 1.1.1.1:443 timeout: 10s sni: cloudflare-dns.com insecure: false
hysteria-client.yaml
server: tunnel.example.com:1984 auth: {{ hysteria_client }}: {{ hysteria_pass }} obfs: type: salamander salamander: password: {{ hysteria_obfs }} http: listen: 127.0.0.1:8080 socks5: listen: 127.0.0.1:1080
trojan-server.json
{ "run_type": "server", "local_addr": "0.0.0.0", "local_port": {{ trojan_port }}, "remote_addr": "{{ trojan_remote }}", "remote_port": 443, "password": ["{{ trojan_password }}"], "ssl": { "cert": "/etc/ssl/wildcard.crt", "key": "/etc/ssl/wildcard.key", "cipher": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384", "cipher_tls13": "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384", "prefer_server_cipher": true, "alpn": [ "http/1.1" ], "alpn_port_override": { "h2": 81 }, "reuse_session": true, "session_ticket": false, "session_timeout": 600, "plain_http_response": "", "curves": "", "dhparam": "" }, "tcp": { "prefer_ipv4": false, "no_delay": true, "keep_alive": true, "reuse_port": false, "fast_open": false, "fast_open_qlen": 20 }, "mysql": { "enabled": false, "server_addr": "127.0.0.1", "server_port": 3306, "database": "trojan", "username": "trojan", "password": "", "key": "", "cert": "", "ca": "" } }
trojan-client.json
{ "run_type": "client", "local_addr": "127.0.0.1", "local_port": 1080, "remote_addr": "{{ trojan_remote }}", "remote_port": {{ trojan_port }}, "password": [ "{{ trojan_password }}" ], "log_level": 1, "ssl": { "verify": true, "verify_hostname": true, "cert": "", "cipher": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA", "cipher_tls13": "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384", "sni": "www.example.com", "alpn": [ "h2", "http/1.1" ], "reuse_session": true, "session_ticket": false, "curves": "" }, "tcp": { "no_delay": true, "keep_alive": true, "reuse_port": false, "fast_open": false, "fast_open_qlen": 20 } }
Вывод
Я рассказал последний год своего весёлого приключения. В этом простом рассказе я хотел бы акцентировать внимание, что вопрос выбора технологии не менее важен, чем вопрос архитектуры, выбора поставщика, и обучения персонала. Сложно гарантировать аптайм, когда ошибка на любом из этапов может внести тебя в бан.
Особое внимание:
- ТСПУ начали поставлять на сети межрегиональных провайдеров, желательно настраивать multihop, чтобы траффик из РФ выходил и шифрованным, и обфусцированным client -> vps rf -> vps eu -> vpn
- желательно не использовать обход блокировок на мобилках одновременно с небезопасными приложениями (макс/яндекс/банки), активно сливают, можно поймать бан на следующий день
- не забываем настраивать split-tunnel, чтобы траффик для отечественных сервисов шёл внутри страны
- РКН чувствителен к портам, для белых списков только 80/443, для обхода блокировок не использовать 1337/1984/3128/8080
- РКН быстро добавляет IP в блэклист сервера за рубежом, и рубит машину в РФ, если спалит
На данный момент самым живым является схема, когда:
- есть защита от активных проб
- есть валидные tls сертификаты и настоящий веб-сервер, который отвечает
- траффик шифруется лишь 1 раз
- траффик обфусцируется и очень похож на https
- входной и выходной адреса отличаются
- есть резервирование на несколько машин внутри страны

Комментарии (16)

edik-petrof
26.04.2026 01:05не использовать ... 1984
Почему? За данным портом не закреплено никакой широко используемой сетевой службы или программы. Или просто само сочетание цифр выглядит сомнительно?) По такой логике и порт 1917 можно запретить тогда.

lex899
26.04.2026 01:05Почему?
Как раз потому что:
За данным портом не закреплено никакой широко используемой сетевой службы или программы.
Любой непонятный трафик на непонятных портах рискует попасть в блокировку "на всякий случай".

Kenya-West
26.04.2026 01:05У России три союзника: порты 22, 80 и 443. Все остальные для РКН рано или поздно станут как красный флаг для быка. Я давно уже свыкся с этой мыслёй...

microtheft
26.04.2026 01:05Ко́микс (от англ. comic — «смешной») — рисованная история, рассказ в картинках.

aleksandr55575
26.04.2026 01:05Мне теперь надо оплачивать 2 впс, чтоб обойти тспу, купленную на мои налоги. Как то не правильно это работает...

rombell
26.04.2026 01:05Я бы платил и за три, если бы просто нажать кнопку, и оно работает. Но именно что надо обучаться, поддерживать весь зоопарк, тратить на это время и когнитивные усилия. Не только лишь все это могут себе позволить, даже ИТшники.

rombell
26.04.2026 01:05Ничто так не бесит (после самих блокировок), как формулировка "зайти не получится". Сюсюканье и (зумерское?) смягчение формулировок. Я взрослый человек, запрещено - напишите, что запрещено, что за хрень с "не получится"?!
Некоторые сайты, megamarket например, вообще перестал меня пускать из-под XP. Независимо от браузера, даже с форка Chrome 132.0.6834.226
Уж не знаю, что они там детектят, но в поддержке предлагают перезагрузить/почистить куки/отключить ВПН (которого в принципе нет под XP, к сожалению) и так далее, а потом просто морозятся.

daggert
26.04.2026 01:05Ну уж простите, но ХР это 25 лет назад. Это уже совсем дое*ка что те кто делают сайты - не думают об этой системе.

Mr_Boshi
26.04.2026 01:05Дое*ка не про то, что сайт на ХР не открывается, а про то, что при этом никто не пишет "Наш сайт не поддерживает ХР", как не пишут и любую другую причину ошибок (ведь это может отпугнуть пользователя и он никогда не вернется. А если сказать "попробуйте позже", то может и вернется...).

V1tol
26.04.2026 01:05TLS 1.2 в системе включён? Мегамаркет не поддерживает 1.1, просто соединение не установится. Ну или причина может быть ещё банальнее - они используют какое-то браузерное апи, не поддерживаемое в 132 хромоноге.

GlazOtca
26.04.2026 01:05Заголовок нужно другой сделать: "Терпели, терпим и будем терпеть!!! Терпилам - слава!"
atwok
Странно, что у одних изымают IP адреса в VK Cloud, а у других там всё работает и они публично распространяют ссылки MTproxy для подключения к Телеграм с обходом белых списков. Или Телеграм это другое и не считается обходом блокировок?