Бывало ли у вас такое, что вы подключились к общественной сети или мобильному интернету, но он себя странно ведёт. Надпись «Подключено, без доступа к интернету» отсутствует, устройство думает, что всё нормально. Вы открываете браузер и видите «Пройдите проверку личности в сети нашего кафе» или в случае с мобильным интернетом «Пополнить баланс можно тут, тут и тут».

Так вот, переходя ближе к теме. Вы можете воспроизвести подобное поведение очень просто прямо сейчас при помощи вашего мобильного телефона и ноутбука. Я в своём конкретном кейсе буду пользоваться услугами оператора красного цвета, однако проблема актуальна для всех текущих 4 монополистов рынка сотовой связи. Как вам, скорее всего, уже известно, они около года меняют свою политику, внедряя одно интересное нововведение — с вас требуют дополнительной платы за раздачу интернета поверх основного пакета. То есть вы не можете взять и использовать свои 7 гигов на месяц как ресурс для раздачи при помощи точки доступа. Для точки доступа вам предлагают отдельный, зачастую совсем невыгодный тариф. Конечно, можно сменить основной тариф на специальный «тариф для раздачи» и платить втридорога, но, как вы понимаете, сегодня мы в потребителя будем играть совсем недолго. Сейчас по пунктам нужно доказать нечестность подобной политики и с чувством завершённого введения перейдём к непосредственно технотексту.

Подобные условия пользования, само собой, порождают внутреннее недовольство пользователей:

За интернет они платят? — Да.

Раздача как-либо использует ресурсы провайдера сверх нормы? — Нет.

Так в чём же дело?

Оператор ничего не должен делать, чтобы абонент мог раздавать интернет. Фактически, пользователь вносит плату за то, чтобы оператор воздержался от препятствования использованию функции раздачи интернета, хоть она и является аппаратной на вашем устройстве — разве вы не должны иметь полное право ей пользоваться после покупки телефона?

Как вы понимаете, согласиться на такой бред можно только от безысходности. Думаю, не стоит доказывать, что абсолютно неэластичная экономика рынка в сфере услуг связи является признаком монополии. Если же не душнить, то лучше всего мысль передаст эта фраза: «Какие бы условия пользования оператор ни поставил — всё равно схавают».

Ещё немного демагогии


ФАС — это такие важные дяди, которые (если верить 2ГИС) сидят в Москве и делают то, что обязана делать монополия на насилие и территорию (Государство): говорят, что они следят за соблюдением законодательства в сфере конкуренции, естественных монополий, рекламы и т. д. и т. п.

Если вы погуглите запросы вроде «ФАС против операторов», то узнаете, что эта тема мусолится уже по меньшей мере 5 лет. И в этот раз в адрес операторов сотовой связи были предъявлены обвинения по поводу «платной раздачи трафика». Произошло это более двух месяцев назад, когда я ещё только планировал эту статью.
UPD (10 ноября)
Все операторы на данный момент «согласились» отменить платную раздачу трафика, так что начало этой статьи может оказаться не таким попсовым на выходе, как планировалось.
Пока ещё ничего на практике не изменилось и плата всё ещё взимается, но уже можно рассчитывать на возвращение привычной всем раздачи на не являющихся «безлимитными» тарифах.
UPD (15 ноября)
Платная раздача отменена на большинстве тарифов. Под изменения помимо безлимитных не попали некоторые особые тарифы, у некоторых операторов это старые необслуживаемые тарифные планы.

Манипуляции, которые я разберу далее, останутся в таком случае актуальны для «безлимитных» тарифов, где раздача в принципе не предусмотрена, и в бесплатных сетях, где пролетают пинги, но требуется верификация по номеру телефона или, что ещё хуже, по СНИЛС.

Да, уже есть общественные сети, где идентификация в Wi-Fi происходит через Госуслуги — такой вот нефритовый стержень в колёса свободного интернета.

Подобная схема будет работать и в сетях, где идёт блокировка OpenVPN (с ним мы ещё сегодня пообщаемся) по косвенным признакам или просто всего неопознанного трафика кроме служебного. Собственно, эта идея же настолько стара, как и сам интернет. Она была на пике своём ещё в десятых годах, а вот современный её вид мы с вами рассмотрим далее.
Если вы уже поняли предмет нашего разговора из заголовка, то листайте сразу до оглавления. В противном же случае, предлагаю начать исследовать тему по порядку.

Как это работает?


Сейчас я вам расскажу одну историю из жизни: 4 года назад (в 2019 году) я случайно оказался уж очень далеко от дома. Если быть точнее, то в сибирском смешанном лесу наедине с вышкой сотовой связи и симкой от «Мегафона». Тогда ещё трава была зеленее, а раздача интернета не требовала доп. платы — она просто не работала на моём безлимитном тарифе. Попытки найти способ использовать сеть с ноутбука меня привели к обсуждению вроде этого (4pda, 2014 год). Умельцы на тот момент уже выяснили способ определения раздачи, который использовался для блокировки трафика. Это была простая блокировка по TTL.

▍ TTL


В подробности вникнем позже, пока достаточно такого объяснения:

Каждое устройство отправляет пакет в интернет, делая в нём запись TTL (Time To Live), равную целому положительному числу. Каждое следующее устройство, которое будет пропускать этот пакет через себя на пути к получателю, по идее должно переписывать (TTL) на (TTL-1).

Оператор с лёгкостью замечает, что одно устройство отправляет пакеты с разными TTL, и блокирует те, в которых TTL больше на единицу. Какие же в таком случае есть варианты обхода блокировки?

  1. Отправлять с устройства, подключённого к точке доступа, все пакеты с заранее увеличенным на единицу TTL. В таком случае после ретрансляции телефоном трафик будет выглядеть как его собственный (почти). Однако это невозможно без root (sudo, Admin) прав на подключённом устройстве.
  2. На стороне телефона закастомить точку доступа так, чтобы она не уменьшала TTL. Как вы понимаете, для этого нужно получить контроль над IP уровнем (об этом тоже позже) пакета и редактировать его. Однако, это тоже не представляется возможным без root (sudo) прав на точке доступа. Природа этого тоже будет разобрана в данной статье.

Собственно, первый способ совершенно не универсален и требует root на всех устройствах в схеме, кроме точки доступа. Второй же позволяет ограничиться одним разблокированным устройством. Так вот, в сибирском лесу я оказался тогда с бородатым Galaxy Note 2 (2012 год выпуска), на котором уже давно стояла LineageOS и был root, благо на старых самсах не было никакого Knox, ваш телефон не терял гарантию при перепрошивке и даже не требовал на это разрешения центрального сервера компании-производителя, которое сейчас нужно ждать по несколько недель — да, да Xiaomi у меня тоже побывал.

Готовое приложение с многозначным названием вроде TTL editor на тот момент решило все мои проблемы и обеспечило пусть и медленным (в лесу, всё же), зато расшаренным на ноут интернетом.

▍ DPI


И всей дальнейшей статьи банально не было бы, если бы в прошлом году я не поехал в тот же лес с тем же железом и не обломался с треском, узнав, что теперь трафик блокируют по паттернам его содержимого. Даже в пассивном режиме Windows отправляет массу служебных пакетов на служебные серверы, которые заранее считаются оператором «несвойственными для android/ios».

Вот каких подколов можно ожидать, когда поставщик услуг, которому ты платишь деньги, может абсолютно не считаться с пользователями и «затягивать удавку».

Ладно, ладно, я понимаю, что такой около-пикабушный гонор никому тут не интересен. Если вы ещё здесь, то я безумно извиняюсь за столь зелёное вступление.

Решаем проблему самостоятельно


Моя первая статья на Хабре носит название Ping пакеты как временное хранилище данных на python raw socket, написана она была буквально за одну ночь в состоянии аффекта (хабра-эффекта) и, как и полагается статье из песочницы, не блещет оформлением или качеством текста. Вопреки ожиданиям, эта статья не будет являться переосмыслением (ремейком, ребилдом, повтором) вышеупомянутой. Уровень материала, изложенного тут, обещает быть выше и не будет смахивать на ликбез по видам сетевого оборудования.

Порог вхождения в дальнейший текст — понимание разницы между белыми и серыми IP-адресами. Да, вот такая нынче на Хабре инфляция параметра «сложность» на посте, спасибо можете передать научпопу и новостям.

В момент написания старой статьи я ещё не знал, что переизобретаю PingFS.

«Ты же прямо сейчас собираешься переизобрести PingTunnel, лицемер ты чёртов!» — сказали бы вы сейчас и оказались бы отчасти правы.

В то же время идею мне подкинули в комментариях:
Тык


В общем, размазанное вступление ещё и технической части делать не очень хочется — и без этого есть что рассказать.

Суть проблемы же была озвучена в первом абзаце, а её решение (о боже!) в заголовке. Так что считаю разумным перейти сразу же к оглавлению.

  1. Введение
  2. Ещё немного демагогии
  3. Как это работает?
  4. Решаем проблему самостоятельно
  5. Реальный пакет из WireShark
  6. Начинаем реализовывать
  7. NAT?
  8. ICMP тоже пробивает дыры?
  9. Инкапсуляция
  10. Настраиваем OpenVPN под Windows
  11. Так как же оператор транслирует icmp?
  12. Заключительные штрихи
  13. Вместо заключения

Раз уж тезис о PingTunnel мной был озвучен, то кажется необходимым его развернуть.

PingTunnel — утилита для передачи TCP/UDP-трафика через ICMP.



Есть две ноды, между которыми возможна связь по IP (например, в глобальном интернете).

  • Первая — pingtunnel client (ретранслятор, инкапсулятор).
  • Вторая — pingtunnel server (приёмник, прокси).

Обе pingtunnel-ноды (далее client и server) знают IP-адреса друг друга.

Пользователи за первой нодой подключаются к её порту, а она, в свою очередь, туннелирует все пакеты, полученные из него при помощи ICMP, до удалённой прокси-ноды (server).

PingTunnel Server же от своего имени общается с неким однозначным и неизменным target server.

С точки зрения юзера за pingtunnel clientом, он может общаться с самим клиентом, как если бы это был target server.

Как вы могли заметить, концептуальные неприятности всплывают практически сразу:

