← Назад в базу знаний

Как Discord детектирует прокси по TLS-рукопожатию и что это значит для мультиаккаунтинга

Как Discord детектирует прокси по TLS-рукопожатию и что это значит для мультиаккаунтинга

Что вообще видит Discord

Discord — не просто чат. Это инфраструктура на Cloudflare и собственном edge, где каждый запрос проходит через кучу слоёв: TLS fingerprint, HTTP/2 fingerprint, поведенческие метрики, IP-репутация. Мультиаккаунтинг ломается не на одном уровне, а на стыке нескольких.

Начнём с базы. Когда клиент открывает TCP-соединение к `gateway.discord.gg:443`, первое, что видит сервер — ClientHello. Это ещё до всякой авторизации, до токена, до HTTP. В ClientHello лежит JA3-отпечаток. Discord его читает.

JA3 — это MD5 от конкатенации: версия TLS, список cipher suites, список extensions, список elliptic curves, формат point compression. Всё в hex, через запятую. Получается строка вроде `771,4865-4866-4867-49195-49199,0-23-65281-10-11-35-16-5-13,29-23-24,0`. MD5 от неё — и есть отпечаток.

Официальный desktop-клиент Discord (Electron + Chromium) имеет конкретный JA3. Мобильный — другой. Веб-версия в Chrome — третий. Бот на discord.py — четвёртый, потому что там aiohttp. И если ты сидишь через `curl` или `python-requests`, JA3 будет радикально отличаться от всего, что Discord ожидает увидеть.

Почему residential-прокси не спасают

Классическая схема мультиаккаунтинга: купил residential-прокси, повесил на каждый аккаунт свой IP, радуешься. Работало годами. Сейчас — нет.

Причина в том, что residential-прокси даёт тебе чистый IP, но не даёт тебе чистый TLS. Прокси-сервер терминирует TCP, а дальше пересылает байты как есть. ClientHello от твоего `python-requests` доходит до Discord без изменений. И Discord видит: IP из жилого сектора Comcast в Чикаго, а JA3 — от Python 3.11 с OpenSSL 3.0. Это несоответствие.

Хуже того. Squid, 3proxy, обычный SOCKS5 — все они работают на уровне TCP. Они не трогают TLS. Значит, любой fingerprint, который клиент отправил, долетает до целевого сервера в первозданном виде. Никакой маскировки.

Вот как выглядит типичный JA3 от `requests`:

```python

import requests

import hashlib

requests использует urllib3 + OpenSSL, JA3 будет стабильным

r = requests.get("https://discord.com/api/v10/gateway")

print(r.status_code)

Посмотреть свой JA3 можно через внешний сервис

print(requests.get("https://tls.peet.ws/api/all").json()["tls"]["ja3_hash"])

```

На выходе получишь что-то вроде `3b5074b1b5d032e5620f69f9f700ff0e`. Это отпечаток Python. Discord знает этот хеш. Он в чёрном списке.

HTTP/2 fingerprint — второй слой

Даже если ты подделал JA3, есть ещё HTTP/2 fingerprint. Он строится из:

- SETTINGS frame (какие параметры и в каком порядке)

- WINDOW_UPDATE

- PRIORITY frames

- порядка pseudo-headers (`:method`, `:authority`, `:path`, `:scheme`)

- HEADERS frame padding

Chrome отправляет `:method :authority :scheme :path`. Firefox — `:method :path :authority :scheme`. Go net/http — вообще другой порядок. И это видно на уровне фреймов, ещё до расшифровки.

Discord (как и Cloudflare) собирает эти данные в Akamai-style fingerprint. Комбинация JA3 + HTTP/2 fingerprint + IP ASN даёт очень точную картину того, кто стучится.

Подделать HTTP/2 fingerprint сложнее, чем JA3. Нужен либо кастомный TLS-стек, либо библиотека вроде `curl-impersonate`, которая эмулирует Chrome на уровне байтов.

Что реально работает

`curl-impersonate` — патченный curl, который воспроизводит TLS и HTTP/2 handshake Chrome или Firefox. Не просто заголовки, а именно байтовый поток.

```bash

curl_chrome116 -X GET "https://discord.com/api/v10/gateway" \

-H "Authorization: Bot YOUR_TOKEN" \

-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \

--proxy socks5://user:pass@residential-proxy:1080

```

Флаг `curl_chrome116` — это wrapper-скрипт, который подставляет нужные cipher suites, extensions, порядок HTTP/2 фреймов. JA3 будет совпадать с Chrome 116. Если прокси residential и ASN чистый — Discord видит обычного пользователя Chrome.

Альтернатива — `tls-client` (Python-обёртка над Go-библиотекой). Она умеет эмулировать Chrome, Firefox, Safari, iOS.

```python

from tls_client import Session

session = Session(client_identifier="chrome_120")

session.proxies = {"https": "http://user:pass@residential:8080"}

headers = {

"Authorization": "Bot YOUR_TOKEN",

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"

}

r = session.get("https://discord.com/api/v10/users/@me", headers=headers)

print(r.status_code, r.json())

```

`client_identifier="chrome_120"` даёт JA3, идентичный реальному Chrome 120. Плюс HTTP/2 fingerprint совпадает.

IPv6 меняет расклад

Residential IPv4-прокси дорогие и медленные. IPv6-подход другой: у тебя есть /64 или /48 префикс, и ты можешь назначить каждому аккаунту уникальный адрес. Не NAT, не shared IP — реальный отдельный адрес.

Проблема в том, что многие сайты (и Discord в том числе) относятся к IPv6 настороженно. Причины:

- Многие residential-провайдеры ещё не раздают IPv6 массово. Значит, IPv6-трафик часто идёт из дата-центров.

