Как вообще появился этот проект?
После начала активной блокировки Socks5 прокси возник вопрос - почему остальной Socks5 траффик работает и не проходит только при обращении к Telegram?
Тогда я начал исследовать этот вопрос и наткнулся на то, что в Socks5 IP и порт к которому пойдёт соединение передаются в сыром виде, да как и весь последующий трафик.
Пошли эксперименты с подменой байтов в трафике и буквально первое что дало результат - подмена версии Socks с 5 на 6, и трафик пошёл.
Это решение живет даже на момент написания этого текста (а это около 6 месяцев с начала блокировки Telegram+Socks и написания простой программы)
Но я не назвал бы такое решение "надежным", поэтому я мельком накидал это решение.
-
Загрузите репозиторий на ваш сервер:
git clone https://github.com/0mnr0/Socks-5E.git && cd Socks-5E
-
Если на вашем сервере нету docker compose - установите его
-
Сгенерируйте данные для авторизации:
chmod +x genAuth.sh && ./genAuth.sh(в противном случае сервер будет работать без авторизации) -
Выполните
docker compose build && docker compose up -
Готово, Socks-5E поднят на порту
48980, подключайтесь через специальный скрипт
- Шифрует данные ключом с авто-ротацией
- Добавляет случайный padding
+-------------------+ +-------------------+ +-------------------+
| Клиент | | SOCKS5-сервер | | Цель назначения |
+-------------------+ +-------------------+ +-------------------+
| | |
|--[1] Greeting -----------------------> | |
| \x05, NMETHODS, METHODS[] | |
| | |
|<--[2] Method Selection ---------------- | |
| \x05, METHOD | |
| | |
|--[3a] Auth Request (если METHOD=0x02)-> | |
|<--[3b] Auth OK ------------------------ | |
| | |
|--[4] CONNECT -------------------------> | |
| VER=5, CMD=1, ATYP, ADDR, PORT | |
| | ------- [5] TCP Connect -------> |
| | |
|<--[6] CONNECT Response ---------------- | |
| VER=5, REP=0x00, BND.ADDR, PORT | |
| | |
| <======================== [7] Данные (Plaintext) ===========================> |
+------------------+ SOCKS5 +------------------+ ECDH+ChaCha20 +------------------+ TCP +----------+
| App | Plain | Local Client | Encrypted | Remote Relay | Plain | Target |
| (Telegram, etc.) | text | (main.py) | | (server.py) | | |
+------------------+ +------------------+ +------------------+ +----------+
App Local Client Remote Relay Target
| | | |
|--[1] Greeting --------> | | |
| \x05, NMETHODS, | | |
| METHODS[] | | |
| | | |
|<--[2] Method Choice --- | | |
| \x05, METHOD | | |
| | | |
|--[3a] Auth (0x02) ----> | | |
|<--[3b] \x01\x00 ------- | creds сохранены | |
| | | |
|--[4] CONNECT ---------> | | |
| VER=5, CMD=1, | connect_request | |
| ATYP, ADDR, PORT | сохранён | |
| | | |
| (App ждёт ответа) | | |
| | | |
| |--[5a] NEW_SESSION -----> | |
| | \x01 + X25519 pub_key | |
| | --- ИЛИ --- | |
| |--[5b] RESUME ----------> | |
| | \x02 + session_id | |
| | + nonce + Enc(proof) | |
| | | |
| |<--[6a] server pub_key -- | (новая сессия) |
| |<--[6b] Enc(session_id) - | |
| | | |
| | Derived key: | |
| | HKDF(X25519 shared) | |
| | | |
| |--[7] Enc(Greeting) ----> | |
| |<--[8] Enc(Method) ------ | |
| | | |
| |--[9] Enc(Auth) --------> | (если creds) |
| |<--[10] Enc(Auth OK) ---- | |
| | | |
| |--[11] Enc(CONNECT) ----> | |
| | |--[12] TCP Connect -> |
| |<--[13] Enc(CONNECT Resp) | |
| <--[14] CONNECT Resp --- | | |
| VER=5, REP=0x00 | | |
|<== Plaintext ===========>|<== Enc(data)+padding ====>|<== Plaintext ======>|
| reader.read() | nonce+len(ct)+ct | |
| 16384 bytes max | + rand 0..1200 bytes | |
- Пошаманить над таймингами
- Поправить статичный байт, указывающий на тип сессии
- Перейти на шифрование Elligator2, т.к. текущий палится при статистичеком анализе
- Переписать на C#
- Придумать/стырить защиту от зондирования