Самыми универсальными и везде используемыми типами icmp однозначно являются req (Echo request), repl (Echo reply), time limit (TTL exceeded) и unreach (Host unreachable) — позже мы разберём их подробнее.

Для большей стабильности трансфера полезной нагрузки в многоуровневых сетях по icmp стоит использовать самую популярную связку (req,repl) или (req,time) в качестве альтернативы. Из этого вытекает первое неудобство: сетевой интерфейс ping server должен быть в «режиме простоя» — не заниматься собственным творчеством и не отвечать на icmp самостоятельно.

Решение этой проблемы весьма очевидно — включить режим простоя, однако для понимания самой сути проблемы нужно взглянуть на принципиальное различие между Windows и Linux при работе с сетью.

На самом деле, в стандартном инструментарии Windows не предусмотрена работа с адаптером на пакетном уровне (L2, Ethernet). Историю этой проблемы я разгребать не хотел бы, а первый же ответ на stackoverflow гласит, что причиной тому Win32 limitations — спасибо за многословность. Ну да оно и не важно, ведь оконные люди таки сварили себе почти настоящие сырые сокеты при помощи костыльного драйвера, названного WinPcap.

WinPcap — программный инструмент, работающий в среде Windows и позволяющий взаимодействовать с драйверами сетевых интерфейсов. Функционал программы обеспечивает приложениям возможность захвата и передачи сетевых пакетов в обход стека протоколов.

Самый популярный ui к pcap — это, конечно, WireShark. Его мы и будем использовать для дальнейших экспериментов и наблюдения за поведением скриптов.

Однако переписать стандартные возможности драйвера подобное решение всё равно не может. Пинги всё так же будут получать автоматические ответы от ОС, пока мы её саму любезно не попросим об одолжении.

Как оказалось, этим занимается встроенный брандмауэр, конфигурируемый панелькой wf.msc. Тыкаем Win+R + wf.msc, идём Правила для входящих > Общий доступ к принтерам ... входящий ICMP и выключаем все пунктики.


На Linux можно было бы просто прописать net.ipv4.icmp_echo_ignore_all = ‘1’

Теперь я отправляю пакеты с другого конца города на свой основной компьютер, пробросив ICMP, и как можно заметить на скриншоте ниже, компьютер не отправляет автоматических ответов.


Теперь идём по пути наименьшего сопротивления и находим первое же готовое решение по запросу PingTunnel: github.com/esrrhs/pingtunnel.

Качаем эту реализацию, делаем всё в соответствии с readme-шкой и видим такую картину:


На сервере ситуация аналогична, обе стороны бесконечно ждут подключения. В Wireshark`е же всё выглядит исключительно правдоподобно. Как вы уже могли догадаться, ноды просто не принимают пакеты — для этого нужно использовать pcap.

Второй шанс готовым реализациям я решил дать с ptunnelNG. На его GitHub указано, что он должен работать с WinPcpap и Pcap для полноценной совместимости с Windows…


Npcap стоит, ptunnelNG из коробки его не видит даже в PATH. Можно было бы пойти дальше и перебрать ещё пару-тройку готовых решений, но они все имеют фатальный недостаток. Вы можете справедливо заметить, что упорство всё перетрёт, и я могу где-нибудь найти конфиги, или в крайнем случае изменить и перекомпилировать сам pingtunnelNG — но мне ещё в статье про RuGPT3.5 очертенело чинить чужой код, так что кажется, что пришло время делать свой велосипед.

Своей задачей я ставлю реализовать всё максимально коротко и понятно, пусть и недостаточно качественно для широкополосного подключения. Компромиссом в предыдущих реализациях выступал Go, я же предпочту Python для получения максимально минималистичного proof of concept. (Спойлер: в итоге пропускная способность получилась отличная, и скорость итераций Python даже близко не стала узким местом).

Первым шагом же нужно будет сделать вспомогательный модуль для отправки кастомных ping-пакетов. Для этого предлагаю быстро вспомнить конкретные слои пакета ICMP и связать их с нашими уровнями доступа и возможностями перехвата.

Типичная блок-схема сетевого фрейма c пакетом icmp, которую нам выдаст любой поисковик по запросу «структура icmp пакета»:


Предлагаю не мусолить картинку, как это обычно делается, а сразу смотреть всё на примере живого пакета. Не просто так же мы сниффер поставили, верно?

Реальный пакет из WireShark



▍ L2 | Ethernet | Канальный уровень (14 байт)



В этом заголовке находятся MAC-адреса получателя и отправителя. PCAP обеспечивает нам возможность перехвата пакетов, начиная с этого уровня, однако тут нужно упомянуть канальную фильтрацию.

Канальная фильтрация — нормальное состояние Ethernet сетевой карты, ведь если MAC-адрес назначения в заголовке принятого пакета не совпадает с MAC-адресом текущего сетевого интерфейса и не является широковещательным, то разумным поведением кажется отсеивание такого пакета.

Другими словами, сетевая карта не даст нашему устройству «получить» пакет с битым или некорректным L2-заголовком, так что ничего интересного мы не увидим (даже в wireshark).

Если же вы хотите видеть реально всё, что поднимается с аппаратурного уровня (L1) до канального, то вы можете попросить ОС о переключении драйвера сетевой карты в неразборчивый режим (работает даже под Windows), однако эта информация вам может понадобиться только если вы будете заниматься хардкорными вещами в пределах одной L2-подсети (где между устройствами есть прямая физическая связь по Wi-Fi или Ethernet) вроде MAC spoofing, mitm и в общем случае пентестом.

Т. е. если вы не киберфрик из 2000-х и у вас в подвале не лежит приблуда как на картинке ниже, то вам это знать не обязательно. В противном случае вы уже и без меня знаете, что под Linux можно создавать сокеты сразу L2-уровня и буквально биндиться не к IP-адресу, а к MAC для выполнения самых грязных и мутных фокусов, упомянутых выше.


▍ L3 | IP | Пакетный уровень (20 байт)



На этом слое уже будут лежать IP адреса получателя и отправителя, т. е. будет обеспечена IP-маршрутизация.

А также хеш суммы для верификации, а именно этот уровень обеспечивает корректность заголовка транспортных протоколов, таких как TCP, UDP, ICMP и т. д. Это значит, что уже на L3 известен конкретный транспортный\управляющий протокол следующего уровня, в нашем примере Protocol: ICMP (1)

Мы же ещё можем обратить внимание на тот самый TTL из начала статьи, который в моём случае изначально равен 128 (в то время как дефолтный TTL на линуксах и ведроидах равен 64).

▍ L4 | ICMP | Протокол управляющих сообщений (8 байт)



Собственно, наш сегодняшний пациент. Пока стоит обратить внимание на поле type. В нашем конкретном пакете type=8 (echo req). В ответ на него ожидается type=0 (echo reply) в качестве успеха преодоления маршрута, и какой-либо другой служебный ICMP в случае неудачи, например type=3 (unreachable) или, внимание, type=11 (TTL Exceeded).

TTL Exceeded отправляется в ответ железкой, которая получила пакет с опустившимся до нуля TTL, который либо просто не долетел до получателя, либо заблудился и зациклился.

Кстати, именно на TTL основан tracert — утилита windows для «трассировки маршрута». Она просто отправляет на указанный адрес ICMP-пакеты, каждый раз с TTL += 1. Таким образом на всех нодах по пути к получателю умрёт (TTL упадёт до нуля) хотя бы один пакет, и каждая должна будет раскрыть своё существование ответным ICMP 11 пакетом. Кстати, traceroute на линуксе работает не совсем так же (См Tracert vs Traceroute).

▍ Data | PayLoad


Последний сегмент любого транспортного пакета — пустое место, куда можно положить служебные сообщения, сегменты файлов, запросы местоположения врагов в шутере, и даже записать туда другие пакеты, возможно, даже пакеты совсем другого типа и протокола. В общем свободное место есть — дальше же всё зависит от вашей фантазии.


Начинаем реализовывать


Сейчас мы разберём минимальный и полностью читаемый генератор ICMP-пакета. Для этого используется так называемый RAW socket.

RAW сокет позволяет инициализировать себя с кастомным protocol code (то самое поле L3 уровня в нашем пакете, где было написано 1 — ICMP). L4-уровень же становится полностью подконтролен пользователю.

Для создания такого сокета в Windows нужны права Администратора. Важно упомянуть, что это всё ещё не настоящий SOL_SOCKET, как в Linux, и вы не можете кастомить IP-заголовок так, как вам захочется (т. е. IP-адрес вы так не измените). Единственное же, что подлежит изменению — поле protocol code.

▍ Send ICMP


Для работы с ICMP нам нужно вписать в поле protocol code число 1. Но, полагаю, будет более честно абстрагироваться от этого и достать эту единичку встроенной в Python socket-функцией getprotobyname.

import socket
import struct

ICMP_CODE = socket.getprotobyname('icmp')

Теперь нам нужно посчитать хеш-сумму пакета. Алгоритм я угнал с какого-то открытого ресурса и уже не вспомню его принципа работы (это мне ещё аукнется). Вы можете и сами оценить эту функцию взглядом:


def checksum(source_string):
    sum = 0
    count_to = (len(source_string) / 2) * 2
    count = 0
    while count < count_to:
        this_val = source_string[count + 1]*256+source_string[count]
        sum = sum + this_val
        sum = sum & 0xffffffff
        count = count + 2
    if count_to < len(source_string):
        sum = sum + source_string[len(source_string) - 1]
        sum = sum & 0xffffffff
    sum = (sum >> 16) + (sum & 0xffff)
    sum = sum + (sum >> 16)
    answer = ~sum
    answer = answer & 0xffff
    answer = answer >> 8 | (answer << 8 & 0xff00)
    return answer

Теперь по классике конструируем заголовок из наших чиселок при помощи struct.

Тут есть пара нюансов:

  1. Пакет нужно собрать дважды. Сначала с полем хеш-суммы, равным 0. Посчитать для него хеш-сумму. И только после этого итоговую версию пакета с посчитанным хешем, записанным в это самое поле. (Ну, не можем же мы посчитать хеш от данных, где используется этот же самый хеш, верно?)
  2. Если длина пакета не кратна 2 (нечётна), то я дописываю в конец кастомный паддинг 123. Это первое, что приходит в голову, когда мы эмпирически выясняем, что checksum() не работает со строками, длина которых нечётна.


def create_packet(id,data):
    
    ICMP_ECHO_REQUEST=0 #Код типа ICMP - в нашем случае ECHO
    header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, 0, id, 1)
    data = data+b"\x00\x11\x22"*(len(data)%2)

    my_checksum = checksum(header + data)
    header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), id, 1)
    return header + data

На самом деле вы можете сейчас перемотать текст чуть выше и увидеть в коде функции checksum-строку (len/2)*2, т. е. на самом деле я угнал плохой перевод с python2 на python3 — такая вот суровая участь Legacy enjoyer`а… (В python2 один слеш выполняет над int целочисленное деление, в то время как в python3 сразу переводит во float и делит адекватно).

