@node Безопасный SSH @section Безопасный SSH Данная статья -- попытка дополнить уже существующую относительно грамотную @url{https://stribika.github.io/2015/01/04/secure-secure-shell.html, Secure Secure Shell }. Но только относительно грамотную: некоторые вещи не являются правдой и поэтому часть рекомендаций не годна. @strong{Несогласия} Сразу же приведу список того с чем не согласен, для тех кто знаком со статьёй или её сутью: @itemize @item Мало затронута тема аутентификации сервера @item DES -- сломан, но не 3DES. Если уровень безопасности в 112 бит достаточен, то его использование приемлемо (если закрыть глаза на низкую производительность) @item RC4/Arcfour имеет особенности из-за которых некоторые реализации действительно можно считать сломанными. При **правильном** использовании Arcfour обладает хорошей силой и производительностью. OpenSSH реализовал этот алгоритм правильно: отбрасывается первые 1536 байт его выхода, разные не связанные между собой ключи. При своей производительности в контексте OpenSSH можно рассматривать к применению @item С какой стати размер блока шифра должен быть хотя бы 128 бит? Это действительно позволяет реже перегенерировать ключи шифрования, но кроме этой особенности в этом размере нет ничего страшного. Кроме того, автор выкинул CAST, но оставил Blowfish, хотя у него размер блока тоже в 64 бит @item Конечно дело паранойи и недоверия, но даже скептики типа Брюса Шнайера не видят особый смысл использования 256 бит ключей против 128. В AES-е безопасность пусть и 126.5 бит, но IMHO даже этого достаточно @item Автор так не доверяет NIST-овским кривым, но к AES не имеет никакого предвзятого отношения. Для меня это странно @item Почему-то полностью исключены UMAC алгоритмы MAC. И почему размер подписи должен быть не менее 128 бит. Если алгоритм MAC использует nonce-ы (например счётчик) на входе, то нет смысла встраивать эту информацию в сам тэг и при достаточно частой смене ключей аутентификации безопасность коротких тэгов вне сомнений (а это существенная экономия трафика, ведь с каждым сообщением добавляется этот тэг). UMAC их позволяет делать и, как правило, значительно быстрее HMAC. Poly1305 это как-раз разновидность UMAC @end itemize @strong{Проблема} Собственно почему всё это пишется. Эдвард Сноуден раскрыл @url{https://www.spiegel.de/international/germany/inside-the-nsa-s-war-on-internet-security-a-1010361.html, документы} в которых упоминается что у спецслужб есть возможность прослушивать SSH. Как они это делают: @itemize @item получают долгоживующие асимметричные ключи с серверов или у пользователей @item дешифруют слабую криптографию @end itemize Под слабой криптографией подразумевается и действительно устаревшая, в которой в ходе многих лет криптоанализа нашли уязвимости, и та к которой приложили руку эти самые спецслужбы. Сноуден продемонстрировал что лазейки в алгоритмах они для себя @url{https://projectbullrun.org/dual-ec/vulnerability.html, сделали}, чем и пользуются. Криптография это не только чисто математическая и техническая область. Огромный вес имеет доверие, репутация, даже политика. В данной статье предлагается настроить SSH сервер и клиент так, чтобы исключить слабую недоверяемую криптографию. @strong{Аутентификация сервера} Первым делом после установки TCP соединения SSH необходимо убедиться что на другом конце тот самый сервер который мы и ожидаем увидеть. То бишь аутентифицировать его. К сожалению SSH не поддерживает алгоритмы одновременной аутентификации и обмена ключами, хотя существуют алгоритмы даже двустороннего аутентифицированного обмена ключами. Но это лишь вопрос деградации производительности и трафика. Существуют патчи добавляющие SRP (двусторонний аутентифицированный обмен ключами), но его нет в mainline версиях OpenSSH. SSH предоставляет следующие алгоритмы: @itemize @item @code{ecdsa-sha2-nistp256} @item @code{ecdsa-sha2-nistp256-cert-v01@@openssh.com} @item @code{ecdsa-sha2-nistp384} @item @code{ecdsa-sha2-nistp384-cert-v01@@openssh.com} @item @code{ecdsa-sha2-nistp521} @item @code{ecdsa-sha2-nistp521-cert-v01@@openssh.com} @item @code{ssh-dss} @item @code{ssh-dss-cert-v00@@openssh.com} @item @code{ssh-dss-cert-v01@@openssh.com} @item @code{ssh-ed25519} @item @code{ssh-ed25519-cert-v01@@openssh.com} @item @code{ssh-rsa} @item @code{ssh-rsa-cert-v00@@openssh.com} @item @code{ssh-rsa-cert-v01@@openssh.com} @end itemize Итого это либо: RSA, либо DSS (вариант DSA), ECDSA (DSA на основе эллиптических кривых), Ed25519. DSS/DSA отпадают, так как стандартом определены длины ключей только размеров в 1024 бит, а этого уже недостаточно. ECDSA варианты отпадают так как используют кривые созданные NIST-ом и в них уже найдены @url{http://safecurves.cr.yp.to/, уязвимости}. Ed25519 это вне всяких сомнений лучший вариант: алгоритм подписей на основе эллиптических кривых, создан Дэниелем Бернштайном (независим от госорганизаций, корпораций, великолепный математик, криптограф, программист, хакер), работает за константное время, очень быстрый код, 256 бит размер ключей. RSA сам по себе хуже только тем что сложнее реализовать (хотя в OpenSSH с этим проблем нет) и он во много раз медленнее и размеры подписей с публичными ключами занимают в разы больше места. Плюс никто не гарантирует что RSA ключи на сервере/клиенте будут сгенерированы достаточной длины. Мои предпочтения: @verbatim HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com, ssh-ed25519, ssh-rsa-cert-v01@openssh.com, ssh-rsa-cert-v00@openssh.com, ssh-rsa @end verbatim @strong{Обмен ключами} После того как мы убедились что на другом конце тот кто нам нужен, то дальше необходимо установить (обменяться) ключи которые будут использоваться для шифрования и аутентификации сообщений. Этот этап за всё время сессии SSH может быть выполнен лишь один раз, но от него может зависеть абсолютно вся безопасность, так как не важно какой силы у вас алгоритм симметричного шифрования если ключи утекут на этапе обмена. Для обмена ключами используется асимметричный алгоритм Диффи-Хеллмана: самый первый в мире, революционный, асимметричный алгоритм. OpenSSH предоставляет следующие варианты: @itemize @item @code{curve25519-sha256@@libssh.org} @item @code{diffie-hellman-group-exchange-sha1} @item @code{diffie-hellman-group-exchange-sha256} @item @code{diffie-hellman-group1-sha1} @item @code{diffie-hellman-group14-sha1} @item @code{ecdh-sha2-nistp256} @item @code{ecdh-sha2-nistp384} @item @code{ecdh-sha2-nistp521} @end itemize ECDH это Диффи-Хеллман на эллиптических кривых, значительно более быстрый, но опять же использует NIST-овские кривые. Исключается. @code{diffie-hellman-group1-sha1} тоже исключается так как размер модуля группы DH 1024 бита. @code{diffie-hellman-group-exchange-} позволяет варьировать размеры группы от мала до велика: конкретные значения необходимо настроить (убрать маленькие) на сервере. Ну и SHA1 лучше перестать использовать совсем. Curve25519 схож с Ed25519. Обладает всеми теми же свойствами. Очень быстрый (вроде даже самый быстрый среди на практике используемых безопасных алгоритмов DH на основе эллиптических кривых), простой в коде, 256 бит размер ключей. Вне всякой конкуренции: он лучший. К сожалению многие серверы не поддерживают ни curve25519, ни даже все остальные DH. Мои предпочтения: @verbatim KexAlgorithms curve25519-sha256@libssh.org, diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1 @end verbatim @strong{Шифрование} После того как ключи установлены, то можно уже начинать и само шифрование -- то самое что гарантирует нам конфиденциальность. В отличии от этапа аутентификации и обмена ключами: производительность в данном контексте уже играет очень существенную роль. Одно дело получить на одном ядре процессора возможность передавать данные со скоростью гигабит, а другое дело еле-еле вытягивать несколько десятков мегабит. @itemize @item @code{3des-cbc} @item @code{aes128-cbc} @item @code{aes128-ctr} @item @code{aes128-gcm@@openssh.com} @item @code{aes192-cbc} @item @code{aes192-ctr} @item @code{aes256-cbc} @item @code{aes256-ctr} @item @code{aes256-gcm@@openssh.com} @item @code{arcfour} @item @code{arcfour128} @item @code{arcfour256} @item @code{blowfish-cbc} @item @code{cast128-cbc} @item @code{chacha20-poly1305@@openssh.com} @item @code{rijndael-cbc@@lysator.liu.se} @end itemize 3DES: усиленная версия DES алгоритма, обладающая 112 бит силой. В принципе использовать можно если такой силы достаточно, однако не рекомендуется из-за безумно медленной скоростью работы. Ну и среди всех остальных алгоритмов эти 112 бит -- наименьшая безопасность. Arcfour (также известный как RC4): потоковый шифр, очень быстрый относительно многих других. Имеет много особенностей и проблем с правильным использованием. Настолько много что его рекомендуют никогда не применять. Говорить что он совсем сломан и не юзабелен я бы не стал, но рекомендовать его тоже не стоит. CAST128 -- предшественник одного из финалистов конкурса AES, одобрен к использованию на государственном уровне в Канаде (читай: канадский ГОСТ). Каких-то критичных недостатков вроде не имеет, но и производительностью или чем-то другим интересным не выделяется. Rijndael -- финалист конкурса AES. Честно говоря, не знаю разницы в OpenSSH между этим Rijndael и AES. Возможно это оригинальная не ослабленная AES версия алгоритма. AES -- известный, популярный, полно где применяющийся алгоритм. За десятки лет имеет много криптоанализов. Может смущать что это ослабленная версия Rijndael (для повышения производительности, как официально заявляется), но многие годы анализов не выявили атак которые бы призвали его в негодность. Брюс Шнайер, Дэниель Бернштайн доверяют этому алгоритму. Хотя у него и имеются проблемы в реализациях: ключи например могут утекать через кэш процессоров современных. Да и сама реализация не такая уж простая в коде. В любом случае это очень неплохой компромисс между безопаснотью/сложностью и производительностью. Blowfish -- старый, хорошо известный (проанализированный) алгоритм созданный Брюсом Шнайером. Независимость от госструктур, хорошо проанализированный, имеющий неплохую производительность. Если есть недоверие к AES, то я бы рекомендовал. В AES есть три варианта: CBC, CTR, GCM. Это разные режимы шифрования. Не вдаваясь в подробности: в SSH выявлена уязвимость при которой можно получить до 32 бит открытого текста (дешифровать его то бишь). Необходимо либо обновить SSH-сервер, либо как контрмера простая: не использовать CBC режим. Сам CBC не имеет уязвимостей: это лишь в контексте SSH у него есть такой недостаток. Даже если SSH у вас свежий, то CBC всё-равно не рекомендовал бы: для его сообщений требуется дополнение (увеличение трафика) и его вычисления нельзя распараллелить. CTR (режим счётчика): можно распаралаллелить вычисления, не требует дополнения. GCM: относительно недавно введённый режим аутентифицированного шифрования (поэтому не во всех SSH-релизациях встретится) -- то есть одновременно сразу же при шифровании производится и вычисление аутентифицирующего тэга. Очень сильно подкупает то, что GCM в современных x86-процессорах имеет аппаратное ускорение. Даже без него не требует как и CTR дополнения, может быть распараллелен. ChaCha20-Poly1305: опять же вне конкуренции это лучший вариант. ChaCha20 алгоритм потокового шифра (более быстрый вариант Salsa20) совмещённый с Poly1305 алгоритмом аутентификации. Созданы опять же Дэниелем Бернштейном, не имеет хоть сколько-то серьёзных выявленных проблем в безопасности, очень просты в реализации (менее 100 строк кода на C), имеют фантастическую производительность: они быстрее аппаратно ускоренного AES-GCM. То есть более надёжный, более безопасный, более быстрый чем аппаратно ускоренный AES алгоритм аутентифицированного шифрования. Вопрос размера ключа шифрования скорее религиозный, вопрос доверия. В принципе 128 бит достаточно. AES-128 имеет 126.5 порог безопасности. По мне так и этого достаточно. 256 бит лично я бы выбрал, если бы не сильно деградировала производительность. Кстати, ChaCha20 имеет 256 бит ключ и она даже при этом быстрее AES-128. Мои предпочтения: @verbatim Ciphers chacha20-poly1305@openssh.com, aes128-gcm@openssh.com, aes128-ctr, blowfish-cbc @end verbatim @strong{Аутентификация сообщений} Зашифрованные сообщения могут быть при передаче изменены. Изменение шифрованного текста может приводить к осознанному изменению открытого текста после дешифрации. Передавать неаутентифицированные сообщения нельзя никогда. Кроме того необходима проверка их целостности. OpenSSH предоставляет следующие алгоритмы: @itemize @item @code{hmac-sha1} @item @code{hmac-sha1-96} @item @code{hmac-sha2-256} @item @code{hmac-sha2-512} @item @code{hmac-md5} @item @code{hmac-md5-96} @item @code{hmac-ripemd160} @item @code{hmac-ripemd160@@openssh.com} @item @code{umac-64@@openssh.com} @item @code{umac-128@@openssh.com} @item @code{hmac-sha1-etm@@openssh.com} @item @code{hmac-sha1-96-etm@@openssh.com} @item @code{hmac-sha2-256-etm@@openssh.com} @item @code{hmac-sha2-512-etm@@openssh.com} @item @code{hmac-md5-etm@@openssh.com} @item @code{hmac-md5-96-etm@@openssh.com} @item @code{hmac-ripemd160-etm@@openssh.com} @item @code{umac-64-etm@@openssh.com} @item @code{umac-128-etm@@openssh.com} @end itemize Тут у SSH выявляется критически важный недостаток первоначальных реализаций. Подписать и зашифровать сообщение можно в разных порядках: @itemize @item зашифровать, потом добавить подпись зашифрованного сообщения @item добавить подпись открытого сообщения, потом зашифровать всё это @item зашифровать, потом добавить подпись открытого сообщения @end itemize Первый вариант делает IPsec, второй TLS, третий SSH. Вариант SSH категорически нельзя применять. Вариант TLS может быть атакован, что и сделали в BEAST атаке. Вариант IPsec (Encrypt-then-MAC) всегда правилен и только так и должен применяться. Половину доступных алгоритмов в OpenSSH имеют приписку etm (Encrypt-then-MAC) и только они и должны всегда использоваться. К сожалению многие SSH серверы всё ещё не обновляются и не поддерживают их. Как я уже говорил в начале, короткие 64-бит тэги вполне приемлемы если правильно реализованы. Они быстрее вычисляются и меньше трафика едят. UMAC появился позже HMAC-ов, но пока не имеет недостатков в безопасноти. Зато имеет преимущество в виде высокой скорости работы зачастую. Остальные HMAC отличаются только используемой хэш-функцией. MD5 реально сломан, но в контексте HMAC он вполне себе годный к использованию. SHA1 уже не рекомендуется, но он тоже годен. Если очень важна производительность, то конечно HMAC-MD5 будет быстрее всех. Но я бы как и автор статьи рекомендовал бы не поддерживать криптографию от которой реально надо бы избавляться. Завтра не исключено что найдут ещё более серьёзную уязвимость в MD5/SHA1 и HMAC-MD5/SHA1 которая их сразу же приведёт в негодность, а трафик уже был перехвачен и записан нехорошими людьми. RIPEMD-160 создан в академических кругах, независимо от госструктур. Не имеет применимых криптоатак. Имеет 160 бит хэш, более короткий чем у SHA2, а значит экономящий трафик. SHA2 уже тоже не советуется к применению. Обладает пока достаточной криптографической силой, но он гораздо более медленный чем все остальные. Подчеркну что отдельный этап аутентификации сообщений, MAC, не применяется если мы уже использовали аутентифицированный режим шифрования. То есть GCM режим это уже применение аутентификации, так же как и Poly1305 это тоже чисто режим аутентификации (кстати это разновидность UMAC). Поэтому данная настройка не играет никакой роли для подобных шифров. Мои предпочтения (вынужден добавлять и не @code{-etm} версии из-за кучи не обновлённых серверов): @verbatim MACs umac-64-etm@openssh.com, umac-128-etm@openssh.com, hmac-ripemd160-etm@openssh.com, hmac-sha2-256-etm@openssh.com, hmac-sha2-512-etm@openssh.com, umac-64@openssh.com, umac-128@openssh.com, hmac-ripemd160, hmac-sha2-256, hmac-sha2-512 @end verbatim @strong{Общие рекомендации} @itemize @item Используйте сильную парольную фразу для ваших клиентских ключей @item Шифруйте диск где находятся ключи сервера @item Используйте только свободного программное обеспечение, проверенные временем и криптоанализами алгоритмы шифрования и, что важнее, их реализацию @item Следите за security обновлениями @item Не добавляйте то чего можно не добавлять. Каждая лишняя строчка кода это лишний повод появиться уязвимости. Не обновляйтесь ради обновления @end itemize @copyright{} Сергей Матвеев