Comments 187
Насчёт OpenWRT не знаю — у меня TomatoUSB + Entware — и там есть проблема в том, что пришлось вручную ребилдить OpenSSL, потому что Entware не поставляет libssl/libcrypto.a… Что ломает, например, OpenSSH, который хочет строго ту же версию, с которой слинкован. Нет, по хорошему надо было разворачивать кросскомпайл на компе, но мне было лениво — проще было билд делать на самом роутере =)
Но ядро 2.6 в 2021-м?
Откройте для себя:
1. FreshTomato — свежий томатоюсб. И как вы на него не наткнулись в сети?
2. Openwrt — монстр, свежайшее ядро 5.х. Можно собрать звездолет.
можно пробовать поднять на роутере
по классификации автора статьи это п.3
А ещё прикольнее поставлять в виде коробки raspberry pi, чтобы подарить можно было :)
Этакая "антироскомнадзоровская" коробочка? =) Как сам РосКомНадзор ставит свои у провайдеров, так и мы у обычных людей =)
Проблема тут в том, что под каждого провайдера приходится адаптировать. Как ни странно, https садаптировать проще, поскольку там явно "не тот" сертификат. А вот с http каждый городит что хочет…
число провайдеров конечное (и небольшое), можно со временем собрать конфиги для каждого
Притом соединение к серверу придется проксировать всегда, а сам сервер ставить где-то в Нидерландах, иначе заблочат
Можно сделать универсальный вариант — сравнивать тип ответа с физического порта и туннеля, всегда использовать туннель при несовпадении.
Это, кстати, решит проблему с провайдерами, которые просто блекхолят трафик без предупреждения. Таких не мало.
и иным ресурсам с целью расширения конкурентного присутствия, в условиях непрерывных и постоянно меняющихся технических и юридических помех со стороны, в том числе, третьих лиц. » (с)
Mitm с бантиком :-) брать такие подарки только у тех, от кого нет секретов :-)
Субъективно — можно сильно упростить решаемую задачу, если завернуть кеширующим резолвером (тот же dnsmasq) весь DNS-трафик за пределы родины с помошью DoH/DoT.
При этом подключение будет осуществляться непосредственно к заблокированному IP, в результате будет обычный и одинаковый для всех отлуп по TCP без таймаута (разумеется, если речь идет не про открытый http, а про tls или что-либо, что провайдеры не умеют/не считают нужным MiTM-ить).
Ну, и есть минус — заворачивание всего DNS наружу может ломать логику CDN в ряде случаев, но это почти полностью проблемы провайдера (за исключением ПО, сильно чувствительного к задержкам).
Тот же Мегафон, над которым я упражнялся выше, никак не трогает DNS трафик, и IP из DNS-а приходит вполне легитимный. Перехват осуществляется уже на базе запрашиваемого IP. Даже для linkedin.com.
Так что DoH тут бы не помог совсем никак.
Мегафон — да, но есть провайдеры, с которыми достаточно просто настроить DoT на роутере.
Вот если бы это упаковали в докер, то было бы вообще супер. Для dоh\dot прекрасно работает pihole или adguardhome
lua-struct для парсинга бинарных пакетов (в частности, поиска сертификата после ServerHello).
С версии Lua 5.3 функционал lua-struct встроен в луа в виде функций string.pack и string.unpack.
Я даже написал апгрейд для них(lua-advanced-string-pack) который позволяет читать массивы и сложные структуры.
Мало подобрать семена, надо еще пропалывать и поливать огород.
А так-же травить вредителей.
1) Нормальность депутатов (любой кандидат может всячески изображать нормального до выборов, а потом «переобуться», как только его изберут)
2) Допуск этих самых «нормальных» депутатов до выборов
3) Отсутствие возможности подтасовки результатов выборов (я лично не знаю способов проверки, что бюллетени не подвергались модификации, а также не подвергалось модификации ПО и оборудование, подсчитывающее эти самые бюллетени. Если будет какой-то математически доказуемый способ по типу блокчейна — тогда другое дело)
4) Отсутствие подкупной массовки, оставляющей «нужные» голоса (путём каких-либо бонусов, угроз или шантажа)
5) Политически активное население, желающее голосовать за «нормальных депутатов» в противовес «стабильности», «духовных скреп» и прочего.
Возможно, это даже не все пункты (перечислил только те, что быстро пришли в голову). Если хотя бы один пункт будет нарушен — то вся идея выбора «нормальных депутатов» пойдёт коту под хвост, ибо перевес будет за стороной, имеющей возможность манипуляции голосами.
Может и минусов наловлю, но:
Где ваши "нормальные" депутаты от оппозиции? Всё более-менее известные, уж извините, какие-то фрики. Вот мне, обычному человеку, какая от них польза, что они толкают? Хайп и свои шкурные интересы? Приведите пример путнего законопроекта от оппозиционного депутата, который как-то повлияет/улучшит жизнь простого гражданина?
Посмотрел ваши ссылки, ну такое, если не ошибаюсь 2 было про пенсионный возраст, а остальное вообще меня никак не касается, но вот это мне понравилось 722042-7 закон о чистоте пива))))
А минусов насували как будто я написал, что Путин бог, а навальный лох))))
Опять же в первом случае вы скинули ссылку на инициативы несистемной, а во втором случае на законопроекты системной и вам не кажется что, инициатива и законопроект это довольно таки разные вещи? Инициатива про пешеходный переход меня вообще не касается, а законопроект о публичных мероприятиях частично, т.к на шествия и пикетирования я не хожу, а вот на публичных мероприятиях могу присутствовать.
Уж извините, что ответил с задержкой, на калыме заработался и не до интернетов было.
Что касается «меня не касается» то этого не было в изначальных условиях.
Несистемная оппозиция любит за чужие слова цепляться, однако за свои слова не привыкли отвечать. Значится так, вы меня сразу упрекнули "за не точность формулировки", так и вы тоже перепутали гражданскую инициативу с законопроектом) я вроде и провластный, но сдругой стороны люблю чужое мнение выслушать, но вы так его подаёте, хех.
Да можно и без дапутатов, просто заменить их на котиков. Получится, что раньше от каждого депутата был вред, а теперь хоть пользы котик не приносит, но и не вредит. Так что получаем строгое улучшчение ситуации.
Ещё одно есть условие, с которым не ясно, что делать — компетентность избирателей. Фактически получается, что большинство не способно на осознанный выбор потому, что кухарка, слесарь или программист не могут управлять государством, так как не имеют специальных знаний и следовательно не способно правильно оценить кандидатов. Некомпетентность приводит к тому, что избирателя обманут в любом случае. Не намухлюют с голосами, так обманут честным путем при помощи отработанных технологий из рекламного бизнеса. А редкое мнение понимающих все равно потонет в массе облапошенных.
Я не думаю что мне нужны какие-то специальные знания чтобы понять, хорошо управляют государством или нет. Это как с молоком — сам корову я подоить не смогу, но отличить кислое молоко от нормального смогу запросто.
Пример — в Новосибирске не вывозят мусор и не чистят снег уже десять тысяч лет, а каждую весну/осень город стабильно затапливает. Какой вывод можно из этого сделать?
Какой вывод можно из этого сделать?
что это место проклято? :-)
Если, как с молоком, то для определения явных проблем с качеством, особых знаний не надо, но дальше надо определять, кто виноват и что делать. Виноват молочник, виноват форсмажор. Еще интересный вариант, у вас не кислое, а у соседа кислое — уже три варианта, молочник, форсмажор, сосед. Может он в холодильник не поставил, а валит на молочника, а может правду говорит, а может он безграмотный и не знает, что делать с молоком, но он требует сменить молочника. Что делать в таком случае без понимания приемов обращения с молоком. Потом, дальше, решили менять, пришел мужик — говорит, что молочник, надо как-то понять квалификацию и оценить независимость от отдельных производителей молока. Первое надо сделать умея только пить молоко. Для второго надо быть чуть ли не следователем с полномочиями проверять счета в банках и осуществлять слежку.
Если молочник доставляет мне прокисшее молоко то совершенно пополам почему и что там у него случилось. Его надо менять. А если молоко хорошее то какая разница что говорит сосед. Ему не нравится и пусть меняет.
Только в случае с молочником, если он не монополист, то рынок решит проблему сам. А власть обладает монополиями во многих сферах, так что тут всё не так просто.
так обманут честным путем при помощи отработанных технологий из рекламного бизнеса
Это уже большой шаг вперёд. Какой бы не была лживой реклама, в конечном счёте вы получаете какой-то товар, который хотя бы формально соответствует заявленным характеристикам. Гораздо хуже, когда вы не получаете вообще ничего, либо прямо противоположное.
Она работает как «испорченный телефон» в информационном направлении Регион>Область>Москва и как «система ниппель» в обратном, материальном направлении.
Зачем нужна армия посредников в виде депутатов «выражающих суверенную волю народа» если сейчас практически у каждого есть смартфон и возможность напрямую осуществлять свою власть непосредственно как гласит 3 статья конституции.
На самом деле стране нужны не «нормальные» депутаты, а идейные ITшники для объединения воли народа и реализации честных выборов через технологию блокчейн.
В свете того, что скоро придёт замедление вместо блокировки — ИМХО более перспективно заворачивать всё в VPN поверх HTTPS с белыми списками IP, которые туда не пойдут.
Ну вот да. Проблема пинга к игровым сервера проще решается белым списком игровых серверов. Их, в принципе, не так и много, так что можно совместными усилиями составить список по умолчанию как сейчас составлен список заблокированных сайтов — он будет значительно меньше и его будет значительно проще поддерживать.
А весь остальной не-игровой траффик — только через VPN. Причём по возможности — self-hosted. Просто считайте, что ежемесячная стоимость работоспособного интернета выросла примерно на $5 (которые стоит сервер для VPN) — налог на РКН.
В теории есть неплохая схема с универсальным обходом блокировок на основе geo-ip.
Если исходить из того, что все заблокированные сайты хостятся вне РФ, то можно все geo-RU адреса маршрутизировать напрямую, а зарубежные — отправлять в VPN (нужен хороший vpn по скорости и расположению)
Плюсы: маршруты не будут удлинняться; универсальность способа
Минусы: в vpn уходит много пока ещё не заблокированного и не замедленного трафика; есть единичные случаи достаточно популярных сайтов, которые давно заблокированы, но их удивительные админы продолжают хостить сайт в РФ (например lostfilm.tv)
Мой выбор это
- самый дешёвый vps в Европе
- DoH на роутере
- wireguard для подключения и шифрования
- socks5 proxy для перенаправления только конкретных ресурсов
- плагин для браузера для быстрого добавления/исключения ресурсов
Как выйдет релиз routeros с поддержкой wg, можно будет избавится от VPN клиента на машине и возможно что то получится придумать с проксированием на уровне роутера
Может для постоянного коннекта он и неплох, не знаю (у меня SSTP работает вполне шустро — шустрее того же OpenVPN-а), но для всего остального… Ну, не знаю.
Холивора не получится. Я вот в первый раз услышал про SSTP (что не удивительно, учитывая что он принадлежит M$, а я их продукты не люблю), но уже вполне в состоянии ответить на вопрос "почему не":
- нет нормальной реализации сервера под линух
- не работает из коробки под iOS и MacOS
- "But if you’re obsessed with privacy, stick with WireGuard. It’s open-source and not owned by Microsoft." (https://www.cactusvpn.com/beginners-guide-to-vpn/what-is-sstp/#sstp-vs-wireguard)
2. Ну, это верно, под MacOS придётся собирать клиент, про iOS не знаю, но наверняка есть какой-то сторонний клиент. С другой стороны я понятия не имею, работает ли на этих устройствах из коробки Wireguard. А вот SSTP из коробки работает на Windows.
3. Сам SSTP протокол полностью открыто описан, и по сути является обёрткой над давно всем известным PPP с минимальными добавлениями и завёрнутым в HTTPS, так что ничего нового в нём нет. Ну и этак можно сказать что GitHub принадлежит MS, а значит от него тоже надо держаться стороной =) Современная MS совсем не та MS что была раньше.
SoftEther это немного другая история — он поддерживает кучу протоколов, поэтому неясно, а чего ради из них всех предпочитать именно SSTP.
WireGuard есть примерно вообще под всё: https://www.wireguard.com/install/
Волк может натянуть овечью шкуру, но останется волком.
Но продолжать не буду, рассуждения о волках и овечьих шкурах — это уж совсем субъективный холивор. =)
А разве при использовании SoftEther эта фича с VPN over HTTPS работает только при использовании SSTP? Мне почему-то показалось, что это фича самого SoftEther, так что полагаю ещё какие-то из поддерживаемых им протоколов должны такое уметь.
Да отстаньте со своим вайргардом — оно хипстерская поделка и ближайшие лет пять ею и останется. А там, глядишь, что нового и изобретут
Главное достижение WireGuard — он показал, что настройка и реализация VPN могут быть очень простыми и при этом более чем эффективными. Остальным VPN (особенно будущим) теперь придётся конкурировать с учётом этого. И за это WireGuard большое спасибо. А в остальном, WireGuard или что-то другое — не так уж и важно.
Поэтому тут или SoftEther какой, или заворачивать WireGuard (или другой протокол) в shadowsocks. Второй вариант более универсален потому что shadowsocks есть и под OpenWRT, а с SoftEther там все не так однозначно было когда я последний раз интересовался.
А если начнется „цепная реакция“, и пользователи массово попытаются обходить обсуждаемую блокировку Twitter с помощью VPN-сервисов, дальше начнутся блокировки доступа уже к ним
Но с учетом того что речь идет о том, что они научились на блокировках Телеграм, а возможность блокировать конкретные VPN сервисы была уже и тогда, то мне кажется что речь идет именно о блокировке протоколов через DPI, которые установили в рамках «суверенного рунета» и сейчас применяют для замедления Twitter.
Проблема вовсе не в том, в сколько кликов оно накатывается. Проблема в тьме доступных настроек, которые временами приходится подкручивать, потому что иначе возникают разные проблемы. Проблема в том, что без вникания в настройки нет уверенности, что настроено "в два клика" оно корректно и безопасно (и зачастую оказывается, что это не так). Всё это создаёт (излишнюю, как показал WireGuard) сложность.
Всё это создаёт (излишнюю, как показал WireGuard) сложность.
я в это не верю. Потому что по Вашей логике получается, что или WireGuard работает (повезло), либо не работает и возможности починить его не будет. Хотя тут, наверное, должны быть попросту мощные инструменты диагностики. Но я все равно могут придумать какой-нибудь /высосанный из пальца, конечно же/ кейс, когда какая-нибудь настройка типа MTU сломает WG. Либо WG настоль крут, что у него внутри сложная логика "сделай мне хорошо", но если так, то мы прекрасно знаем как любая сложная логика ломается о реальность :-/
Ну, фишка в том, что он "просто работает". Магия-с. :)
На практике я сталкивался с двумя ситуациями, когда он не работал. И хотя может показаться, что это противоречит первому предложению, на самом деле это не так, или не совсем так — потому что ситуации слишком специфические.
В первой ситуации я обнаружил, что в кафе на их WiFi он не подключается, а через мобильный инет работает. Дома на WiFi проблем никогда не было. Очевидно, что тут скорее проблема в настройках инета в кафе, может там файрвол какой или ещё что-то, но разбираться с этим с телефона было слишком неудобно, так что реальную причину я не знаю (если, например, они тупо блокируют всё, кроме HTTP, то это сломает абсолютное большинство VPN, и я не склонен расценивать это как проблему "недостаточной сложности" WireGuard).
Во второй ситуации было интереснее — периодически подвисало VPN-соединение, и помогал только его перезапуск. Здесь уже это происходило в обычных условиях между двумя стационарными серверами (но находящимися в разных странах). Я частично выяснил в чём проблема: пакет от клиента приходит на сервер, сервер на него отвечает, но вот этот ответ уже до клиента не доходит. Причём наблюдается эта проблема только для этой пары портов отправителя/получателя и возникает после передачи довольно большого объёма данных. Отправка с другого порта сервера пакета на порт клиента — проходит. Соответственно, после перезапуска VPN меняется порт клиента, и проблема уходит. ISP клиента говорит, что никакой фильтрации у них которая могла бы это вызвать — у него нет. Соответственно, я пока грешу на какой-то ISP по дороге и/или баг вроде этого: Как мы раскрыли 24-летний баг в ядре Linux. В целом, на проблему самого WireGuard это так же не похоже.
На моём андроиде, кстати, его из коробки нет.
На моём андроиде, кстати, его из коробки нет.
не верю :-) даже на самом китайском андроиде есть IKEv2 или какой-нибудь IPsec. Проверьте, пожалуйста, еще раз
настраиваем IKEv2 без SMS и регистрации за 21 день?
хорошая шутка, оценил
не верю :-) даже на самом китайском андроиде есть IKEv2 или какой-нибудь IPsec. Проверьте, пожалуйста, еще раз
Не буду делать скриншот, но есть:
PPTP, L2TP, L2TP/IPSec PSK, L2TP/IPSec RSA, IPSec XAuth PSK, IPSec XAuth RSA, IPSec Hybrid RSA.
Именно IKEv2 нету. Пользуюсь как раз «каким-нить» IPSec
Старые версии Android шли без IKEv2. Насколько могу понять по исходникам, в AOSP вообще только в 9 версии добавили IKEv2.
Если нет то надо ставить клиент (на моём есть :) )
Или опенвпн — удостоверяющий центр подними, ключей нагенери, конфигов наделай. Некоторые простые варианты конфига в актуальных версиях уже не работают — требуют усиления TLS, это дополнительно ключи делать.
Wireguard — конфиг в десяток строчек и несколько команд для установки почти под чем угодно (microtik ждём).
А по простоте поднятия вообще SSH SOCKS прокси рулит, но нужна ручная работа для установки соединения.
Wireguard — конфиг в десяток строчек и несколько команд для установки почти под чем угодно (microtik ждём).
да-да-да, удачи его настроить, когда wireguard обновит шифры и клиент со "старым" wg не сможет работать работать с "новым" wg.
Тот же IPsec решает проблему тем, что он есть везде в каком-бы то ни было виде и можно подобрать набор совместимых параметров, но это же и проблема, т.к. его нужно подбирать иногда, а это превращается в научный тык.
История с энфорсингом свежих версий (как сейчас с TLS) хороша только тем, чтобы держать разработчиков софта "в тонусе" и не происходило https://en.wikipedia.org/wiki/Protocol_ossification
В маршрутизаторе делается при помощи стандартного функционала, но вот поднять весь стэк на голом линуксе задачка достаточно развлекательная.
Опять же — уже больше год вполне себе успешно живу с Wireguard, ничего не отваливалось. что я сделал не так?
Более того, со своим бэкграундом я слишком сильно долго настраивал WG, потому что искал дополнительную информацию, что и как там реализовано, потому что НУ НЕ МОЖЕТ БЫТЬ ТАК ПРОСТО, Я ЧТО-ТО УПУСКАЮ!
Я вот не понял, это что, извращённый аргумент из серии "не исключено, что вам придётся когда-нибудь в будущем помучаться с этим простым инструментом, поэтому давайте вместо этого продолжать мучиться сегодня со сложным"?
… Но втихую надеюсь на HTTP3/QUIC, что его тоже будут пропускать везде, и вот тогда и туннели можно будет тоже пустить маскируясь под него =)
Тут можно ещё добавить, что в одном TCP-потоке множество соединений и страдать будут все.
А вот если реально плохая связь, то там может очень сильно всё нарастать (ретрансмиты внутри и снаружи туннеля).
Но вот то, что снаружи это фактически HTTPS (хотя и с неестественным профилем трафика) — это огромный плюс. Ну и второй плюс, что из-за этого, это самый стабильный VPN, пролезающий через любые наты.
А с HTTP3, боюсь, что к тому времени в России просто запретят UDP, как нежелательный протокол :)
Для туннелей это очень неправильно
неправильно, но проблема как будто преувеличена. Вы ведь про TCP meltdown problem?
Есть и критика раздувания проблемы — http://samag.ru/archive/article/603
В общем, у автора свое видение проблемы, а тесты у него уж очень прямолинейные.
Единственным минусом такого подхода является то, что в случае, если Мегафон начнёт поддерживать eSNI, то коннекты к его сайту будут проксироваться, но пока что SNI у него вполне незашифрованный.
eSNI, к слову, уже deprecated (из Firefox даже уже и выпилили), будущее за ECH, где ClientHello шифруется целиком.
Автор, не пробовал то же самое сделать на envoy? Его механизм фильтров как будто аналогичен nginx и учитывая, что envoy написан буквально недавно и уже активно используется в высокопроизводительных service mesh — возможно будет хорошим выбором. Я даже читал, что к нему можно модули на wasm делать, но это не точно
Правда, если это неверно, и вы отправляете запросы, что-то меняющие на удалённом сервере, то тут беда… Прилетит по итогу два запроса — один — тот на который заблокирован ответ, и второй — спроксированный.
если все-таки влезть в L7 каким-то образом (ну, не знаю — свой сертификат сделать и полноценный DPI), то можно будет разделить идемпотентные запросы от неидемпотентных...
А в HTTP в принципе можно вычитать метод и отфильтровать не-GET/OPTIONS и вместо него отправить тот же GET / (или OPTIONS, что вообще то даже лучше, но тут я не берусь предсказать поведение провайдерского DPI, может и пропустить, или ответить как-то нестандартно… Надо пробовать) сохранив все остальные заголовки для проверки… Но это такое.
Насчёт envoy — честно, не слышал, посмотрю на досуге как-нибудь.
Однако, если приходится часто посещать разные заблокированные сайты, то переключать туда / сюда прокси будет неудобно
Так SwitchyOmega умеет правила, можно шаблоны задать и прокси/прямое подключение для них
Да и в любом случае при заворачивании 100% трафика в VPN пинг страдает в 99% случаев (есть ситуации при которых он может улучшиться к некоторым хостам, я практиковал это, но для этого надо специально строить цепочку серверов и арендовать с расчётом под конкретное приложение — в общем речь не о General Purpose).
Ваш вариант — это скорее один из подвариантов варианта 2 «гибридного» со списками. Просто списки формируете вы вручную =)
Если он стоит рядом, и они ощутимо проседают — Вы что-то не так настроили, потому что в нормальных условиях этого происходить не должно. Попробуйте взять тот же WireGuard, он достаточно быстрый, жрёт мало ресурсов, и его практически невозможно "настроить" (т.е. его сложно настроить некорректно :)), и проверьте с ним. Плюс неплохо убедиться, что сервер на котором стоит VPN не перегружен другими задачами.
В бытность пребывания на территории РФ все решилось швейцарским VPN за 3 бакса в месяц, в качестве софта был SoftEther.
Сначала пользовал ShadowSocks, но через него коряво работали торренты (ко мне нельзя было подключиться), перешел на обычный роутинг всего трафика. Для того чтобы погонять в контру полчасика можно и выключить, особых неудобств не отмечено.
Что прикажете с этим делать?))
заверяет что сигнатурное определение трафика позволит видеть буквально всё— Доктор, больше 3-х раз в неделю с женой не получается.
— Дед, а лет тебе сколько?
— 85.
— Дед, ну это же превосходно!
— Да? А мой сосед говорит, что с женой ежедневно, а ему 95!
— Ну так и вы говорите!
При большом желании можно финализировать TLS тем же NGINX-ом, легитимных клиентов пускать дальше как прокси, а нелегитимных — отдавать что угодно, хоть котиков, хоть собачек.
Особым запросом — это нечто вроде «port knocking», вполне можно сделать так, чтобы по дефолту NGINX финализировал TLS, но если получает какой-то спецзапрос — то добавляет ИП адрес который этот запрос отправил в список и далее весь трафик проксирует напрямую VPN-у.
Но это всё конечно требует поддержки с клиентской стороны.
Роскомнадзор хоть и действует по всей России, блокируют только на конечных пользователях, Так что ВПН в русском дц. прокатит. Ну это конечно, если вас не парит чио они льют ваш трафик куда-то ещё :)
Если ресурс заблокирован в РФ, но хостится в РФ и аплинком имеет МТС (такие существуют), то он будет недоступен из любой точки мира.
Если находим в нём этот редирект — это означает сразу две вещи:
Сайт блокируется, значит этот коннект надо редиректить.
Если по запросу получаем ответ о редиректе, то это может быть не блокировкой, а законным ответом сайта о перенаправлении клиента на другую страницу этого же сайта.
Такое встречается нередко.
Заходишь, бывает, на главную страницу сайта какой-нибудь конторы, а он редиректит тебя на какую-нибудь свою внутреннюю страницу типа /news/
Или у сайта могут быть зеркала. Заходишь на одно из зеркал, а оно перенапраляет тебя на основной домен сайта.
Ну и так далее.
Некоторые shared-хостинги выделяют учётку ssh на своём сервере под пользователя, не рутовую само собой. В принципе её можно использовать для запуска своего ПО при большом желании...
Идея отличная.
Списки выкидывать совсем, думаю не стоит. Они могут пригодиться хотя бы для кэширования результатов проверки.
Кстати, если провайдер начнёт просто дропать непонятное HTTPS соединение на адрес из реестра? Такой вариант предусмотрен? Всё равно ведь большинство не будет читать заглушку на сайте с поддельным сертификатом.
Неверно, блокировка дйствует только на уровне местных провайдеров, мтс, билайна, мегафона…
Если поднять свой сервер в ДЦ, например, в МСК, то все блокировки будут обходиться. Я себе так и сделал — взял дешёвый VPS с CentOS (минимальные ресурсы), поставил туда проксю — ей хватает, прописал Primary DNS cloudflare — они одни из самых быстрых, как Secondary DNS — OpenNet DNS, они ничего не блокируют и поддерживают несколько доп.зон, например .lib (в этой зоне открываются флибуста, рутрекер).
Подключение к проксе — по белым IP чтобы чужие не лазили. И всё работает весьма быстро. Вот пример:

*10 lua entry thread aborted: runtime error: content_by_lua(nginx.conf:357):45: bad argument #2 to 'connect' (number expected, got nil)
stack traceback:
coroutine 0:
[C]: in function 'connect'
content_by_lua(nginx.conf:357):45: in function 'socket_connect_dest'
content_by_lua(nginx.conf:357):85: in main chunk, client: 127.0.0.1, server: 0.0.0.0:30443
Такое ещё может произойти если вы пытаетесь подключиться к серверу напрямую, а не путём iptables-правила REDIRECT.
Напишите
ngx.log(ngx.INFO, tostring(dest_addr));
ngx.log(ngx.INFO, tostring(dest_port));
после
local dest_port = tonumber(dests[2]);
Если там nil — то у вас не подтянулась таки информация об исходном destination.
Так, — чукча ничего не понимает, когда забабахаете готовое решение, — просьба ответить на этот комментарий)
А на wsl работать будет? А то я боюсь роутер окирпичить.
Насчет скорости так отличные скорости и пинг, если правильно подберешь сервер.
У меня даже некоторые сайты через VPN быстрее работают.
Раньше и у меня проблемыбыли и тормоза с VPN, когда я пользовался общедоступными простыми вариантами. Но нашел прогу SoftEther VPN Client Manager теперь пролем нет.
А еслиб мне это на постоянке надо было, так оплатил бы платные варианты, там еще лучше.
Почти ничего не понял, но прочитал с удовольствием. СПАСИБО
А как думаете автор статьи возможно ли сделать блокировку рекламы на роутере, пай ходе не предлагать плохо блокирует.
Как вариант при запуске делать запрос на заведомо блокируемый ресурс, чтобы определить с каким конкретно сертификатом приходит редирект у данного провайдера.
Так скрипт будет самостоятельно адаптироваться к другим провайдерам использующим тот же принцип блокировки с редиректом.
Маленький лайфхак — на самом деле, необязательно использовать VPN и/или серверы в Европе, почти на всех VDS/VPS в России нет блокировки трафика. Берём, например, Y.cloud (у них серверы в Екатеринбурге и вроде в Москве есть) ставим wireguard с резолвом (dns-o-https) через nextdns (пробовал pihole — nextdns проще администрировать и процессорное время не занимает), подрубаем это все добро к keenetic (или любому другому роутеру с wireguard) и радуемся открытому интернету без рекламы. Задержка +~ 3-6ms к вашей, скорость 200+ Мбит/сек. Один минус — стоимость ~500 рублей в месяц (25%CPU). Но на рынке есть VPS и за 80 рублей в месяц с серверами в Москве, который тоже прекрасно работает.
Получается, что для того, чтобы понять, что сайт блокируется, достаточно вычитать полученный от сервера сертификат
чаще мне встречается отсылка фальшивого TCP RST, вызывающая разрыв соединения:
$ curl -v https://rutracker.org
* Trying 2a03:42e0::214:443...
* Connected to rutracker.org (2a03:42e0::214) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* OpenSSL SSL_connect: Connection reset by peer in connection to rutracker.org:443
* Closing connection 0
curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection to rutracker.org:443
будет ли решение работать в таком случае?
В моей версии (которая чуть проапдейчена относительно этой) есть автоматический фоллбэк на альтернативный канал при разрыве основного, чуть позже могу скинуть луа-код последней версии.
Я ещё провайдера поменял, с мегафона на билайн, так что чуть изменилась логика обработки редиректов и сертификатов, а заодно кэширование добавил.
Обновлённый lua-код
local prefer_hosts = false
local prefer_socks_hosts = true
local intercept_domains = {".t.co", ".twimg.com", ".twitter.com", ".twttr.com"}
local cached_domains = ngx.shared.domains
local host = nil
local socket = ngx.req.socket(true)
socket.socktype = "CLIENT"
local god = require("resty.getorigdest")
local dest = god.getorigdest(socket)
local sni_name = ngx.var.ssl_preread_server_name
ngx.log(ngx.DEBUG, dest)
ngx.log(ngx.DEBUG, sni_name)
local openssl = require("resty.openssl")
openssl.load_modules()
local ngx_re = require("ngx.re")
local cjson = require("cjson")
local socks5 = require("resty.socks5")
local struct = require("struct")
local dests = ngx_re.split(dest, ":")
local dest_addr = dests[1]
local dest_port = tonumber(dests[2])
local connect_type_last = nil
local socket_create_with_type = function(typename)
local target = ngx.socket.tcp()
target.socktype = typename
return target
end
local socket_connect_dest = function(target)
local ok = nil
local err = nil
if (prefer_hosts == true and host ~= nil) then
ok, err = target:connect(host, dest_port)
connect_type_last = "host"
if (err ~= nil) then
local socktype = target.socktype
target = socket_create_with_type(socktype)
ok, err = target:connect(dest_addr, dest_port)
connect_type_last = "ip"
end
else
ok, err = target:connect(dest_addr, dest_port)
connect_type_last = "ip"
if (err ~= nil and host ~= nil) then
local socktype = target.socktype
target = socket_create_with_type(socktype)
ok, err = target:connect(host, dest_port)
connect_type_last = "host"
end
end
if (ok == nil and err == nil) then
err = "failure"
end
return target, err
end
local intercept = false
local connected = false
local isCached = false
local upstream = socket_create_with_type("UPSTREAM")
local bufsize = 1024 * 16
local peek, err, partpeek = socket:receiveany(bufsize)
if (peek == nil and partpeek ~= nil) then
peek = partpeek
elseif (err ~= nil) then
ngx.log(ngx.WARN, err)
end
local domainIntercept = false
if (sni_name ~= nil) then
for _, v in pairs(intercept_domains) do
local domain = "." .. sni_name
local match = domain:sub(-string.len(v)) == v
if (match == true) then
domainIntercept = true
ngx.log(ngx.DEBUG, sni_name .. " intercepted based on rule " .. v)
-- host = sni_name;
break
end
end
end
if (domainIntercept == true) then
intercept = true
elseif
(dest_port == 80 or ngx.re.match(peek, "(^GET \\/)|(HTTP\\/1\\.0[\\r\\n]{1,2})|(HTTP\\/1\\.1[\\r\\n]{1,2})") ~= nil)
then
local http_host_find, err =
ngx.re.match(peek, "[\\r\\n]{1,2}([hH][oO][sS][tT]:[ ]?){1}(?<host>[0-9A-Za-z\\-\\.]+)[\\r\\n]{1,2}")
local http_host = nil
if (http_host_find ~= nil and http_host_find["host"] ~= false) then
http_host = http_host_find["host"]
end
if (http_host ~= nil and host == nil) then
host = http_host
end
local cached = nil
if (host ~= nil) then
cached = cached_domains:get(host)
end
if (cached ~= nil) then
ngx.log(ngx.INFO, "retrieved cached interception info: intercept=" .. tostring(cached))
intercept = cached
isCached = true
else
local err = nil
upstream, err = socket_connect_dest(upstream)
if (err ~= nil) then
intercept = true
else
local ok, err = upstream:send(peek)
if (err ~= nil) then
ngx.log(ngx.WARN, err)
end
local data, err, partdata = upstream:receiveany(bufsize)
if (data == nil and partdata ~= nil) then
data = partdata
elseif (err ~= nil) then
ngx.log(ngx.WARN, err)
end
if (data ~= nil) then
local match = "\r\nLocation: http://blackhole.beeline.ru/"
local matched = data:find(match, 1, true)
if (matched ~= nil) then
upstream:close()
upstream = socket_create_with_type("UPSTREAM")
intercept = true
else
connected = true
local ok, err = socket:send(data)
if (err ~= nil) then
ngx.log(ngx.WARN, err)
end
peek = nil
end
end
end
end
elseif (dest_port == 443 or sni_name ~= nil) then
local serv_host = nil
if (sni_name ~= nil and host == nil) then
host = sni_name
end
local cached = nil
if (host ~= nil) then
cached = cached_domains:get(host)
end
if (cached ~= nil) then
ngx.log(ngx.INFO, "retrieved cached interception info: intercept=" .. tostring(cached))
intercept = cached
isCached = true
else
local err = nil
upstream, err = socket_connect_dest(upstream)
ngx.log(ngx.DEBUG, err)
if (err ~= nil) then
intercept = true
else
local ok, err = upstream:send(peek)
if (err ~= nil) then
ngx.log(ngx.WARN, err)
end
-- Parsing the ServerHello packet to retrieve the certificate
local offset = 1
local data = ""
local size = 0
local servercert = nil
upstream:settimeouts(2000, 60000, 1000)
while (servercert == nil) do
if (size == 0 or offset >= size) then
local data2, err, partdata = upstream:receiveany(bufsize)
if (data2 ~= nil) then
data = data .. data2
elseif (data2 == nil and partdata ~= nil and partdata:len() > 0) then
data = data .. partdata
elseif (err ~= nil) then
ngx.log(ngx.WARN, err)
break
end
size = data:len()
ngx.log(ngx.DEBUG, "UPSTREAM received for ServerHello certificate retrieval! " .. size)
end
ngx.log(ngx.DEBUG, offset)
if (offset < size) then
local contenttype, version, length, subtype = struct.unpack(">BHHB", data, offset)
if (contenttype ~= 22) then
-- We got something other than handshake before we retrieved the cert, probably the server is sending the cert encrypted, fallback to legacy cert retrieval
break
elseif (subtype ~= 11) then
offset = offset + 5 + length
else
local suboffset = offset + 5
local _, _, _, _, certslength, _, firstcertlength = struct.unpack(">BBHBHBH", data, suboffset)
-- We need only the first cert, we don't care about the others in the chain
local firstcert = data:sub(suboffset + 1 + 3 + 3 + 3, firstcertlength)
servercert = firstcert
end
end
end
upstream:settimeouts(2000, 60000, 60000)
local cert = nil
if (servercert ~= nil) then
cert = openssl.x509.new(servercert, "DER")
ngx.log(ngx.DEBUG, "Cert retrieved from ServerHello peeking")
else
-- We employ a legacy method of gathering the certificate, involving connecting to the server and doing a SSL handshake by ourselves
ngx.log(ngx.DEBUG, "LEGACY CERT RETRIEVE")
local serv = socket_create_with_type("TLSCHECK")
local err = nil
serv, err = socket_connect_dest(serv)
ngx.log(ngx.DEBUG, err)
local session, err = serv:sslhandshake(false, sni_name, false, false)
if (err ~= nil) then
ngx.log(ngx.DEBUG, err)
-- We fallback to proxying in case if we failed to connect due to timeout or reset (we are blackholed)
intercept = true
else
ngx.log(ngx.DEBUG, err)
local sslsess, err = openssl.ssl.from_socket(serv)
ngx.log(ngx.DEBUG, err)
if (sslsess ~= nil) then
cert = sslsess:get_peer_certificate()
ngx.log(ngx.DEBUG, "Cert retrieved from secondary handshake")
end
end
serv:close()
end
-- Parsing the certificate
if (cert ~= nil) then
local sub = cert:get_subject_name()
local alt = cert:get_subject_alt_name()
for k, obj in pairs(sub) do
ngx.log(ngx.DEBUG, k .. " " .. cjson.encode(obj))
if (serv_host == nil and k == "CN" and obj.blob:find("*", 1, true) == nil) then
serv_host = obj.blob
end
if
(k == "CN" and obj.blob == "megafon.ru" and
(sni_name == nil or sni_name:find("megafon.ru", 1, true) == nil))
then
ngx.log(ngx.DEBUG, k .. " " .. obj.blob)
upstream:close()
upstream = socket_create_with_type("UPSTREAM")
intercept = true
end
end
for k, obj in pairs(alt) do
ngx.log(ngx.DEBUG, k .. " " .. cjson.encode(obj))
if (serv_host == nil and k == "DNS" and obj:find("*", 1, true) == nil) then
serv_host = obj
end
end
end
if (serv_host ~= nil and host == nil) then
host = serv_host
end
if (intercept ~= true) then
connected = true
local ok, err = socket:send(data)
if (err ~= nil) then
ngx.log(ngx.WARN, err)
end
peek = nil
end
end
end
end
if (connected == false and intercept == false) then
local err = nil
upstream, err = socket_connect_dest(upstream)
if (err ~= nil) then
intercept = true
upstream = socket_create_with_type("UPSTREAM")
end
end
if (isCached == false and domainIntercept == false) then
ngx.log(ngx.DEBUG, "Saving cached data: host=" .. host .. ", intercept=" .. tostring(intercept))
cached_domains:set(host, intercept)
end
if (intercept == true) then
local ok, err = upstream:connect("192.168.120.1", 45213)
ngx.log(ngx.DEBUG, err)
ok, err = socks5.auth(upstream)
ngx.log(ngx.DEBUG, err)
local ok = nil
local err = nil
if (prefer_socks_hosts == true and host ~= nil) then
ok, err = socks5.connect(upstream, host, dest_port)
connect_type_last = "socks_host"
if (err ~= nil) then
upstream = socket_create_with_type("UPSTREAM")
upstream:connect("192.168.120.1", 45213)
ok, err = socks5.auth(upstream)
ok, err = socks5.connect_ip(upstream, dest_ip, dest_port)
connect_type_last = "socks_ip"
end
else
ok, err = socks5.connect_ip(upstream, dest_addr, dest_port)
connect_type_last = "socks_ip"
if (err ~= nil and host ~= nil) then
upstream = socket_create_with_type("UPSTREAM")
upstream:connect("192.168.120.1", 45213)
ok, err = socks5.auth(upstream)
ok, err = socks5.connect(upstream, host, dest_port)
connect_type_last = "socks_host"
end
end
ngx.log(ngx.DEBUG, err)
end
upstream:setoption("keepalive", true)
upstream:setoption("tcp-nodelay", true)
upstream:setoption("sndbuf", bufsize)
upstream:setoption("rcvbuf", bufsize)
ngx.log(
ngx.INFO,
"RESULT: " ..
tostring(host) ..
"/" ..
dest_addr ..
":" .. dest_port .. " intercept:" .. tostring(intercept) .. " connecttype:" .. connect_type_last
)
local ok = false
if (peek ~= nil and peek:len() > 0) then
ok, err = upstream:send(peek)
if (err ~= nil) then
ngx.log(ngx.WARN, err)
end
else
ok = true
end
local pipe = function(src, dst)
while true do
local data, err, partial = src:receiveany(bufsize)
local errs = nil
local ok = false
if (data ~= nil) then
ok, errs = dst:send(data)
elseif (data == nil and partial ~= nil) then
ok, errs = dst:send(partial)
elseif (err == "closed") then
ngx.log(ngx.WARN, src.socktype .. ":" .. err)
return
elseif (err ~= nil and err ~= "timeout") then
ngx.log(ngx.WARN, src.socktype .. ":" .. err)
end
if (errs == "closed") then
ngx.log(ngx.WARN, dst.socktype .. ":" .. errs)
return
elseif (errs ~= nil) then
ngx.log(ngx.WARN, dst.socktypeerr .. ":" .. errs)
end
end
end
if (ok ~= false) then
local co_updown = ngx.thread.spawn(pipe, upstream, socket)
local co_downup = ngx.thread.spawn(pipe, socket, upstream)
ngx.thread.wait(co_updown, co_downup)
end
upstream:close()
ngx.flush(true)
socket:shutdown("send")
Вот как во всём этом разобраться не IT - специалисту???...
А как быть если провайдерский DPI отсылает TCP FIN, ACK пакет сразу после ClientHello? Никаких TCP RST или поддельных сертификатов.
На ум приходит что надо как-то выделять соединение в отдельный поток и следить за идущим пакетом после ClientHello. Задача непростая.
Была идея отслеживать этот пакет по TTL, но очевидно что это не решает проблемы на 100%. Будет много лжесрабатываний.
Домашний DPI, или как бороться с провайдером его же методами