Теперь реализуем функцию send, которая создаст RAW socket и отправит через него сырые данные.


def send(dest_addr,pkt):
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, ICMP_CODE)
    host = socket.gethostbyname(dest_addr)

    while pkt:
        sent = my_socket.sendto(pkt, (dest_addr, 1))
        pkt = pkt[sent:]

    return my_socket

Использовать наши новые функции можно так: send("8.8.8.8",create_packet(ID,b"Hello!"))

Не забываем, что всё это работает только при наличии прав Администратора!

▍ Recv ICMP


Раз уж самым простым решением для приёма icmp-пакетов под Windows является их перехват на уровне pcap, а мы хотим автоматизировать пайплайн на каждой из сторон, моментально отправляющий и получающий ICMP-пакеты, то нам нужен API на Питоне для pcap.

Само собой, его уже придумали до нас. Вторая же строка поиска (потому что на первой реклама скам-курсов, привет, поиск от Яндекса) выдаёт нам миловидную библиотечку PyPcap.

pip install pypcap
Preparing metadata (setup.py) ... error
error: subprocess-exited-with-error

× python setup.py egg_info did not run successfully.
│ exit code: 1
╰─> [1 lines of output]
pcap.h not found
[end of output]

Ну, на первый взгляд, ситуация не критическая. Да, библиотечка не несёт в зависимостях исходники pcap, отказываясь устанавливаться без них. Вот что говорит readme на GitHub либы:

Note for Windows users: Please download the Npcap SDK, unpack the archive and put it into the sibling directory as wpdpack (setup.py will discover it).

Спасибо и на этом. Качаем dev-версию npcap в рабочую папку установки и пробуем ещё раз:
building 'pcap' extension error
error: Microsoft Visual C++ 14.0 or greater is required. Get it with «Microsoft C++ Build Tools»: visualstudio.microsoft.com/visual-cpp-build-tools

Знаете, когда pip начинает жаловаться на C++ Build Tools и отправляет вас скачивать жирнющий Visual Studio, то, скорее всего, это не поможет. Вы 30 минут будете медитировать перед полоской загрузки, скачивающей вам на компьютер 5 гигабайт инструментов сборки, и как итог pip начнёт падать не с ошибкой Build Tools, а банально из-за ошибок компиляции C-кода. Чистоты эксперимента ради я даже попробовал повторить всё в средах Python 3.8 и 3.10 вместо моей дефолтной 3.12 и абсолютно ничего не получил с этого. Можете даже не пытаться.

Репозиторий GitHub этой библиотеки не менялся уже 5 лет, так что на поддержку рассчитывать не приходится. Благо её уже форкнули и пофиксили. Теперь нашим мессией станет pcap-ct.
pip install pcap-ct

И, о чудо, всё устанавливается с первого раза.

Теперь мы можем создать объект sniffer, обеспечивающий нам заветный recieve любых пакетов, которые мы получаем сетевой картой.

import pcap
sniffer = pcap.pcap(name=None, promisc=True, immediate=True, timeout_ms=50)

Однако это может не сработать на вашем устройстве, как не заработало на моём сервере, где одновременно сосуществуют около десятка сетевых интерфейсов. Для того, чтобы указать конкретный, нужно редактировать аргумент name на идентификатор девайса вашего конкретного адаптера.

Рабочий для меня вариант выглядит так:

sniffer = pcap.pcap(name=r"\Device\NPF_{EC1D1645-C46F-45B4-96F2-19179FFF3CFB}", promisc=True, immediate=True, timeout_ms=50)

Но как же из него читать пакеты? Есть два способа:

  1. Итерация по объекту sniffer (он является генератором) — то есть вызов sniffer.__next__(). За нас это может сделать for packet_num, packet in sniffer: ..., он будет работать бесконечно, автоматически ожидая нового пакета между итерациями, если буфер закончился.
  2. Считывание всего буфера за раз при помощи pkts = sniffer.readpkts() — не останавливает выполнение кода, возвращает всё, что есть на текущий момент, в форме списка. Позже можно также итерироваться по принципу for packet_num, packet in pkts: ..., этот for уже не останавливает выполнение, ведь он просто проходится по считанному буферу и заканчивает свою работу.

Остаётся отфильтровать трафик от всех протоколов, кроме ICMP, и избавиться от broadcast-пакетов, ожидая в Destination IP (поле L3-заголовка) адрес, ассоциируемый с нужным нам интерфейсом.

Это я сделаю ближе к концу, когда буду писать основной livecycle ноды.

Пока на время отвлечёмся в пользу теории и чуть лучше спланируем наши дальнейшие действия.

NAT?


Если вы смоги переварить всё вышеизложенное, то, вероятнее всего, вы не являетесь юзером, который считает, что интернет — это магия, снизошедшая на нас от умных дедов, которые смоги его сделать 80 лет назад. Хотя, даже если вы никогда не ковыряли NAT-трансляцию, а за вас это всегда делал сисадмин (у каждого свой стек как-никак), могу предложить вам свою статью для базового понимания NAT. Дальше я в любом случае буду ссылаться на hole-punch и, пожалуй, даже начну прямо сейчас:

ICMP тоже пробивает дыры?


Спойлер: Иначе и быть не может.

