Ник Пост Дата
gepron1x(Георгий)

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

По словам @bol-van войс блочат именно по STUN.

Решаюсь написать кастомный фильтр для WinDivert:

Первая попытка успешная! Я сделал простейший фильтр на длину udp Payload, которую подсмотрел в Wireshark. Войсчат в дискорде работает.

Моя конфигурация

start “zapret: http,https,quic” /min “%~dp0winws.exe” ^
–wf-raw=“(tcp and remotePort == 443) or (udp and (udp.PayloadLength == 74 or udp.PayloadLength == 20))” ^
–filter-tcp=443 --hostlist=“%~dp0list-discord.txt” --dpi-desync=disorder2 --new ^
–filter-udp=50000-65535 --dpi-desync=fake --dpi-desync-cutoff=d4 --dpi-desync-repeats=6 --dpi-desync-any-protocol

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

2024-10-09T23:39:33.409Z
Decavoid(Decavoid)

--dpi-desync-cutoff=d4 --dpi-desync-repeats=6
Эти ключи необходимы? Что если их убрать?

2024-10-10T00:11:51.479Z
bolvan

repeats не знаю, а без cutoff будет беда, усиленная кратно через repeats

2024-10-10T05:27:59.567Z
bolvan

я бы рекомендовал сохранить стандартный фильтр через --wf-save
там есть ряд важных ограничителей
и над ним уже издеваться

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

я не исследовал блокировку дискорда
вывод о стуне был сделан на базе постов в обсуждениях. может еще что-то есть

в течение 2 недель собираюсь выкатить юзер моде реализацию ипсетов
но когда подсетей мало лучше использовать wf-raw

2024-10-10T05:34:06.976Z
SsSAtonioSsS(Antonio)

Можно ли определить конкретный пакет по его началу?
Конкретно пакеты auth в discord:

0000   xx xx xx xx xx xx 2c f0 5d a3 58 ee 08 00 45 00
0010   00 66 d1 4d 00 00 80 11 5a 70 c0 a8 32 32 22 00
0020   f9 ee e5 0c c3 58 00 52 6d fc 00 01 00 46 00 00
0030   e4 df 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0040   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0050   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0060   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0070   00 00 f4 f7

0000   xx xx xx xx xx xx 2c f0 5d a3 58 ee 08 00 45 00
0010   00 66 d1 4e 00 00 80 11 5a 6f c0 a8 32 32 22 00
0020   f9 ee e5 0d c3 58 00 52 bf d4 00 01 00 46 00 00
0030   e4 df 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0040   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0050   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0060   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0070   00 00 a3 1e

У пакетов общие 5 байт в начале payload и 2 байта в конце.

Можно ли указать это для нахождения нужного пакета?
Первые 4-5 байт данных не изменяются.
–wf-raw=“udp.Payload[0:3]==0x00010046”
При указании ничего не работает…

2024-10-10T14:18:09.533Z
partyhard

Во-первых, udp.Payload[i] работает с байтами. Для работы с 32-разрядными словами (4 байта) используйте udp.Payload32[i].
Во-вторых, я не уверен, что i можно указывать как диапазон. Цитата из доков:

The packet*[i], tcp.Payload*[i] and udp.Payload*[i] fields take an index parameter (i). The following indexing schemes are supported:

  • Undecorated integer (e.g., packet32[10]): evaluates to the i th word from the start of the packet/payload. This is essentially C-style array indexing;
  • Negative decorated integer (e.g., packet32[-10]): evaluates to the i th word from the end of the packet/payload. Here the index (-1) is the first full word that fits; and
  • Byte decorated (negative) integer (e.g., packet32[10b] or packet32[-10b]): evaluated to the word offset by i bytes from the start (or end) of the packet/payload.
2024-10-10T14:45:06.341Z
bolvan

Рабочий пример из winws для детекта входящего HTTP redirect

// HTTP/1.? 30(2|7)

tcp.PayloadLength>=12 and tcp.Payload32[0]==0x48545450 and tcp.Payload16[2]==0x2F31 and tcp.Payload[6]==0x2E and tcp.Payload16[4]==0x2033 and tcp.Payload[10]==0x30 and (tcp.Payload[11]==0x32 or tcp.Payload[11]==0x37)

байты идут в network byte order. То есть big endian.

2024-10-10T16:03:31.104Z
gepron1x(Георгий)

