udpobfs
http://www.git.cypherpunks.ru/?p=udpobfs.git;a=blob;f=README
Постоянно стали возникать новости о блокировках VPN-ов в РФ. Хотя у меня
только один раз возникала она (
55eac8d1c25b49bafcc4ed1ece2f4f7763e0230f)
на несколько часов.
Многие предлагают бороться обфускацией трафика, маскированием его под
что-то другое. Я на всё это смотрю проще, со времён разработки GoVPN:
если сеть не позволяет случайные данные (сплошной рандом) отправлять, то
значит это whitelist блокировка: разрешено отправлять только явно
заданные вещи. По этой сети нельзя произвольными данными обмениваться.
Извращаться и страдать хернёй с попытками то так, то сяк, то таким или
другим образом запрятать данные, а то и вообще со стеганографией -- я не
собираюсь. Нет сети обмена произвольными данными -- значит нет. Мне не
интересно играть в игры, прятки и притворяться по всякому. Это же всё
равно продолжение игры по правилам не совсем дружных с головой людей,
и потакание их тупостям. А с их точки зрения они будут продолжать видеть
то, что люди, не смотря на whitelisting, всё равно продолжают
использовать эти каналы связи.
Blacklist блокировки уже давно стали нормой абсолютно везде в мире,
задолго до РФ -- да и в целом то я не сталкивался с ними на практике
особо.
Так вот для меня лакмусовой бумажкой является возможность отправки чисто
шума, не содержащего ни структуры, ни заголовков явных каких-то, ни чего
то подобного. Это у меня умел GoVPN, но не охота снова смотреть на него,
ибо это мой первый проект на Go, где по идее надо бы вообще всё
переписать с нуля. Сам протокол то там нормальный, а вот код так себе.
Да и я уже говорил, что если бы WireGuard появился раньше, то я бы и не
начинал писать GoVPN, ведь всякие DPI-resistant фишки я уже добавлял
после того как мне просто нужен был какой-то простой препростой VPN, а
не IPsec или OpenVPN.
Нельзя ли просто сделать какой-нибудь простой UDP прокси, который бы
симметрично как-то шифровал пакетики, исключительно для того, чтобы они
выглядели как сплошной шум? Проще написать, чем читать документацию
какого-нибудь shadowsocks, obfsproxy и подобных проектов, где я так и не
смог за пару минут найти как именно они работают и могут ли просто "шум"
слать. Всякие имитации HTTPS/whatever мне не интересны.
Вот и написал его. (Пока?) Даже handshake нету. Предполагаю что в любом
случае уж OpenSSH то будет работать априори (а если нет, то можно
выдернуть Ethernet -- всё равно это не работающая сеть). А значит по
нему (аутентифицированному, с PFS) можно просто отправлять ключи для
udpobfs какими-нибудь скриптами. Вариантов масса. Почему не делать VPN
прямо поверх OpenSSH, который вполне себе из коробки умеет даже TUN
интерфейс создавать? Плохая производительность, как минимум потому что
это поверх TCP будет.
Каждая сторона имеет 64-бит счётчики, являющиеся nonce-ом. В начале
пакета добавляются только 24-бит счётчика, остальная часть в памяти на
каждой стороне. Если значение счётчика пакета пришло меньше чем было
прежде, то значит было переполнение и в памяти увеличивается оставшаяся
часть. Аналогично как это с ESN в IPsec ESP делается. Над полным 64-бит
счётчиком и шифротекстом (ChaCha20) вычисляется Poly1305 (ключ, как это
принято в ChaCha20-Poly1305, берётся из первых 256-бит выхлопа ChaCha20)
вычисляется MAC, но только 40-бит от него используется. 24-бит часть
счётчика и 40-бит MAC добавляются перед шифротекстом, всего восемь байт
overhead. И эти 8 байт шифруются Blowfish-ем. Почему Blowfish? Потому
что у него 64-бит блок, а почти у всех остальных шифров (хоть сколько то
серьёзных) -- 128-бит. "Заголовок" 8 байт. UDP пакет может быть пустым,
а значит для 128-бит шифров понадобится дополнение, с которым не хочется
возиться. Ключи для всего этого (пара ChaCha20+Blowfish для каждой
стороны) вырабатываются из выхлопа SHA3 SHAKE128, на входе которого
общий ключ приходящий из вне.
Демон берёт ключи из stdin -- можно прямо на лету их подавать всё новые
и новые. Конечно же будет какой-то промежуток времени когда ключи будут
разсинхронизованы и поэтому часть трафика потеряется, но да и фиг с
этим. Это всё равно заточено под обфускацию VPN, внутри которого всякие
TCP не сильно пострадают.
Сейчас вспомнил что в коде нет обнуления буферов с nonce-ами после
обновления ключей -- надо будет поправить. Да и всё же хоть какой-то
handshake, пускай даже без DH, но добавить, ибо сейчас при любом выходе
демона ему по хорошему стоит менять ключи. Откладываю это, ибо боюсь что
это вырастит в полноценный транспортный протокол, чего не хотелось бы.