Представим себе абстрактную рабочую сеть с gateway`ем, выполняющим NAT-трансляцию. Трансляция работает с L3, то есть просто переписывает адреса в IP-заголовке (ведь все уровни ниже IP не имеют логического смысла на стыке сетей).

Индикатором необходимости трансляции в приходящем пакете является port.

Порты — те самые штуки, которые «открываются» сисадминами, «пробрасываются» геймерами и «закрываются» антивирусом бабушкина и по совместительству ассоциируются у обывателя с «логической дыркой», выделяемой для конкретной службы вашего устройства.

Если вы относитесь к этим недалёким экспертам и думаете, что «ICMP не использует порты» или «ICMP работает на зарезервированном 1-м порте», то пришло время приоткрыть завесу этой тайны.

И правда, если мы загуглим «Что такое сетевой порт?», то мы получим примерно такой ответ:

Сетевой порт — идентифицируемый номером системный ресурс, выделяемый приложению, выполняемому на некотором сетевом хосте для связи с приложениями, выполняемыми на других сетевых хостах (в том числе c другими приложениями на этом же хосте).

Весьма мутно, не находите? Давайте сами найдём это поле port в пакете. Ловим TCP-пакет вайршарком и…


Source Port и Dest Port находятся внутри TCP (транспортного заголовка). На IP-уровне ещё никаких портов не предусмотрено.

Пингуем 8.8.8.8 и ловим icmp-пакет, чтобы и его препарировать


Как и ожидалось, никакого port нет. По той простой причине, что UDP- и TCP-порты являются сущностями транспортного уровня и появляются вместе с самими протоколами семейств UDP/TCP. Из этого, кстати, следует, что два потока информации, отправленные в «один и тот же порт» протоколов разных транспортных семейств и не перемешиваются.

Ладно, возвращаемся к ICMP. Если из нашей условной подсети разные люди «пингуют» один и тот же внешний адрес, то обратная трансляция для NAT становится неоднозначной. Для решения этой неопределённости в ICMP-пакете есть поле ID. Казалось бы — альтернатива портам, но если мы посмотрим в нашем пакете на поле идентификатора, то мы увидим там очень оригинальную и идентичную для всех пакетов единицу. Судя по всему — это фейл Windows (ну или просто игнорирование фичи, заложенной в концепцию изначально).

Так как же тогда однозначно определять обратный маршрут для пакета?

Поиск информации на эту тему приводит нас к подобной идее: For ICMP query/reply type messages like Echoes (pings), NAPT uses the ICMP Query ID (sometimes just called the ICMP ID) the same way it would use a TCP or UDP port number.

То есть привычную нам роль порта для icmp, как и предполагалось, играет поле ID.
Попробуем найти однозначный ответ на максимально живом примере — моём роутере. Mikrotik открыто позволяет мониторить даже самые мелочи, так что icmp nat сессия не должна будет уйти незамеченной. Заходим на веб-майку и следуем пути IP>Firewall>Connections.

Пингуем 8.8.8.8 изнутри и находим активную сессию трансляции…


И к сожалению, не находим ничего ценного. Сколько бы устройств изнутри ни отправляли пакеты на сколь угодно много устройств снаружи, маршрутизация работает правильно, даже если id у всех пинг-пакетов один и тот же. И как бы ни прискорбно это было осознавать, мне так и не удалось найти спецификацию алгоритма трансляции, который бы вёл себя подобным образом. Я думаю, что роутер просто запоминает пары GrayAddress + 8.8.8.8 во временную память и выполняет обратную трансляцию согласно прямому соответствию адреса отправителя адресу из записи в таблице. Однако для корректной работы такой схемы после обратной трансляции запись нужно удалять и давать шанс сработать следующей записи (например, соответствующей другому устройству подсети, которое пингует 8.8.8.8).

Но с реальностью это совершенно не стыкуется. На один ping req вам может прийти ответ из огромного количества repl, так что схема со стеком записей не похожа на правду, даже в нашей небольшой домашней сетке.

С CG-NAT, подобными тем, что используются операторами сотовой связи, ситуация обстоит логичнее, но в то же время усложняет изначальный концепт. Подробнее о них мы поговорим позже, уже ближе к готовой реализации.

Инкапсуляция


Инкапсуляция — это включение всего пакета одного протокола (то есть его заголовки и данные) внутрь пакета другого протокола в качестве передаваемой информации.

В нашем случае это необходимость обеспечения слоя совместимости сырых данных из icmp-пакета (например, дампа L3-пакета) с реальным стеком L3-отправителя (для захвата и инкапсуляции) и приёмника (для развёртки и маршрутизации).

Для того, чтобы превращать свои данные в сетевые сущности, были придуманы виртуальные сетевые драйверы. Это логические интерфейсы, создаваемые на уровне операционной системы, трафик которых можно полностью контролировать из приложений при помощи стандартных файловых дескрипторов. Традиционно они делятся на два вида:

  1. L3-интерфейсы (network TUNnel) или TUN. Решают именно ту задачу, что я описал выше — дают приложению интерфейс контроля уровня IP. Именно они создаются всякими готовыми VPN-сервисами вроде Radmin, Hamachi и Windscrible.
  2. L2-интерфейсы (network TAP — в переводе «отвод») или просто TAP. Кстати, если вы не перешли по ссылке той пикчи со странным девайсом из начала статьи, то стоит упомянуть, что именно он изначально назывался TAP, и по его внешнему виду в принципе уже можно понять, что делает «сетевой отвод», будь он физический (как на картинке) или логический (как ваши мосты в Windows\Linux). С практической точки зрения используется для «соединения» уже существующих L2-интерфейсов и обычно не используется для VPN.

Слава богу, что нам не придётся самим изучать api виртуальных адаптеров и страдать от проблем инкапсуляции streaming-протоколов в message based.

Как вы могли догадаться, готовое решение существует. И является им широко известный OpenVPN. Он, кстати, позволяет не только соединять два tun/tap посредством udp, но и прописывать один из этих tun как gateway для клиента и использовать основной интерфейс сервера как shared adapter для перенаправления ВСЕГО трафика клиента через сервер — это же сыграет с нами злую шутку позже, но поверьте, результат стоит всех трудностей на пути).

Настраиваем OpenVPN под Windows


Да, в этом блоке я в общих чертах распишу процесс поднятия сервера с shared-адаптером под виндой, ведь там имеются некоторые подводные камни.

Для начала нужно будет скачать сам OpenVPN Server на домашний компьютер (тот, у которого ICMP проброшен во внешний мир).

Думаю, процесс установки не вызовет больших трудностей, да и гайдов в интернете полно.
Единственное, что стоит упомянуть, это необходимость установки wintun драйвера. В новых версиях OpenVPN он идёт в комплекте, в более старых же установщиках (кои могут предлагаться в гайдах) он может не качаться автоматически, в таком случае об этом нужно будет позаботиться вручную. В остальном же процесс установки выглядит примерно так:


Процесс генерации сертификатов и асимметричных пар я тоже, пожалуй, пропущу. Сверить прогресс мы можем по соответствию списков уже готовых ключей:

  • На сервере:
    1. ca.crt
    2. server.crt
    3. server.key
    4. dh.pem

  • Если вы продвинутый пользователь, или гайд вас к этому принудил, то тут могут быть и другие доп. методы защиты вроде TLS — я же ограничусь классическим минимумом.
  • Для клиента:
    1. ca.crt
    2. client1.crt
    3. client1.key
    4. dh.pem

  • client1 — это имя собственное, выданное клиенту при генерации. Оно может быть другим у вас.

Теперь предлагаю посмотреть на наших новых друзей — TAP- и TUN-адаптеры. Увидеть все свои адаптеры можно в "Панели управления" -> Сеть и Интернет -> Центр управления сетями -> Изменение параметров адаптера.

Забавно, что в новых версиях Windows панель управления всё больше и больше вытесняется новым системным приложением «Настройки», в которых мелкомягкие понемногу заново изобретают панель управления. Я серьёзно.

Они хотели сделать панель управления в новом красивом интерфейсе и вместо того, что бы просто закастомить движок рендера UI, они стали заново изобретать велосипед, в котором нет половины функций. Возможно, они элементарно не смогли интегрировать свой новый мусор вроде персонализации и настроек сервисов с аккаунтами в уже готовую и безотказно работающую десятки лет архитектуру, а может быть просто имитируют развитие продукта. Я даже недавно столкнулся со сборкой WIndows, где вообще вырезана панель управления — вот это было реально приключение.

Думаю, останусь пока верен модульной структуре органов управления компьютера и подобно панели брандмауэра, что мы уже видели в начале статьи, вызову этот компонент при помощи:
Win+R -> ncpa.cpl.

Видим, что всё, что нам может понадобиться, уже готово к употреблению:


Теперь можно переходить к конфигурации.
OVPN Конфиг сервера
port 27005
proto udp
dev tun
#topology subnet
ca "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\ca.crt"
cert "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\issued\\server.crt"
key "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\private\\server.key" # This file should be kept secret
dh "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\dh.pem"
#tls-auth "C:\\Program Files\\OpenVPN\\bin\\ta.key" 0
server 10.8.0.0 255.255.255.0
windows-driver wintun

push "redirect-gateway local def1 bypass-dhcp"
route-gateway 10.8.0.1
push "dhcp-option DNS 8.8.8.8"

keepalive 10 600
persist-key
persist-tun
cipher AES-256-CBC
comp-lzo
status "C:\\Program Files\\OpenVPN\\log\\status.log"
log "C:\\Program Files\\OpenVPN\\log\\openvpn.log"
verb 4
#mute 20


OVPN Конфиг клиента
client
dev tun
proto udp
remote 127.0.0.1 27005
resolv-retry infinite
nobind
#persist-key
#persist-tun

ca ca.crt
cert client1.crt
key client1.key
dh dh.pem
#tls-auth ta.key 1

cipher AES-256-CBC
verb 0
comp-lzo
connect-retry-max 25


Если вам лень осознавать написанное в этих конфигах, то вот основные поинты, которые можно из них выцепить:

  • Сервер поднимается на 27005 порту.
  • Сервер заставляет клиента исполнить команду redirect-gateway local def1 bypass-dhcp, которая выбирает в качестве default-gateway на клиентской машине TUN-адаптер. К результату: клиент будет пытаться отправить весь свой интернет-трафик через сервер.

Запускаем сервер и видим, что к TUN-адаптеру «подключился провод».


Чтобы клиент мог использовать сервер как прокси для всего трафика, у него должен быть прописан default gateway как 10.8.0.1 (наш сервер в сети vpn) — это для нас сделала инструкция redirect-gateway, однако со стороны сервера тоже нужна поддержка. Для этого нам нужно на сервере «поделиться» интернетом основного адаптера с TUN-адаптером.




Соглашаемся на то, что Windows перепишет адрес OpenVPN TUN на взятый из воздуха дефолтный. OpenVPN сам поправит его на нормальный. Зачем Windows это делает? Для меня всегда было загадкой. Называется эта вставлялка палок в колёса APIPA (Automatic Private IP Addressing) и нужна исключительно, чтоб портить жизнь честным сисадминам. Ходят слухи, что где-то там в реестре это отключаемо, но мы тут собрались не для того, что бы индусский код чинить.

Теперь обратим внимание на то, что в конфиге клиента осуществляется попытка подключения к 127.0.0.1:27005, что вообще-то является localhost`ом. Всё верно — на этом порту мы поднимем наш супер мега крутой туннель, написанный на Python.

Аналогичная схема будет работать и на стороне сервера, что сделает общую модель примерно такой:


Теперь пришло время добить остатки проблем, связанные с ICMP.

Так как же оператор транслирует icmp?


Для исходящего пакета CG-NAT генерирует временный ID и сам вписывает его в поле id вашего icmp-пакета, запоминая при этом ваш локальный адрес и 8.8.8.8 как однозначно соответствующие ему.

Этот временный идентификатор будет сохранён нашим уловным 8.8.8.8 в ответном пакете, следовательно CG-NAT сможет однозначно транслировать ответ обратно вам. Для удобства, если вы отправляете сразу поток пакетов с одного внутреннего адреса на один и тот же внешний, то транслятор не выдаёт новый id для каждого, а подобно обычной транспортной nat-сессии использует уже существующую запись о соответствии GaryIP -> 8.8.8.8 [ID:123].

Это создаёт необходимость для нашего serverа отвечать клиенту icmp reply пакетами только с тем id же, что записан в icmp req пакетах ОТ клиента. В таком случае мы будем поддерживать уже существующий тоннель в CG-NAT и сможем отправлять много reply и req в любых пропорциях.

Заключительные штрихи


Как ни странно, большую часть работы мы уже выполнили, пока разбирались с генерацией и захватом ICMP-пакетов. Остаётся написать пару циклов, которые будут заниматься трансфером данных в обе стороны и получить готовое решение для такой задачи:


На самом деле нам осталось только написать основные циклы сервера и клиента, которые будут бесконечно применять созданные нами инструменты.

▍ Клиент


Создаём функцию, которая будет играть роль ресивера для всех пакетов OpenVPN Client и отправлять при помощи наших обёрток для icmp.

global addr
addr=("127.0.0.1",123)
def vpn2tun(sock):
	global addr
	while 1:
		d,a=sock.recvfrom(9999)
		addr=a
		print(len(d),a)
		try:
			send(icmpclient,create_packet(123,d))
		except Exception as e: print(e)
		#time.sleep(0.1)

Параллельно с этим нам нужно итерироваться по генератору pcap и фильтруя пакеты отправлять их обратно в OpenVPN Client. И когда я говорю параллельно, это означает, что мы не будем городить ничего сложнее, чем банальный запуск одного из циклов в отдельном потоке.

import threading
t=threading.Thread(target=vpn2tun,args=(sock,))
t.start()

for _,p in sniffer:
	if p[23]==1 and p[34]==0 and socket.inet_ntoa(p[30:34])==me_in_local:
		print(len(p[42:].removesuffix(b"\x00\x11\x22")))
		sock.sendto(p[42:].removesuffix(b"\x00\x11\x22"), addr)

▍ Сервер


Аналогичный клиентскому цикл трансляции, но только в обратном направлении. Пока в качестве id будем использовать некую глобальную переменную (её будет определять цикл захвата icmp).