Написал фильтр на основе wf-save, со всеми подсетями дискорда.
Да простит бог меня за это…

rules.txt

!impostor and !loopback and
((outbound and (((tcp.DstPort == 80) or (tcp.DstPort == 443)) or ((udp.DstPort == 443) or
(udp.DstPort >= 50000 and udp.DstPort <= 65535 and (
(ip.DstAddr >= 66.22.196.0 and ip.DstAddr <= 66.22.199.255) or
(ip.DstAddr >= 66.22.200.0 and ip.DstAddr <= 66.22.207.255) or
(ip.DstAddr >= 66.22.208.0 and ip.DstAddr <= 66.22.223.255) or
(ip.DstAddr >= 66.22.224.0 and ip.DstAddr <= 66.22.227.255) or
(ip.DstAddr >= 66.22.230.0 and ip.DstAddr <= 66.22.231.255) or
(ip.DstAddr >= 66.22.232.0 and ip.DstAddr <= 66.22.239.255) or
(ip.DstAddr >= 66.22.240.0 and ip.DstAddr <= 66.22.247.255) or
(ip.DstAddr >= 66.22.248.0 and ip.DstAddr <= 66.22.248.255))
))) and
(((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or ((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))))
or
(inbound and tcp and (tcp.Ack and tcp.Syn or tcp.Rst or tcp.Fin) and ((tcp.SrcPort == 80) or (tcp.SrcPort == 443)) and (((ip.SrcAddr < 127.0.0.1 or ip.SrcAddr > 127.255.255.255) and (ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255) and (ip.SrcAddr < 192.168.0.0 or ip.SrcAddr > 192.168.255.255) and (ip.SrcAddr < 172.16.0.0 or ip.SrcAddr > 172.31.255.255) and (ip.SrcAddr < 169.254.0.0 or ip.SrcAddr > 169.254.255.255)) or ((ipv6.SrcAddr > ::1) and (ipv6.SrcAddr < 2001::0 or ipv6.SrcAddr >= 2001:1::0) and (ipv6.SrcAddr < fc00::0 or ipv6.SrcAddr >= fe00::0) and (ipv6.SrcAddr < fe80::0 or ipv6.SrcAddr >= fec0::0) and (ipv6.SrcAddr < ff00::0 or ipv6.SrcAddr >= ffff::0)))))

2024-10-10T20:14:09.038Z
Jabronskiy

Проверил по-быстрому с этим конфигом

cmd

start “zapret: discord” /min “%~dp0winws.exe” ^
–wf-raw=@testwf.txt ^
–filter-tcp=443 --hostlist=“%~dp0list-youtube.txt” --hostlist=“%~dp0list-blacklist.txt” --hostlist=“%~dp0list-discord.txt” --dpi-desync=split --dpi-desync-split-pos=1 --dpi-desync-fooling=badseq --dpi-desync-repeats=7 --new ^
–filter-udp=50000-65535 --dpi-desync=fake --dpi-desync-any-protocol --dpi-desync-cutoff=d4 --dpi-desync-repeats=6

Коннектит ко всем серверам, кроме Бразилии, Гонконга, Индии, иногда Японии и юга США, Сингапура и Австралии. Но! Один раз даже к Роттердаму не подключился, но перезаход помог. Возможно зависит от настроек, но нужны ли эти сервера?

2024-10-10T21:06:12.119Z
gepron1x(Георгий)

Полагаю, что тот список подсетей включал только российские сервера. Сделал фильтр по заголовку пакета, попробуй его:

Спойлер

!impostor and !loopback and
((outbound and (((tcp.DstPort == 80) or (tcp.DstPort == 443)) or ((udp.DstPort == 443) or
(udp.DstPort >= 50000 and udp.DstPort <= 65535 and udp.PayloadLength == 74 and udp.Payload32[0] == 0x00010046
))) and
(((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or ((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))))
or
(inbound and tcp and (tcp.Ack and tcp.Syn or tcp.Rst or tcp.Fin) and ((tcp.SrcPort == 80) or (tcp.SrcPort == 443)) and (((ip.SrcAddr < 127.0.0.1 or ip.SrcAddr > 127.255.255.255) and (ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255) and (ip.SrcAddr < 192.168.0.0 or ip.SrcAddr > 192.168.255.255) and (ip.SrcAddr < 172.16.0.0 or ip.SrcAddr > 172.31.255.255) and (ip.SrcAddr < 169.254.0.0 or ip.SrcAddr > 169.254.255.255)) or ((ipv6.SrcAddr > ::1) and (ipv6.SrcAddr < 2001::0 or ipv6.SrcAddr >= 2001:1::0) and (ipv6.SrcAddr < fc00::0 or ipv6.SrcAddr >= fe00::0) and (ipv6.SrcAddr < fe80::0 or ipv6.SrcAddr >= fec0::0) and (ipv6.SrcAddr < ff00::0 or ipv6.SrcAddr >= ffff::0)))))

2024-10-10T21:21:30.224Z
gepron1x(Георгий)

Он, конечно потенциально может сработать на пакеты с пейлодом 74 байта, заголовок которых начинается на 0x00010046, но я думаю что это маловероятно.
https://fossies.org/linux/misc/nDPI-4.10.tar.gz/nDPI-4.10/src/lib/protocols/discord.c?M=26
Нашел такой же метод в этом коде.

UPD Закинул все мои пресеты на форк github GitHub - gepron1x/zapret-win-bundle: zapret and blockcheck binary bundle for windows (discord presets)
preset_discord и preset_full соответственно :slight_smile:

2024-10-10T21:24:32.466Z
Jabronskiy

Как я понял это список подсетей серверов от провайдера i3D.net B.V, но есть еще от Гугла(были еще от Psychz Networks, но, кажись, от них отказались). Собственно поэтому на ту же Японию, юг США и Роттердам коннектит с переменным успехом, так как они поделены между провайдерами и тут как повезёт куда тебя кинет. Финский сервак, к которому походу только при автоматической подборке сервера кидает, например, вообще весь от Гугла.

Я может попозже попробую дополнить фильтр остальными айпишниками, но пока второй вариант работает.

2024-10-11T10:52:45.238Z
Jabronskiy

Ну вот что-то такое вышло. В этих диапазонах явно не только дискорд, но работают все сервера из списка за исключением Африки и, возможно, юга США, которые с переменным успехом работают. Финский тоже работает, на треть работает Франкфуртовский, но к нему вряд ли коннектить будет, так как к финскому пинг меньше(причем даже до Московского больше).
Но честно сказать не знаю кому нужны какие-то сервера кроме Московского, Роттердамского и финского/Стокгольмского. Наверное можно объединить с фильтром по заголовку и так меньше всего флуда будет?

filter.txt

!impostor and !loopback and
((outbound and (((tcp.DstPort == 80) or (tcp.DstPort == 443)) or ((udp.DstPort == 443) or
(udp.DstPort >= 50000 and udp.DstPort <= 65535 and (
(ip.DstAddr >= 66.22.196.0 and ip.DstAddr <= 66.22.199.255) or
(ip.DstAddr >= 66.22.200.0 and ip.DstAddr <= 66.22.207.255) or
(ip.DstAddr >= 66.22.208.0 and ip.DstAddr <= 66.22.223.255) or
(ip.DstAddr >= 66.22.224.0 and ip.DstAddr <= 66.22.227.255) or
(ip.DstAddr >= 66.22.230.0 and ip.DstAddr <= 66.22.231.255) or
(ip.DstAddr >= 66.22.232.0 and ip.DstAddr <= 66.22.239.255) or
(ip.DstAddr >= 66.22.240.0 and ip.DstAddr <= 66.22.247.255) or
(ip.DstAddr >= 66.22.248.0 and ip.DstAddr <= 66.22.248.255) or
(ip.DstAddr >= 35.215.192.0 and ip.DstAddr <= 35.215.255.255) or
(ip.DstAddr >= 35.215.128.0 and ip.DstAddr <= 35.215.191.255) or
(ip.DstAddr >= 35.207.192.0 and ip.DstAddr <= 35.207.255.255) or
(ip.DstAddr >= 35.213.0.0 and ip.DstAddr <= 35.213.127.255) or
(ip.DstAddr >= 35.214.128.0 and ip.DstAddr <= 35.214.255.255) or
(ip.DstAddr >= 34.0.240.0 and ip.DstAddr <= 34.0.255.255) or
(ip.DstAddr >= 35.213.128.0 and ip.DstAddr <= 35.213.191.255) or
(ip.DstAddr >= 35.213.192.0 and ip.DstAddr <= 35.213.255.255) or
(ip.DstAddr >= 35.217.0.0 and ip.DstAddr <= 35.217.63.255))
))) and
(((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or ((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))))
or
(inbound and tcp and (tcp.Ack and tcp.Syn or tcp.Rst or tcp.Fin) and ((tcp.SrcPort == 80) or (tcp.SrcPort == 443)) and (((ip.SrcAddr < 127.0.0.1 or ip.SrcAddr > 127.255.255.255) and (ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255) and (ip.SrcAddr < 192.168.0.0 or ip.SrcAddr > 192.168.255.255) and (ip.SrcAddr < 172.16.0.0 or ip.SrcAddr > 172.31.255.255) and (ip.SrcAddr < 169.254.0.0 or ip.SrcAddr > 169.254.255.255)) or ((ipv6.SrcAddr > ::1) and (ipv6.SrcAddr < 2001::0 or ipv6.SrcAddr >= 2001:1::0) and (ipv6.SrcAddr < fc00::0 or ipv6.SrcAddr >= fe00::0) and (ipv6.SrcAddr < fe80::0 or ipv6.SrcAddr >= fec0::0) and (ipv6.SrcAddr < ff00::0 or ipv6.SrcAddr >= ffff::0)))))

Инфу брал отсюда, отсюда и тут еще сверялся.

2024-10-12T10:52:42.305Z
bolvan

Прекрасно, очень хорошо сделано. Для этого и задумывались --wf-save и --wf-raw.
Жаль, что нет ipset-ов в windivert.

Но еще стоит помнить, что базовый фильтр немного изменяется при включении autohostlist режима.
Если вдруг понадобится автолист, там нужен перехват RST и http redirect.

2024-10-12T11:00:55.195Z
gepron1x(Георгий)

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

2024-10-12T15:28:29.259Z
Hint

Что нужно сделать с этим первым пакетом, чтобы его пропустило? Написал клиентскую dll для Discord для перенаправления tcp трафика на socks5/https (просто кидаю dll в папку с программой и всё работает за исключением звонков), а с проксированием udp стало лень возиться (половину кода написал, но потом плюнул и решил для звонков использовать VPN). Если можно как-то отредактировать какой-то пакет, чтобы дальше всё работало, то сделать это легко на уровне процесса.

2024-10-12T18:15:12.124Z
Hint

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

2024-10-12T19:12:03.422Z
Jabronskiy

Но еще стоит помнить, что базовый фильтр немного изменяется при включении autohostlist режима. Если вдруг понадобится автолист, там нужен перехват RST и http redirect.

Что-то подобное в inbound? И это получается отдельный фильтр, который надо использовать только если hostlist-auto включен, а в ином случае лучше без него?

inbound

(inbound and tcp and ((tcp.Ack and tcp.Syn or tcp.Rst or tcp.Fin) or (tcp.PayloadLength>=12 and tcp.Payload32[0]==0x48545450 and tcp.Payload16[2]==0x2F31 and tcp.Payload[6]==0x2E and tcp.Payload16[4]==0x2033 and tcp.Payload[10]==0x30 and (tcp.Payload[11]==0x32 or tcp.Payload[11]==0x37))) and ((tcp.SrcPort == 443)) and (((ip.SrcAddr < 127.0.0.1 or ip.SrcAddr > 127.255.255.255) and (ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255) and (ip.SrcAddr < 192.168.0.0 or ip.SrcAddr > 192.168.255.255) and (ip.SrcAddr < 172.16.0.0 or ip.SrcAddr > 172.31.255.255) and (ip.SrcAddr < 169.254.0.0 or ip.SrcAddr > 169.254.255.255)) or ((ipv6.SrcAddr > ::1) and (ipv6.SrcAddr < 2001::0 or ipv6.SrcAddr >= 2001:1::0) and (ipv6.SrcAddr < fc00::0 or ipv6.SrcAddr >= fe00::0) and (ipv6.SrcAddr < fe80::0 or ipv6.SrcAddr >= fec0::0) and (ipv6.SrcAddr < ff00::0 or ipv6.SrcAddr >= ffff::0)))))

2024-10-13T15:47:54.821Z
bolvan

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

2024-10-13T16:11:26.794Z
bolvan

Не будет, если cutoff сделать. у windivert нет conntrack. Там нельзя задать номер пакета в “соединении”.
Потому придется в user-mode в winws. У pktws есть свой коннтрак.
windivert фильтр отсеивает левые IP прямо в ядре. Это замена iptables фильтрам.

2024-10-13T16:14:33.926Z