Ранее я выборочно писал о разных полезностях в SSH, а в этот раз решил написать вообще обо всём, чем я в SSH пользуюсь. Будет в меру объяснений и много примеров. По сути здесь весь мой опыт использования SSH и всё написанное здесь я лично использовал. Соответственно, если чем-то не пользовался (например, tun-устройствами), то об этом не пишу.
Что такое и зачем нужен SSH Agent¶
SSH Agent (SSH Агент) хранит в памяти компьютера закрытые SSH-ключи. Когда SSH-клиент (/usr/bin/ssh
в линуксе и макоси, например) пытается подключиться к серверу при помощи ключа, она сначала делает запрос к SSH Agent и делегирует ему криптографическую операцию с закрытым ключом, который никогда не покидает пределы агента.
Без SSH Agent SSH-клиент напрямую читает ключи с диска, в линуксе и макоси они лежат в каталоге ~/.ssh
, если ключ зашифрован, то клиент спрашивает соответствующую парольную фразу. SSH Agent импортирует ключи к себе в хранилище и требует задать новую парольную фразу для доступа к ключу. Агент запоминает, когда клиент запрашивал ключ и может потребовать ввести парольную фразу и/или показать дополнительный диалог с подтверждением.
В linux и macos по умолчанию стоит /usr/bin/ssh-agent
из openssh, однако он малофунциональный и сложный в настройке. Вместо него можно использовать агент из комплекта gnupg (gpg-agent
), он умеет не только PGP-ключами управлять, но и выполнять функцию SSH Агента. У gpg-agent есть два преимущества: он настраивается, а также позволяет задавать пароли для шифрования ключей в памяти.
Ранее я уже писал несколько раз об организации ssh-туннелей: SOCKS-прокси через SSH, Туннель через SSH-сервер. В этой статье я расскажу, как максимально безопасно организовать SOCKS-прокси через ssh-туннель.
Обычно, когда делают SOCKS-прокси-туннель, просто добавляют к команде соединения через ssh аргумент типа -D localhost:8008
. Потенциально это не очень безопасно по нескольким причинам:
- вместо аутентификации по ключу используется интерактивная аутентификация по паролю;
- на сервере может быть включен X-Forwarding, дыра;
- аутентификация происходит под обычным ssh-пользователем в интерактивной сессии.
Интерактивная сессия для туннеля не нужна, более того, если вы позволяете соединяться нескольким клиентам под одним аккаунтом, вы им фактически разрешаете выполнять любые команды на сервере.
Аутентификация по паролю также чревата последствиями. Например, если вы хотите разрешить нескольким разным людям подключения с туннелем, вам придётся создать несколько аккаунтов на сервере с разными паролями. Логин через ключи решает эту и ещё несколько других проблем.
Также для аутентификации для прокси-туннеля можно использовать отдельный ключ с простым паролем, это удобно.
Обновлено 2016-06-26: инструкция изменена для El Capitan
В стандартной конфигурации (речь дальше пойдёт про Mac OS 10.9 Mavericks и выше) при использовании ssh-ключей во встроенном ssh-клиенте парольная фраза запрашивается через макосный security-фреймворк (и стандартный диалог запроса пароля соответственно). После первого ввода пароля запускается ssh-agent и при дальнейших вызовах ssh или git c этим ключом пароль больше не запрашивается.
На мой взгляд, такая схема слишком небезопасная и нужно какое-то разумное ограниченное время жизни «запомненного» ключа в агенте, например, пара минут. Cделать это штатными средствами через диалоги/настройки невозможно, однако можно изменить файл запуска агента и выставить там нужное время жизни ключа в агенте. В результате практически при каждой попытке использовать любой ключ будет выскакивать диалог запроса парольной фразы.
В SSH есть крайне полезная фича, позволяющая организовать прозрачный проброс трафика через практически любой SSH-сервер. Принцип туннелирования простой: подключаемся к ssh-серверу со специальными опциями и получаем SOCKS-прокси, висящий на указанном в опциях порту локальной машины. Что самое приятное — на удалённой машине не надо ставить никакой софт, плюс необязательно быть суперпользователем, достаточно обычного аккаунта.
Дальше я детально опишу сценарий настройки и конфигурации такой системы.
Аккаунт на ssh-сервере можно легко использовать для создания SOCKS-прокси, причём для этого достаточно обычного непривилегированного аккаунта. Всё делается очень просто (подключаемся к серверу example.com под юзером user):
% ssh -D 127.0.0.1:13388 [email protected]
Запускается с виду обычная ssh-сессия, оставляем её в таком виде, а дальше указываем в клиенте (веб-браузере, например) адрес SOCKS-прокси 127.0.0.1
, порт 13388
и пользуемся.
По сути ssh-клиент организует туннель, по которому гоняется трафик. Особенным плюсом является то, что на стороне сервера не нужно вообще никакого специального софта.
Другой полезный рецепт — создание туннеля до конкретного сетевого сервиса, работающего на удалённом сервере или доступного только с удалённого сервера. Делается это так:
% ssh -L LOCAL_ADDR:2222:HOST_ADDR:80 [email protected]
LOCAL_ADDR можно опустить, тогда будут использованы все локальные сетевые интерфейсы:
% ssh -L 2222:HOST_ADDR:80 [email protected]
При этом происходит следующее: все соединения с локальной машины к адресу LOCAL_ADDR:2222 (для бо́льшей безопасности можно указывать LOCAL_ADDR равным 127.0.0.1
или localhost
) будут перенаправляться через SSH-соединение и уже с компьютера на другом конце отправляются на адрес HOST_ADDR:80. По такому принципу можно пробрасывать любое сетевое соединение; самый простой пример — до http-сервера, видного только в сети ssh-сервера, или до сервера базы данных.
Вот пример для пробрасывания подключения до сервера mysql, доступного в удалённой сети по адресу 192.168.3.12 и порту 3306:
% ssh -L 127.0.0.1:5900:192.168.3.12:3306 [email protected]
Естественно, все эти опции можно задавать через конфиг ssh-клиента, создавая нечто вроде «профилей подключения» для разных туннелей и сервисов. Об этом я напишу чуть позднее.
Другие статьи на эту же тему¶
- Меняем ssh-agent на gpg-agent
- Параноидальная настройка ssh-agent в Mac OS X Mavericks
- SOCKS-прокси через SSH
- Безопасный ssh-туннель
История изменений¶
- 2013-01-22: изначальная версия