def vpn2tun(sock):
	while 1:
		global id
		send(icmpclient,create_packet(id,sock.recv(9999)))

В цикл захвата icmp добавляется ещё один небольшой поинт в сравнении с клиентом: адаптация под ID пакета, выданный CG-NAT. Для этого мы просто будем запоминать идентификатор приходящих пакетов, записывая его глобальную переменную id.

В остальном ничего необычного: итерируемся, фильтруем, отправляем в OpenVPN сервер на 27005 порту.

id=123
import threading
t=threading.Thread(target=vpn2tun,args=(sock,))
t.start()

for _,p in sniffer:
    if p[23]==1 and socket.inet_ntoa(p[30:34])==me_in_local and p[34]==8:
        id=int.from_bytes(p[38:40],"little",signed=False)
        print(len(p[42:].removesuffix(b"\x00\x11\x22")))
        sock.sendto(p[42:].removesuffix(b"\x00\x11\x22"),("127.0.0.1", 27005))

▍ Тест


В логах сервера появилось успешное подключение клиента:


Проверим, что диалог идёт в форме icmp:


Таблицы маршрутизации


На самом деле ещё не конец. Если мы сейчас просто возьмём и включим VPN на ноутбуке, подключённом к точке доступа, то увидим постоянно растущую нагрузку канала.


Процессор при этом загружен на 100%.

Не нужно быть гением или пророком, чтобы понять, что трафик зацикливается. OpenVPN пытается отправлять пакеты по UDP на домашний сервер, пакеты инкапсулируются в ICMP, которые тоже стремятся попасть на свой Destination IP, но повторно уходят в интерфейс 10.8.0.1 (OpenVPN TUN). Процесс повторяется бесконечное количество раз.

И нет ничего странного в том, что упёрся в потолок именно график BYTES OUT, ведь чисто технически OpenVPN выполняет преобразование и отсылает всё в 127.0.0.1:55555 (наш туннель). Другими словами, его ни в чём винить нельзя.

Для избежания подобного недоразумения нужно понять, почему пакет вообще летит в 10.8.0.1?
Как-то мы обошли эту тему стороной, но как вообще понять, какой адаптер должен быть ответственен за отправку того или иного IP пакета? На разных интерфейсах могут быть разные устройства с одинаковым IP, соответствующем нашему Destination, не отправлять же на оба…
Да и вообще, маршрутизировать пакеты между L2 адаптерами, основываясь на IP заголовке как минимум странно… — Ну, вообще-то нет.

Это практически так и работает и называется данное действие Маршрутизацией (Routing) и является стандартом для любых ОС, будь то Windows, Linux, RouterOS или какой-нибудь OpenWRT.

То есть пакет проходит через ряд фильтров — таблицу маршрутизации (Routetable) и определяется с интерфейсом, на который ему нужно отправиться по правилам вида «Если твой Dst IP вида 192.168.X.X, то твою судьбу определит интерфейс wlan (WIFI)» или последнее правило, срабатывающее если предыдущие не сработали — «Если твой Dst IP любой, то тебе на Ethernet интерфейс».

На Windows вы можете прописать route print и увидеть подобную моей картину:


К слову, дальнейшую маршрутизацию MAC устройства тоже выполняют основываясь на IP, и это нормально. Например Ethernet в свою очередь выбирает физический адрес получателя, основываясь на ARP таблице, со строками вида «192.168.0.1 -> 01:02:...:05:06)»

Вот, кстати, вывод кусочка ARP таблицы в Windows: arp -a


Но это нас уже не сильно интересует. Нашу задачу в общем случае можно обозвать выборочной отправкой трафика через VPN (кстати, в этом треде чел тоже «воюет» с оператором СоС) и решить при помощи изменения тех самых таблиц маршрутизации.

