Привет. Разбираюсь с блокировкой дискорда. Почитал форум, решение есть, но как я понял есть проблема - дурение на всех высоких портах 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
Прошу вашего экспертного мнения. Думаю, нужен фильтр по заголовку, ибо на длину полагаться некрасиво.
я бы рекомендовал сохранить стандартный фильтр через --wf-save
там есть ряд важных ограничителей
и над ним уже издеваться
а дальше стоит вписать ограничитель на подсети дисккорда. они проскакивали в обсуждениях дискорда удп на гитхабе
подсети стоит обьединить, чтобы не писать кучу /24
я не исследовал блокировку дискорда
вывод о стуне был сделан на базе постов в обсуждениях. может еще что-то есть
в течение 2 недель собираюсь выкатить юзер моде реализацию ипсетов
но когда подсетей мало лучше использовать wf-raw
У пакетов общие 5 байт в начале payload и 2 байта в конце.
Можно ли указать это для нахождения нужного пакета?
Первые 4-5 байт данных не изменяются.
–wf-raw=“udp.Payload[0:3]==0x00010046”
При указании ничего не работает…
Во-первых, 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.
Рабочий пример из 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.
Написал фильтр на основе 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)))))
Коннектит ко всем серверам, кроме Бразилии, Гонконга, Индии, иногда Японии и юга США, Сингапура и Австралии. Но! Один раз даже к Роттердаму не подключился, но перезаход помог. Возможно зависит от настроек, но нужны ли эти сервера?
Полагаю, что тот список подсетей включал только российские сервера. Сделал фильтр по заголовку пакета, попробуй его:
Спойлер
!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)))))
Как я понял это список подсетей серверов от провайдера i3D.net B.V, но есть еще от Гугла(были еще от Psychz Networks, но, кажись, от них отказались). Собственно поэтому на ту же Японию, юг США и Роттердам коннектит с переменным успехом, так как они поделены между провайдерами и тут как повезёт куда тебя кинет. Финский сервак, к которому походу только при автоматической подборке сервера кидает, например, вообще весь от Гугла.
Я может попозже попробую дополнить фильтр остальными айпишниками, но пока второй вариант работает.
Ну вот что-то такое вышло. В этих диапазонах явно не только дискорд, но работают все сервера из списка за исключением Африки и, возможно, юга США, которые с переменным успехом работают. Финский тоже работает, на треть работает Франкфуртовский, но к нему вряд ли коннектить будет, так как к финскому пинг меньше(причем даже до Московского больше).
Но честно сказать не знаю кому нужны какие-то сервера кроме Московского, Роттердамского и финского/Стокгольмского. Наверное можно объединить с фильтром по заголовку и так меньше всего флуда будет?
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)))))
Прекрасно, очень хорошо сделано. Для этого и задумывались --wf-save и --wf-raw.
Жаль, что нет ipset-ов в windivert.
Но еще стоит помнить, что базовый фильтр немного изменяется при включении autohostlist режима.
Если вдруг понадобится автолист, там нужен перехват RST и http redirect.
Решение рабочее, но, боюсь, флуд в сети все равно будет во время разговоров и трансляций в дс. Обойти блокировку достаточно в момент подключения, блочат именно тот первый пакет с длиной 74, дальше войс нормально работает
Что нужно сделать с этим первым пакетом, чтобы его пропустило? Написал клиентскую dll для Discord для перенаправления tcp трафика на socks5/https (просто кидаю dll в папку с программой и всё работает за исключением звонков), а с проксированием udp стало лень возиться (половину кода написал, но потом плюнул и решил для звонков использовать VPN). Если можно как-то отредактировать какой-то пакет, чтобы дальше всё работало, то сделать это легко на уровне процесса.
Но еще стоит помнить, что базовый фильтр немного изменяется при включении 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)))))
Он не мешает особо, только раздувает код и вносит какой-то оверхед на процессинг фильтра в windivert.sys. Насколько он значителен судить не берусь, но в коде windivert есть начальный парсинг. На каждый пакет он текст не мучает. Уже все переведено в токенный псевдо-код.
Не будет, если cutoff сделать. у windivert нет conntrack. Там нельзя задать номер пакета в “соединении”.
Потому придется в user-mode в winws. У pktws есть свой коннтрак.
windivert фильтр отсеивает левые IP прямо в ядре. Это замена iptables фильтрам.