- GeoIP для IPv6 часто кривой. Адрес может числиться в Нидерландах, а реально быть в Румынии.

- Репутация IPv6-подсетей слабая — спамеры первыми освоили большие префиксы.

Discord проверяет ASN и rDNS. Если твой IPv6 принадлежит хостингу (Hetzner, OVH, DigitalOcean) — флаг сразу. Нужны IPv6 от residential-провайдеров или мобильных операторов.

Прокси-сервис на базе IPv6 (вроде того, что делает lexic.ml) даёт именно это: большие пулы IPv6 из residential ASN, где каждый запрос может уйти с уникального адреса. Комбинация «чистый JA3 + residential IPv6 + правильный HTTP/2» проходит большинство проверок.

Поведенческий слой

Технические метрики — половина дела. Вторая половина — то, как аккаунты себя ведут.

Discord смотрит на:

- Время между регистрацией и первым сообщением. Если 3 секунды — бот.

- Паттерн активности. 24/7 онлайн без сна — подозрительно.

- Синхронность. Десять аккаунтов отправляют сообщение в одну гильдию в пределах 200 мс — ферма.

- Одинаковые аватарки, bio, никнеймы с инкрементом (`user1`, `user2`).

- IP-переходы. Аккаунт логинился с IPv4 в Германии, потом с IPv6 в Сингапуре через 5 минут — угон или прокси.

Технически идеальный JA3 не спасёт, если десять аккаунтов ведут себя как клоны. Discord банит по кластеру: нашёл один — нашёл все.

Кейс: ферма на 50 аккаунтов через SOCKS5

Пример: сервер на Ubuntu 22.04, 50 Discord-аккаунтов, каждый через свой SOCKS5-прокси от недорогого провайдера. Клиент — `discord.py` self-bot (нарушение ToS, но для понимания механики полезно).

Через 6 часов после старта — 43 аккаунта забанены. Осталось 7. Логи показали: все 43 имели одинаковый JA3 (`3b5074b1b5d032e5620f69f9f700ff0e` — Python) и одинаковый HTTP/2 fingerprint от aiohttp. IP были разные, ASN разные, но fingerprint один. Discord сгруппировал по отпечатку и вычистил пачкой.

Причина: SOCKS5 не трогает TLS. aiohttp отправляет свой ClientHello. Все 50 аккаунтов выглядят как один клиент с 50 IP.

Решение: заменить транспорт на `curl-impersonate` или `tls-client` с эмуляцией Chrome, оставить residential-прокси, добавить рандомизацию таймингов. После переделки — 4 бана из 50 за неделю, и те по поведению, не по fingerprint.

Кейс: IPv6 /64 и GeoIP-несоответствие

Другой пример: /64 префикс от европейского хостинга, 200 адресов, по одному на аккаунт. JA3 подделан через `tls-client`, всё чисто. Но баны пошли на второй день.

Причина оказалась в GeoIP. Discord резолвит IPv6 через MaxMind. Для этого /64 префикса база выдавала локацию «Frankfurt, DE». А аккаунты были зарегистрированы с европейских residential IPv4 (Польша, Чехия). Резкая смена страны при каждом логине — триггер.

Плюс rDNS: у хостинговых IPv6 он вида `static.123.45.67.89.clients.your-server.de`. Discord это видит и помечает как дата-центр.

Решение: IPv6 от residential ASN с корректным GeoIP и без хостингового rDNS. Либо вообще отказаться от IPv6 для Discord и остаться на residential IPv4, но с правильным TLS.

Кейс: синхронный флуд и кластерный бан

Третий пример. 30 аккаунтов, все с правильным JA3 Chrome, residential IPv4, разные ASN. Технически — идеально. Забанили все 30 за 12 минут.

Причина: скрипт отправлял сообщение в общий канал с интервалом 50 мс между аккаунтами. Discord видит: 30 разных «пользователей» с разных IP отправляют однотипные сообщения в одну гильдию в пределах 1.5 секунды. Это невозможно для живых людей. Кластерный бан.

Решение: рандомизация задержек (от 30 секунд до 15 минут), разные тексты сообщений, разные каналы, разные гильдии. Плюс прогрев аккаунтов — регистрация, пауза сутки, первые действия через день. Тогда 30 аккаунтов живут месяцами.

Что проверять перед запуском

Перед тем как поднимать ферму, прогони чек-лист:

- JA3 совпадает с реальным браузером. Проверь на `tls.peet.ws/api/all`.

- HTTP/2 fingerprint тоже совпадает. Там же смотри поле `http2`.

- IP не из дата-центра. Проверь ASN через `ipinfo.io` или `bgp.he.net`.

- GeoIP IP совпадает со страной аккаунта.

- rDNS не палит хостинг.

- Тайминги между действиями рандомизированы, минимум 30 секунд.

- Аккаунты прогреты, не свежесозданные.

- Поведение не синхронно — разные каналы, разные тексты.

Без любого из этих пунктов — бан. Discord не смотрит на один сигнал, он складывает всё в кучу.

Итог

Детект прокси у Discord — это не одна проверка, а конвейер. JA3, HTTP/2 fingerprint, IP-репутация, GeoIP, поведение. Ломается вся цепочка на самом слабом звене. Residential IP без маскировки TLS — бесполезен. Идеальный TLS с дата-центровым IP — тоже. Правильный TLS + residential IP + человеческое поведение — работает.

Главное правило: каждый уровень должен соответствовать легенде. Если аккаунт «обычный пользователь из Варшавы на Chrome», то и TLS, и IP, и тайминги должны это подтверждать. Любое несоответствие — зацепка.

✔️Купить прокси