Наша задача сейчас адаптировать свои routes так, чтобы наши транспортные ICMP отправлялись не на адаптер OpenVPN, а на ваш физический адаптер. На самом деле, в routes не обязательно указывать MAC как пункт назначения, можно использовать привязанный к нему адрес gateway`я. Т. е. туда можно вписать серый ip вашей точки доступа.

route add <Белый адрес сервера> <Серый адрес gateway в вашей локалке>

Победа! Теперь наш ICMP не зацикливается, а сразу вылетает из петли инкапсуляции в сторону точки доступа.


How To Use?


Теперь оставлю вам что-то вроде гайда для самостоятельного использования всего, что мы разобрали. Для примера буду использовать такой тестовый стенд:

  • Дом 36.190.160.236 с Mikrotik 192.168.88.1, пробросившим icmp на домашний сервер 192.168.88.15
  • Точка доступа с адресом белым адресом 83.235.46.166 и серым 10.100.1.2
  • Ноутбук, подключённый к ней с адресом 10.100.23.247

Вот пара one to go скриптов с единственной зависимостью — pcap. Один крутится дома, второй на ноутбуке.

Обратите внимание на переменные, соответствующие IP-адресам — их вам нужно будет задать вручную, если вы решите попробовать всё сами.

SERV
import pcap
sniffer = pcap.pcap(name='\\Device\\NPF_{A99EFA4B-B984-4E10-A34C-B15B161A1697}', promisc=True, timeout_ms=50)


import socket
import struct
import random

ICMP_CODE = socket.getprotobyname('icmp')

icmpclient="83.235.46.166"
me_in_local="192.168.88.15"
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
#sock.setsockopt(socket.SOL_SOCKET, 25, b"eth0")
sock.bind(("127.0.0.1", 55555))
import socket
import struct

ICMP_CODE = 1



def checksum(source_string):
    sum = 0
    count_to = (len(source_string) / 2) * 2
    count = 0
    while count < count_to:
        this_val = source_string[count + 1]*256+source_string[count]
        sum = sum + this_val
        sum = sum & 0xffffffff
        count = count + 2
    if count_to < len(source_string):
        sum = sum + source_string[len(source_string) - 1]
        sum = sum & 0xffffffff
    sum = (sum >> 16) + (sum & 0xffff)
    sum = sum + (sum >> 16)
    answer = ~sum
    answer = answer & 0xffff
    answer = answer >> 8 | (answer << 8 & 0xff00)
    return answer



def create_packet(id,data):
    
    ICMP_ECHO_REQUEST=0 #Код типа ICMP - в нашем случае ECHO
    header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, 0, id, 1)
    data = data+b"\x00\x11\x22"*(len(data)%2)

    my_checksum = checksum(header + data)
    header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), id, 1)
    return header + data



def send(dest_addr,pkt):
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, ICMP_CODE)
    host = socket.gethostbyname(dest_addr)

    while pkt:
        sent = my_socket.sendto(pkt, (dest_addr, 1))
        pkt = pkt[sent:]

    return my_socket

def vpn2tun(sock):
	while 1:
		global id
		send(icmpclient,create_packet(id,sock.recv(9999)))

id=123
import threading
t=threading.Thread(target=vpn2tun,args=(sock,))
t.start()

for _,p in sniffer:
    #print(p)
    if p[23]==1 and socket.inet_ntoa(p[30:34])==me_in_local and p[34]==8:
        id=int.from_bytes(p[38:40],"little",signed=False)
        print(len(p[42:].removesuffix(b"\x00\x11\x22")))
        sock.sendto(p[42:].removesuffix(b"\x00\x11\x22"),("127.0.0.1", 27005))


CLI
import pcap
sniffer = pcap.pcap(name=None, promisc=True, immediate=True, timeout_ms=50)


import socket
import struct
import random
import time

ICMP_CODE = socket.getprotobyname('icmp')

icmpclient="36.190.160.236"
me_in_local="10.100.23.247"

sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
sock.bind(("", 55555))
def checksum(source_string):
    sum = 0
    count_to = (len(source_string) / 2) * 2
    count = 0
    while count < count_to:
        this_val = source_string[count + 1]*256+source_string[count]
        sum = sum + this_val
        sum = sum & 0xffffffff
        count = count + 2
    if count_to < len(source_string):
        sum = sum + source_string[len(source_string) - 1]
        sum = sum & 0xffffffff
    sum = (sum >> 16) + (sum & 0xffff)
    sum = sum + (sum >> 16)
    answer = ~sum
    answer = answer & 0xffff
    answer = answer >> 8 | (answer << 8 & 0xff00)
    return answer

def create_packet(id,data):
    ICMP_ECHO_REQUEST=8 #Код типа ICMP - в нашем случае ECHO
    header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, 0, id, 1)
    data = data+b"\x00\x11\x22"*(len(data)%2)

    my_checksum = checksum(header + data)
    header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), id, 1)
    return header + data

def send(dest_addr,data):
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, ICMP_CODE)
    host = socket.gethostbyname(dest_addr)

    #packet_id = random.randint(0,65535)
    #packet = create_packet(packet_id,data)
    
    while data:
        sent = my_socket.sendto(data, (dest_addr, 1))
        data = data[sent:]

    return my_socket

global addr
addr=("127.0.0.1",123)
def vpn2tun(sock):
	global addr
	while 1:
		d,a=sock.recvfrom(9999)
		addr=a
		print(len(d),a)
		try:
			send(icmpclient,create_packet(123,d))
		except Exception as e: print(e)
		#time.sleep(0.1)

import threading
t=threading.Thread(target=vpn2tun,args=(sock,))
t.start()

for _,p in sniffer:
	if p[23]==1 and p[34]==0 and socket.inet_ntoa(p[30:34])==me_in_local:
		print(len(p[42:].removesuffix(b"\x00\x11\x22")))
		sock.sendto(p[42:].removesuffix(b"\x00\x11\x22"), addr)


Отключаем скам в приложении оператора
Вот так выглядят ваши 10 мегабайт для раздачи, после которых у вас забирают деньги. Спасибо за внимание.


Теперь наша задача выключить назойливый «Режим модема», который ОпСоС норовит вам включить, когда вы палите раздачу. У красного оператора эти тумблеры спрятаны в меню Статистика использования > Добавить трафик > Лучший выбор — забавно, правда?



Теперь у нас не списываются деньги, но и «раздача недоступна»

Остаётся прописать на клиенте статический маршрут командой route add 37.192.163.240 10.100.1.2 и можно бесплатно пользоваться раздачей интернета!

Далее предлагаю оценить диагноз, который нам поставит speedtest — раздутая ведь штука, пусть и бесполезная…

Bandwidth без каких-либо манипуляций


VPN over icmp


Вместо заключения


Полагаю, этот материал позволил мне вам доказать, что icmp-туннели живы даже через десятки лет после их пика популярности, когда ещё не были распространены NAT, а ipv4-диапазон адресов казался вполне себе вместительным.

Была распространена L2-маршрутизация (коммутаторы aka свитчи) можно было гонять icmp с фейковым src ip, не соответствующим твоему. Поскольку по дороге никто не проверяет соответствие src ip и с MAC из arp таблицы, а без NAT в этом нет необходимости, то такой хитрый пакет будет исправно доставлен до адресата и адресат отправит его не обратно тебе, а на выбранную вами цель в поле src ip. Это позволяет сделать массу разных полезных и даже неэтичных вещей.


Однако это ушло в прошлое, и теперь нас ждёт только прекрасный интернет будущего, который, учитывая современные тенденции, может быть суверенен внутри союзных групп стран и жёстко цензурится white-листами доверенных доменов совершенно не таким, каким бы его хотели видеть создатели и конечные пользователи.

На этом я, пожалуй, закончу своё повествование, но, как всегда, ожидаю вас под постом — здравая критика в комментариях исключительно приветствуется.

Узнавайте о новых акциях и промокодах первыми из нашего Telegram-канала ????

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


  1. w1ldy0uth
    22.11.2023 09:28
    +18

    Очень классная статья, спасибо


    1. CodeDroidX Автор
      22.11.2023 09:28
      +7

      Спасибо за обратную связь!


    1. Didimus
      22.11.2023 09:28
      +1

      Спасибо автору, испытал хабрааффект (с) автор


  1. ionicman
    22.11.2023 09:28
    +31

    Ради такого и читаешь хабр, жаль редко появиляются статьи такого уровня.

    Спасибо вам за отличный материал от человека, который когда-то писал свой собственный сниффер на базе WinPCap-а и даже написал, но давно уже все забыл )


    1. vint59
      22.11.2023 09:28
      -5

      99 процентов статей хабра уровня " смотрити , я покаколь"


      1. FreeNickname
        22.11.2023 09:28
        +9

        Ну, Ваш комментарий знатно поднимает эту планку.


      1. t38c3j
        22.11.2023 09:28

        на любом ресурсе так, просто не надо читать хар как ленту, заходите раз в неделю и читайте лучшее


  1. dimars08
    22.11.2023 09:28
    +2

    Спасибо за материал, Андрей. Надо попробовать))


  1. ms25080205
    22.11.2023 09:28

    МТС, тариф СУПЕР МТС 052016 - при попытке включить раздачу на телефоне приходит SMS про подписку МТС Premium - причем данная подписка ничего (совсем) не дает - сам тариф достаточно вкусный и почти все плюшки просто дублируются.

    Лечение на телефонеточень замороченное, попробовал в свое время и не получилось - в итоге использовал китайский-китайский GSM - WiFi роутер, он раздает без вопросов.


  1. SkyHunter
    22.11.2023 09:28
    -4

    Тем временем,

    МТС отменяет плату за раздачу интернета со смартфона.
    https://www.rbc.ru/life/news/655755a99a7947c54338c8b7



    1. Lazhu
      22.11.2023 09:28
      +3

      Соответствующие настройки в тарифных планах у всех абонентов будут реализованы не позднее 29 февраля 2024 года.

      Пока приходят СМСки счастья


    1. Ozarenie
      22.11.2023 09:28
      +2

      Мне интересно на сколько вообще законно было ограничивать раздачу интернета со смартфона.


      1. ms25080205
        22.11.2023 09:28
        +2

        А кто не залетал на премиум-трафике? Кто не помнит, это открытый ресурс, за сам факт скачивания которого списывается плата. Это отменили, и довольно быстро, но тем, кто пострадал и не скандалил так ничегои не вернули.


        1. xenon
          22.11.2023 09:28
          +4

          Какие тут важные слова - "... и не скандалил". Вспоминаю как Шульман рассказывала, что если очередь к специалисту в поликлинике очень длинная (не живая, а та, которая "в апреле подходите") - можно пойти к заведующей, пожаловаться, и оказывается, там есть еще одна, параллельная очередь "для тех кто жалуется" - гораздо более короткая. Вам надо срочно? Ну что же вы сразу не сказали, тогда в четверг. А если вас устраивает в апереле - тогда в апреле!

          Я так влетел с МТСом на этой раздаче трафика на небольшую сумму, кажется, 50р. (там после первого байта приходит SMS, что ах, вы раздаете? немедленно прекратите, а то мы разрешим вам раздавать за 50р в день! А через какое-то время списывают 50р и можно раздавать). Написал в поддержку, сказал, что "ничё не знаю, нам этот ваш интернет не нужон, особенно когда можно случайно на телефоне одной кнопкой включить раздачу и потратить 50р". Попросил отключить возможность раздавать - и знаете что? Оказывается, можно это попросить и они это делают! Видимо, просят так - многие тысячи, и они автоматизировали. Ну и сказал - я там 3 мегабайта вчера выкачал (случайно) - вы с меня 50р за них списали. Таких цен даже в 90-ые не было. Верните пожалуйста. Вернули!

          После этого свободно раздавал через прокси на телефоне и через завышенный TTL на ноуте, но тел уже не истерил про раздачу и деньги не списывались.


          1. ms25080205
            22.11.2023 09:28

            На этом и построен бизнесок, скандал не нужен, чаще всего встают на сторону клиента. Но кому пофиг тому пофиг. Ну там GPS маячок может подписаться на ежедневный гороскоп... Как на поле с коровками, чуть что - и вляпался, создана совершенно ненужная работа, надо раз в месяц заходить в ЛК и контрллировать списания, плюс смотреть "бесплатные" сервисы, которых в прошлый раз не было - они со временем перерождаются в платные.


          1. Artemko_one
            22.11.2023 09:28

            Работал на горячей линии одного из операторов. Многие вещи нужно для начала хотя бы попросить. Самим работникам предлагать абоненту отключить что-то платное или вернуть деньги запрещено. А на некоторые просьбы (тариф без абонентской платы; отключить интернет; отключение раздачи возможно тоже было бы в этом списке, но мой оператор видимо на этом людей не обманывал, так как ни разу с такой просьбой не обращались) нужно было отвечать, что такого нет. И только если клиент конфликтный или настойчиво прямо просит, то тогда делать что-то.

            При этом желательно не портить настроение работнику, он в этом цирке обязан вместе с вами участвовать. Иначе он может обидеться, повторно сказать что такой услуги нет и сбросить звонок. Потому что за такое вряд ли сильно прилетит, а нервы сэкономит.


            1. Didimus
              22.11.2023 09:28

              У клиентов есть признак конфликтности? Походу, у меня он проставлен


              1. Artemko_one
                22.11.2023 09:28

                Имеется в виду в рамках одного разговора. Часто сразу становится понятно по человеку, плюс видно историю обращений


                1. Didimus
                  22.11.2023 09:28

                  Тем не менее, на одном и том же тарифе мне не подключают незаметно всякие левые услуги, а родственникам пенсионерам подключали. Значит, знают, кто менее защищен, а кто будет права отстаивать


      1. omgiafs
        22.11.2023 09:28
        +1

        Все действия поставщиков услуг в "этой стране" основаны на том, что потребитель услуг не пойдёт в суд - у нас так не принято.

        Вы тариф оплатили, причём заранее. Трафик купили. Вам не дают использовать то, что вы купили, вымогая дополнительную сумму, вот как это выглядит.


        1. WebPeople
          22.11.2023 09:28

          Не принято, потому что дорого это делать( А результат не очевиден, даже когда ты вроде как прав. Я трижды с похожими вещами сталкивался, всегда возвращали. Причем не деньгами, а бонусом на счёт телефона. Один раз у меня лишние деньги списали, после звонка в поддержку - вернули, а когда попробовал на них покупку в апстор сделать, то не смог их потратить. После моего гневного звонка мне сказали, что ничего не могут сделать. Обращайтесь в суд...


  1. nameisBegemot
    22.11.2023 09:28
    +1

    Позвольте вас спросить, автор, это у вас такое хобби - разбирать сетевые технологии на уровне инженерии? Или это профессиональное?


  1. MinimumLaw
    22.11.2023 09:28
    +3

    Кто первым напишет в каком номере Хакер'а лохматого года это было? Или там было не ICMP, а упаковка в DNS-запросы? Забыл уже... Давно было...

    Но в любом случае здесь получилось подробнее. Заслуженный плюс.


    1. V-King
      22.11.2023 09:28
      +9

      Помнится, мы в далёком 2005 так нахаляву сидели в кафешках. Привет Таттелеком :) Паковали всё в DNS. Скорость была не айс, но сидеть можно было "без СМС и регистрации" :)


      1. xenon
        22.11.2023 09:28

        Я так из дома сидел через карточки ROL20, кажется. Там был ночной безлимит(!). А когда оплаченные дневные часы оканчивались - DNS все еще работал! Через него и запускал тоннель. Но всерьез им не пользовался. Неудобно, медленно, и такая корявость для жизни и работы не подходит. Но мне понравилось, что увидел, что это возможно прямо на практике.


        1. MinimumLaw
          22.11.2023 09:28
          +1

          Да, с ночным ROLом была история... Я просто не отключился, и... меня тупо не отключили. Так что ночной тариф превратился в круглосуточный - лишь бы телефонная сеть не подводила.

          За тот баг я получил свое первое спасибо ;-)


          1. Jamm3r
            22.11.2023 09:28
            +1

            так вот это откуда- "...НЕ БЫЛО НИ ЕДИНОГО РАЗРЫВА!" )))


            1. MinimumLaw
              22.11.2023 09:28
              +2

              Не. Все проще.

              На вторые сутки я с работы позвонил в службу, назвал логин/пароль и описал ситуацию. Как водится саппорт тут же перекинул на технарей, которые звонку откровенно удивились, проверили журналы, нашли подтверждение и пошли исправлять. Заикнувшись про то, что у нас за такое вообще-то бонусы полагаются, но позже. Баг починили, а бонусы остались где-то в дебрях ROLа.

              Почему сеть держала - это вопрос. Обычная координатка, обычно особым качеством не отличалась. Обычный софтовый шпрот, ни какой-то там элитный Курьер, Зухели или IDC. Но тут факт, что называется, на лицо - двое суток в режиме "скачай весь интернет". А о баге сообщил просто потому, что ночной интернет ночным интернетом, а почту FIDO'шную все равно забирать надо. Негоже боссу диск забивать. Ну, а отключиться самому уже рука не поднималась ;-)

              Вот так я поломал кому-то шикарную мазу попользоваться интернетом почти нахаляву.


    1. fearan
      22.11.2023 09:28
      +8

      Примерно 1996-97 год, когда начали массово туннели строить поверх icmp - у многих провайдеров icmp не учитывался в биллинге.


    1. Format-X22
      22.11.2023 09:28
      +2

      С упаковкой в DNS ещё взломщики всякие балуются, чтобы их активность фильтры не замечали, и ведь вполне могут не замечать, особенно если IPv6, поллиннгом за командами ходят, в обратку данные и никто не видит.


    1. MajorMotokoKusanagi
      22.11.2023 09:28
      +1

      Грубо - публикация из архивов сайта от 20 декабря 2002 года

      Смысл его состоит в том, что хакерскийклиентский компонент "упаковывает"воровской IPv4-траффик в dns-запросы наразрешение адреса по имени (или в какие-либодругие запросы) и отправляет их dns-серверупровайдера. Провайдерский сервак, не найдяответы на эти вопросы, форвардит их дальше,вышестоящему dns-серверу. Таким образом, этизапросы достигают серверного компонента (владельцазапрашиваемого домена). Серверная частьотправляет осмысленные ответы (смыслкоторых понятен лишь злобному хакеру =)),которые, в конечном счёте, достигаютклиентского компонента.

      Или в печатном издании?


      1. MinimumLaw
        22.11.2023 09:28

        Спасибо. Было что-то подобное и в печатном издании. Но и этого достаточно.


  1. VADemon
    22.11.2023 09:28

    свои routes так, чтобы наши транспортные ICMP отправлялись не на адаптер OpenVPN

    Если можно маршруты не трогать, то лучше не трогать, а прописать исходный (локальный, не VPN) IP при открытии сокета. Это же сделает переход на IPv6 версию проще, пользователю можно дать на откуп выбор правильного IP.


  1. LF69ssop
    22.11.2023 09:28
    +7

    Оператор с лёгкостью замечает, что одно устройство отправляет пакеты с разными TTL, и блокирует те, в которых TTL больше на единицу. Какие же в таком случае есть варианты обхода блокировки?

    А почему не упомянут самый простой способ - поставить на устройство с интернетом прокси сервер? Все запросы наружу пойдут только от него, запросы пойдут только от приложений в которых настроен доступ через этот прокси.


    1. vikarti
      22.11.2023 09:28

      Например нужно этот прокси - настраивать. Есть приложения которые не умеют. Можно конечно изврат-способами.

      А еще - если подключение к прокси не шифрованное то DPI в него вполне может залезть (а шифрованное в браузерах как минимум некоторых делается только через .pac-файл)


      1. LF69ssop
        22.11.2023 09:28

        А еще - если подключение к прокси не шифрованное то DPI в него вполне
        может залезть (а шифрованное в браузерах как минимум некоторых делается
        только через .pac-файл)

        Я не понял про что вы. Подключение к прокси это ваш ноутбук подключается к вашему телефону (вероятно wifi), оператор возникает уже после прокси, когда телефон от своего имени лезет наружу.


  1. alexandershelupinin
    22.11.2023 09:28
    +4

    статья гуд, но такие фразы коробят "для всех текущих 4 монополистов рынка сотовой связи". Либо монополист, либо 4. Надо понимать что по соотношению качество/цена у нас одна из лучших, если не лучшая, страна на планете. Как грится "а вы цены в США видели?" Т.е. тоже оборудование что и в Европе+США наши операторы должны покупать и обслуживать, имея прибыль с абонента в ~10 раз ниже.


    1. iroln
      22.11.2023 09:28
      +18

      для всех текущих 4 монополистов рынка сотовой связи

      Правильнее называть это картелем. Денег у операторов много, не надо их жалеть. Бедные несчастные прямо, мешают им два раза просить денег за интернет.

      > "а вы цены в США видели?

      Может нужно сравнивать цены на услуги с учётом макроэкономических показателей, например, ВВП на душу населения?

      > по соотношению качество/цена у нас одна из лучших, если не лучшая, страна на планете

      Качество чего? Интернета под контролем СОРМ и РКН? Лучшая страна на планете, да уж.


      1. alexandershelupinin
        22.11.2023 09:28
        +2

        " Может нужно сравнивать цены на услуги с учётом макроэкономических показателей, например ВВП на душу населения? " не лучше, потому что безотносительно ВВП и з.п. , операторы в РФ покупают ровно тоже оборудование что в Европе + США, имея ARPU в ~10 раз ниже. Безотносительно ВВП и з.п., экономических чудес не бывает, в 10 раз ниже это в 10 раз ниже. Погуглите про ARPU


        1. iroln
          22.11.2023 09:28
          +6

          Всё это всё равно связано с экономикой, нельзя сравнивать просто в абсолютных значениях, не учитывая всё остальное. Если взять тот же Spotify (для него тоже можно посчитать метрику ARPU), когда он ещё был в России, то цена в России на подписку была ~3 раза ниже чем в США и в ~2 раза ниже чем в ЕС, потому что по американским/европейским ценам никто бы в РФ его подписку не покупал, он не смог бы конкурировать на локальном рынке.


          1. venanen
            22.11.2023 09:28

            Вы думаете, что нашим опсосам оборудование так же продают со скидкой?


            1. deseven
              22.11.2023 09:28
              +6

              Вы думаете, что оборудование это единственная статья расходов опсосов?


        1. kacetal
          22.11.2023 09:28
          +4

          Ага, и зарплаты всех сотрудников такие же как и в США конечно.


          1. xenon
            22.11.2023 09:28
            +1

            Причем, они даже и не должны быть такими. Любой гражданин пользуется разными услугами - парикмахеров, сантехников, таксистов, платных врачей, суши домой заказывает. И эта часть его расходов идет по местным ценам. Вряд ли в США врач вас примет за две, три или пять тысяч рублей.


        1. lorc
          22.11.2023 09:28
          +5

          Кроме цены оборудования/материалов есть цена труда. И она сильно выше в развитых странах.

          Отсюда, кстати, растут ноги таких приколов как "крупноузловой ремонт" - дешевле заплатить не сильно квалифицированному рабочему за замену всего блока, чем тратить день работы высококвалифицированного специалиста на поиск и замену сгоревшего транзистора.


          1. 2PAE
            22.11.2023 09:28
            +3

            В первую очередь это от цены простоя. Дешевле вот прямо сейчас заменить крупный блок и работать, чем не работать.


      1. ciuafm
        22.11.2023 09:28
        +1

        Так о том и речь. Вам же трафик фильтруют, это дополнительная услуга - вот и набегает деньга...


      1. ms25080205
        22.11.2023 09:28
        +1

        Одинаковая услуга. Если у потребителя есть возможность платить больше, это же не повод заставлять его платить больше? Обратите внимание, законы рынуа не работают, оператор который снизит цену от неадекватной до приемлемой, может перетянуть себе клиентов и... отчего-то никто так не делает. Загадка!

        Интернет везде под контролем. Возможно, есть ресурсы, которые мониторят это на серьезном уровне, но даже просто переключая различные страны в VPN сервисе видим различную картину блокировок, но везде что-то недоступно, без заявлений и заглушек "по решению такого-то суда", просто не открывается и все. Это реальность, мы не обязаны быть "святее папы римского", лично я бы ту же википедию давно уже отфильтровал, а она до сих пор живее всех живых, как и тытруб.


      1. pushd0w
        22.11.2023 09:28

        Ну как бы там ни было в штатах заменой сорма служит призма, а цена за единицу скорости интернета в России действительно одна из самых низких.


    1. slonoten
      22.11.2023 09:28

      Квадрополия


    1. ms25080205
      22.11.2023 09:28
      +1

      Кстати, наши операторы занимаются (подозреваю, добровольнл-принудительно) натурально социалкой - ставят базу в жуткой дыре, например, деревне на 25 жителей. Очевидно, что это не окупится никогда и ни при каких обстоятельствах, но ставят.


      1. StjarnornasFred
        22.11.2023 09:28

        Это нужно не только (и не столько) для местных жителей, но и для туристов, геологов и т. д. всех, кто уехал в глушь и мог бы жаловаться, что связи нет.


        1. CorruptotronicPervulator
          22.11.2023 09:28
          +1

          Для этих категорий придуманы спутниковые телефоны.


      1. CorruptotronicPervulator
        22.11.2023 09:28
        +6

        Эта имитация деятельностиь финансируется из бюджета, т.е. из наших с вами налогов.


        1. ms25080205
          22.11.2023 09:28

          Я не знаю этого на 100%, однако есть сильное подозрение, что это "отягощение" при оформлении лицензий, хочешь окучивать город-милионник - обеспечь покрытие в дер. Гадюкино. Колхоз - дело добровольное.


      1. Didimus
        22.11.2023 09:28

        Что-то вдоль трассы м11 до сих пор не везде есть связь.. И железная дорога до сих пор за пределами городов без связи.

        В деревнях базовые станции, полагаю, скорее, ставят на магистральных ретрансляторах. Просто в деревне есть электричество, потому там и ставят вышку ретранслятора.


  1. saga111a
    22.11.2023 09:28
    +2

    А я просто меняю ТТЛ, запускаю фаерволл и разрешаю доступ только тому что мне нужно(чтобы сервисы ни винды ни линуха не ходили по своим адресам). Почти всегда работает.


    1. xenon
      22.11.2023 09:28

      Другой вариант - VPN. После того, как у меня wireguard запустился - весь мой трафик с одним сервером. И пофиг, какой там TTL и какие сервера - все превращается в wireguard трафик.

      Но нужно что-то вроде killswitch делать, потому что пока wireguard не поднялся - все идет в открытую.


  1. AdVv
    22.11.2023 09:28
    +2

    Пинги ходят далеко не всегда. Давайте не будем мелочиться

    https://habr.com/ru/articles/129097/


  1. vikarti
    22.11.2023 09:28
    +1

    Классно. А кстати вопрос - замедление в 3 раза а во что упирается? Загрузку процессора?

    Если сервер взять от RuVDS где статья а клиентом как и раньше телефон то будет ли скорость выше?

    Будет ли этот трафик тарифицироваться RuVDS'ом?


  1. olegtsss
    22.11.2023 09:28

    Отличный материал, автор - вы молодец). Мне стало интересно с трансляцией icmp черeз nat. Что там по rfc я не помню, но под рукой все есть, чтобы по-экспериментировать. Складывается впечатление, что связка IdBE и IdLE в пакете icmp является привязкой соединения (по аналогии с вычислением хеша от ip и порта в nat). Практика такова: два компа пингуют сервер в интернете. PC1 имеет в пакете icmp следующее: IdBE=2, IdLE=512, для каждого соединения генерируются новый, после прохождения NAT они не изменяются, ровно как и в ответах от сервера в обратную сторону. PC2 имеет IdBE=4981, IdLE=29971 - аналогичная ситуация.

    Туннель через icmp с вложенным в него vpn - отличная идея, судя по скорости. Провайдеры могут добраться до этого протокола и зашейпить без суда и следствия на какие-нибудь 32 кбит/с. Но этого не случится, ведь нас ждет светлое будущее и суверенный интернет.


    1. xenon
      22.11.2023 09:28

      Тут главное быть фриком-извращенцем, психом-одиночкой. Добрались до ProtonVPNа, до SurfShark'а, до OperaVPN (кстати! они его вернули!), вот недавно до всего что на OpenVPN и Wireguard добрались и пытались временно блокировать. Добираются до целей, которые можно сделать и сразу получить огромный результат. Но если ты используешь какой-то совсем уж черезжопный метод, никто не будет разбираться с ним ради тебя одного, да еще и вносить код по его блокировке на все ТСПУ страны.

      Я для себя решил - если совсем задолбает, мой выбор - wireguard + https://github.com/infinet/xt_wgobfs . Дешево, сердито и мало кто будет использовать.


      1. MiraclePtr
        22.11.2023 09:28
        +2

        Но если ты используешь какой-то совсем уж черезжопный метод, никто не будет разбираться с ним ради тебя одного, да еще и вносить код по его блокировке на все ТСПУ страны.

        Я для себя решил - если совсем задолбает, мой выбор - wireguard + https://github.com/infinet/xt_wgobfs . Дешево, сердито и мало кто будет использовать.

        Для того, чтобы грохнуть ваш "черезжопный метод", нне нужно вносить код по его блокировке на все ТСПУ страны.

        Некоторое время назад во время известных событий в Дагестане, Роскомнадзор пытался заблокировать Telegram в некоторых регионах. Telegram-прокси для DPI выглядят совсем недетектируемо - как набор рандомных байт без каких-то сигнатур. И знаете что сделал РКН? Они просто заблокировали все неопознанные протоколы, работащие поверх TCP. HTTP работает, HTTPS работает, SMTP работает, IMAP работает, а все что "неизестное и ни на что не похожее" - нет. И таким образом у людей еще перестал работать Shadowsocks, который тоже выглядит как набор рандомных байт и не детектируется. А на сопутствующий ущерб им было плевать - были, например, сообщения о том, что перестали работать подключения к Radmin (протокол которого DPI, видимо, тоже не знает), но никому за это ничего не было.

        Многие уже используют недетектируемые UDP-based протоколы, такие как AmneziaWG, KCP, Hysteria. Когда начнут резать все неопознанное TCP, народ массово перепрыгнет на UDP, и РКН в любой момент может начать резать все "неопознанное" и с UDP тоже. И ваш xt_wgobfs такую блокировку не переживет.


        1. Lazhu
          22.11.2023 09:28

          РКН в любой момент может начать резать все "неопознанное"

          Для борьбы с подобными подставами придумали обфускацию


          1. MiraclePtr
            22.11.2023 09:28

            Совершенно верно. О том и речь, что с с обфускацией шансы иметь работающий туннель гораздо больше, чем с какими-то "черезжопными методами".


            1. MiraclePtr
              22.11.2023 09:28

              Поправлюсь, "с обфускацией под стандартный протокол", конечно же.


        1. xenon
          22.11.2023 09:28

          Ну тут - против лома почти нет приема. И этот метод слишком дорогой для них, экстренный. Ну вот если такое будет - окей, на этот случай нужны другие методы. Но они (другие) уже для нас "дорогие", неудобные, медленные.

          Поэтому, мое мнение - пока ситуация относительно ровная - вообще wireguard. И имеем очень быстрый шустрый интернет, прямо как надо! Дальше еще посмотрим, там может шах, может ишак. Вот настанет везде "дагестан" - будем корячить себе эти более хитрые и неудобные VPNы. Но мне кажется неправильным, если вокруг все на пляже в бикини, а ты в костюме химзащиты, потому что вероятность химической или радиационной катастрофы ненулевая. Всегда носить химзащиту - тоже проигрышно.


          1. MiraclePtr
            22.11.2023 09:28

            Поэтому, мое мнение - пока ситуация относительно ровная - вообще wireguard. И имеем очень быстрый шустрый интернет, прямо как надо! Дальше еще посмотрим, там может шах, может ишак.

            Опять же, имейте в виду, что есть свидетельства, что даже пока нет блокировок, РКН собирает некую статстику по детектированным VPN-протоколам на адресах, и когда начинается веселье, то в бан попадает весь адрес. На NTC.party были сообщения от пользователей, кто в период обострения не мог достучаться до своего сервера вообще (даже по HTTPS) из-за того, что до этого времени на том же IP стоял OpenVPN или Wireguard сервер.

            Вот настанет везде "дагестан" - будем корячить себе эти более хитрые и неудобные VPNы.

            Да в большинстве из них нет ничего неудобного, один раз настроил и пользуйся как обычно.

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

            Времена расслабухи на пляже давно прошли, сейчас по пляжу бегает толпа психов и весело катает полутонную бочку с хлором. И крышка у бочки уже пару раз отлетала.

            В таких условиях может и излишне постоянно носить костюм химзащиты, но проверенный противогаз в рюкзаке иметь очень желательно. Потому что добежать до магазина с противогазами в случае чего времени уже может не быть.


  1. aegor
    22.11.2023 09:28

    Статья хорошая, спору нет. Но в в данном конкретном случае это решение избыточно примерно как микроскоп по отношению к гвоздям. достаточно набрать, например, в google play фразу "http proxy server", скачать тот, у кого меньше рекламы. Прописать на дивайте прокси. И радоваться. Там есть как http-прокси, так и socs, и даже прозрачные.

    И да, как только явление станет более-менее массовым, зашейпят на раз. Ведь шейпят же и так "ping -f". Так что как эксперимент для себя - норм, как рабочее решение - ни о чём.


  1. Suhayli
    22.11.2023 09:28
    +2

    Есть готовый программа для андроид и виндовс под названием Droidvpn в котором уже реализовано этот метод. Уже 2 года пользуюсь когда заканчивается ежемесячный трафик или когда нужно скачать какой нибудь большой файл или при раздаче интернет(root)


  1. DennisP
    22.11.2023 09:28

    Насколько я помню, VPN over ICMP реализовано в Softether больше 10 лет назад. Но там нет (не было?) поддержки мобильных устройств.


  1. Keroro
    22.11.2023 09:28

    А можно tldr; ? С целью отучения ОПСОС-ов от жадности предлагается упаковывать траффик на клиенте скриптом для PCAP в ICMP (посредством виртуальной сетевки созданной openVPN), и потом его обратно распаковывать на сервере? И такая схема работает при нулевом баллансе на счету и\или блокировкой ОПСОС-ом раздачи интернета через модем, через который клиент ходит в сеть?


  1. GaryKomarov
    22.11.2023 09:28

    Не проще поднять прокси на смартфоне?


    1. DennisP
      22.11.2023 09:28

      VPN over ICMP может позволять получать халявный траффик от опсоса а также выходить в интернет через Wi-Fi без авторизации на captive portal (вроде как иногда еще такое работает, судя по форумам)


      1. GaryKomarov
        22.11.2023 09:28

        Закончится подобное запретом ICMP трафика


        1. DennisP
          22.11.2023 09:28

          Люди этим занимаются уже лет 15, но полного запрета всё еще не, но движение в этом вопрсе есть. Судя по тому, что мне попадалось, очень часто скорость режется на уровне несколько Кб/С


  1. amberovsky
    22.11.2023 09:28

    Забавно что трюк с TTL сработал, я ожидал операторов в response ставить TTL = 1


  1. TimsTims
    22.11.2023 09:28
    +1

    Оператор с лёгкостью замечает, что одно устройство отправляет пакеты с разными TTL, и блокирует те, в которых TTL больше на единицу. Какие же в таком случае есть варианты обхода блокировки?

    Есть вариант гораздо проще - поднимаем на телефоне proxy server, и при подключении к нему в настройках wifi указываем адрес этого прокси.

    Так как подключения инициализирует сама программа на телефоне, то TTL не уменьшается, раздача работает нормально.


    1. DennisP
      22.11.2023 09:28

      Настройки прокси в Андроиде и Винде - вещь сугубо рекомендательная, многие программы их игнорируют.


      1. NiceDay
        22.11.2023 09:28

        c этим отлично помогает, например, proxifier


        1. DennisP
          22.11.2023 09:28

          Это понятно. Если говорить об установке дополнительного софта, мне кажется проще уже поставить что-то для редактирования TTL


  1. wataru
    22.11.2023 09:28

    К сожалению, такие тонели операторами детектятся вообще элементарно. Ну не посылают обычные клиенты мегабайты ICMP трафика. Так что запросто могут его ограничить 5кб/с а то и вовсе резать.