Intro
Тут на днях я узнал про выход новой Raspberry Pi 4 (кто не в курсе, это такой одноплатный мини-компьютер), и хоть я уже был счастливым обладателем 3 пишки, не удержался и купил обновленную версию. И, признаться, остался не совсем доволен из-за таких вещей как замена видеоразъёма HDMI → micro–HDMI (провод к которому еще надо найти и купить), традиционные периодические проблемы с питанием и тд. Но это – тема отдельной статьи. После того как все необходимые ингридиенты были получены и обнаруженные проблемы более-менее устранены, я как тру-админ и бекендер в душе настроил удаленный доступ к плате по SSH. В ходе этого занимательного процесса пришлось порыться в задворках своей памяти и почитать разные статьи в интернете по теме. Собственно эта статья и будет квинтессенцией того что я вспомнил про этот замечательный протокол с примесью инфы, сворованной из википедии.
Предупреждаю, я буду делать много вставок, возможно временами нести бред и использовать мат; мне вообще похуй, это мой сайт как никак, здесь ЦП не только в ЛС, а везде слать можно. Ладно всё, расслабьтесь, это шутка (но не точно), слава двачу, погнали!
Contents
- Intro
- Theory
- Practice
- Outro
Theory
Итак, закройте глаза, расслабьтесь (но не засыпайте, вам еще статью дочитывать) и представьте себе такую ситуацию:
Вы – админ серьёзной компании, настолько серъёзной, что у нее есть сайт. У вашей компании также есть сервер, на котором этот сайт и работает: HTML/CSS/JS-файлы, базы данных – всё там. А сервера – существа довольно прихотливые: подавай им то усиленное охлаждение, то определённую влажность воздуха, то еще что-то. Поэтому компанией было принято решение поставить ваш сервер в отдельное специально оборудованное помещение, с проветриванием и стойками – так называемой серверной. Вы же сидите в своем лампово обустроенном кабинете и гоняете кску усердно работаете. Ваша задача как админа – осуществлять настройку, обновление и бесперебойную работу сервера, чтобы клиенты компании всегда получали лучший юзер-експериенс от использования вашего сайта. А для этого естественно надо какаим-то образом взаимодействовать с сервером, вводить разные умные команды (по типу sudo rm –rf /). Что делать? Один из вариантов – переехать из вашего уютного кабинета с родными плакатами голых женщин и ретро-игр в шумную и жаркую серверную, чтобы иметь непосредственный доступ к серваку. Звучит как-то не очень воодушевляюще. Другое решение (рекомендую, особенно если вы уже приросли к стулу в своем кабинете) – настроить удалённый доступ. Вы по гайдам (и возможно по этой статье) совершаете определённый ритуал ввода магических команд и установки подозрительных пакетов, вследствие чего вы обретаете суперспособность управлять сервером с компьютера в вашем кабинете как если бы вы управляли им будучи рядом с ним в серверной. Not bad, по-моему.
Для осуществления такого удалённого доступа существует несколько протоколов: telnet, rlogin, SSH. Как говорят, последний в списке не обязательно последний по значимости, а возможно наоборот, потому что с точки зрения безопасности SSH наиболее предпочтителен для использования, и это еще мягко сказано, ввиду того что при разработке telnet и rlogin вопросы безопасности не рассматривались вообще. Сейчас посмотрим всё на схемах:
Абсолютно все данные при использовании ПО для удалённого доступа, использующего telnet/rlogin, передаются в открытом виде. Соответственно какому-нибудь кул-хацкеру не составит большого труда не только смотреть логины, пароли, какие именно команды вы выполняете на сервере и что они выдают в ответ, но и самому получить возможность выполнять на нём команды, а это полнейшее фиаско и фак гг. В случае использования SSH удалённый доступ осуществляется по другому принципу, в 2 этапа:
- Инициализация безопасного соединения
- Защищённый удалённый доступ
Перед началом сессии удалённого доступа две целевые машины с помощью хитрой математики создают защищённый “тоннель” (это конечно абстракция для удобства представления и повествования, на самом деле передаваемые просто “накрываются” шифрованием), такой, что если через него передавать данные, то возможность прочитать данные будет только у целевой машины на другой стороне. У хайкера на этот раз ничего не получится сделать, всё защищено тоннелем, и он пойдёт дальше мечтать о крутости на какой-нибудь hackertyper.net.
Далее мы можем осуществлять удаленный доступ как обычно.
И сейчас, когда образное представление о предметной области было получено, давайте добавим более номенклатуризированную (я чуть не сдох пока писал это слово) и точную теорию.
SSH (Secure Shell – защищённый шелл) – сетевой протокол прикладного уровня, использующийся главным образом для удалённого доступа/управления различными узлами в сети (хосты/роутеры/…). Также он может туннелировать внутри себя другие протоколы (например Linux-протокол удалённого рабочего стола X11). Стандартный номер сетевого порта – 22. Работает по модели взаимодействия клиент-сервер: на управляемой машине устанавливается SSH–сервер, исполняющий на ней команды от авторизованных SSH–клиентов, установленных на других машинах. Поддерживается параллельное подключение нескольких клиентов к одному SSH–серверу. Предусмотрена возможность сжатия данных, удобного для передачи аудио/видео.
Переходим к самому интересному: каким именно образом SSH осуществляет защищённое соединение. В SSH предусмотрены 3 вида аутентификации:
- Аутентификация по IP-адресу. Удалённый доступ предоставляется только той машине, которая имеет определённый IP-адрес. Ввиду того, что злоумышленник потенциально может “захватить” этот IP-адрес для своего хоста (кому интересно, гуглить по темам DHCP,ARP, routing tables) и далее успешно пройти аутентификацию, является небезопасным способом.
- Аутентификация по паролю. При создании соединения используется пароль, который клиент должен предоставить для подключения.
- Аутентификация по открытому ключу. На сервере хранятся файлы открытых ключей клиентов, которым разрешено подключаться у нему по SSH.
Аутентификация по IP-адресу. Удалённый доступ предоставляется только той машине, которая имеет определённый IP-адрес. Ввиду того, что злоумышленник потенциально может “захватить” этот IP-адрес для своего хоста (кому интересно как, гуглить по темам DHCP,ARP,ARP–spoofing, routing tables) и далее успешно пройти аутентификацию, является небезопасным способом.
Аутентификация по паролю. Здесь клиент должен предоставить пароль для успешного подключения. Пароль используется для выработки общего сессионного криптографического ключа, который будет использован в дальнейшем для шифрования всех передаваемых данных. На сервере хранится пароль. Сервер генерирует случайный сессионный ключ, шифрует его с помощью пароля и отправляет подключающемуся клиенту. Клиент, если он знает пароль и без труда расшифровывает полученные данные получая сессионный ключ для дальнейшего шифрования соединения. Если же он не знает пароль, то и сессионный ключ в открытом виде у него получить не удастся, и доступ соответственно не будет предоставлен.
Аутентификация по открытому ключу. Аналогично аутентификации по паролю, только в процессе создания сессионного ключа используется ассиметричная криптография. Сервер хранит открытый ключ клиента, которому разрешено подключаться по SSH. У клиента есть соответствующий закрытый ключ. Сервер генерирует случайный сессионный ключ, шифрует его открытым ключом клиента и отправляет клиенту. Клиент расшифровывает полученные данные закрытым ключом и получает сессионный ключ для шифрования соединения.
В криптографии так устроено, что чем больше длина пароля тем лучше, а ключи можно рассматривать в нашем контексте как пароли огромной длины. Соответственно аутентификация по открытому ключу в этом смысле предпочтительней, чем аутентификация по паролю.
Что касается конкретных алгоритмов шифрования: для выработки общего сессионного ключа используется алгоритм Диффи-Хеллмана; для шифрования передаваемых данных в ходе соединения используется симметричное шифрование, а именно AES, 3DES, Blowfish; за целостность отвечают CRC-32/HMAC–SHA-1/HMAC–MD5.
Practice
“Theory is when you know everything but nothing works. Practice is when everything works but no one knows why. In our lab, theory and practice are combined: nothing works and no one knows why”
“Это всё конечно красиво звучит, но Влад, на словах ты Лев Толстой, а по итогу мы ничего реального еще и не сделали” – скажете вы. Хм, соглашусь, я и сам терпеть не могу надменных теоретиков, поэтому lets get hands dirty right fucking now!
Дано: 2 хоста в одной сети, на обоих системах: ОС Linux Ubuntu 18.04 64bit.
Задача: настроить удалённый доступ одного хоста (SSH–клиент) к другому (SSH–сервер).
1. Установка
Большинство Linux–дистрибутивов уже имеют предустановленный SSH-клиент, который запускается так:
ssh [params]
соответственно на клиентскую машину(192.168.1.100) мы ничего устанавливать не будем. А вот на второй машине(192.168.1.200) установим SSH–сервер:
sudo apt update
sudo apt install ssh
SSH–сервер работает как служба, соответственно чтобы её запустить, набираем:
sudo systemctl start ssh.service
Если надо запускать SSH–сервер при старте системы (добавить в автозагрузку):
sudo systemctl enable ssh.service
Получить информацию о состоянии SSH–службы:
sudo systemctl status ssh.service
Тут всё довольно тривиально.
Конфигурационные данные SSH хранятся в /etc/ssh/. Здесь особое внимание стоит обратить на файл sshd_config – это основной конфигурационный файл SSH-сервера, нутро которого мы сейчас будем ковырять. Откроем его текстовым редактором на выбор, я буду использовать vim:
sudo vim /etc/ssh/sshd_config
Тут мы видем много ‘#’. Это символы начала однострочного комментария. Параметры имеют такую форму:
parameter_name param_value
Некоторые параметры закомментированы:
#parameter_name param_value
Если надо поменять дефолтные значения определённого параметра, надо его раскомментировать т.е. убрать ‘#’ вначале (если он вообще был закомментирован конечно) и собственно поменять значение на нужное.
Теперь посмотрим поближе на некоторые важные параметры в конфиге.
Port – номер сетевого порта на котором работает SSH-сервер. Если хост на котором у вас установлен SSH-сервер выходит в какую-нибудь сеть, где могут обитать нехорошие люди (например интернет) то рекомендуется поменять дефолтное значение 22, на какое-нибудь другое. Зачем? Всё очень просто. Вышеупомянутые нехорошие люди пишут специальные проги, ищущие хосты с SSH-серверами и пытающиеся подобрать пароль перебором. Мало того, что они своим флудом могут повлиять на производительность, так еще и реально же пароль подобрать удачно могут, и тогда “гг вп, админ репортед”. Соответственно если порт переназначить с дефолтного значения, то всей этой истории уже не бывать, так как ставка переборщиков сделана на стандартный 22 порт, соответственно туда и ломится весь этот брутфорс-трафик, который кончено будет дропнут, если порт закрыт.
Логирование SSH тесно связано с syslog-механизмом (кому интересно: https://en.wikipedia.org/wiki/Syslog).
SyslogFacility – определяет к какому типу syslog-сообщений будут относиться логи SSH.
LogLevel – определяет “уровень важности” логируемых сообщений. Все генерируемые SSH логи, имеющие этот уровень ниже установленного значения, записываться и храниться не будут. Возвращаясь к теме кул хацкеров и брутфорсеров паролей: если вы хотите заценить, насколько сильны их порывы заовнить ваш ваш сервак через SSH, просто установите в LogLevel значение VERBOSE (по умолчанию оно должно быть INFO):
LogLevel VERBOSE
После изменения лог-уровня попытки аутентификации будут зафиксированы в логе. Посмотреть всё это и впечатлиться упорностью можно в файле /var/log/auth.log.
PermitRootLogin – определяет возможность аутентификации на SSH-сервере как root. С точки зрения безопасности не очень хорошо, если такая аутентификация возможна, так как root – это бог, его права и возможности в системе неограничены. Если вдруг креды утекут нехорошим людям, то можно ливать. Гораздо лучше создать пользователя которому предоставлены только те привилегии, которые необходимы для работы (дада, принцип минимализма в ИБ) и предоставлять возможность авторизовываться через него (параметр AllowUsers), отключив аутентификацию как root.
AllowUsers – устанавливает список пользователей, в качестве которых могут авторизоваться SSH-клиенты. Авторизоваться возможно только в качестве указанных пользователей.
MaxAuthTries – устанавливает количество попыток входа по истечении которого последующие блокируются
MaxSessions – устанавливает максимальное количество подключений к серверу в каждый момент времени. Да, как упоминалось ранее, SSH-сервер имеет возможность поддержки сразу нескольких параллельных соединений.
PubkeyAuthentification –если значение “on”, то используется аутентификация по открытому ключу. Ваш кеп.
PasswordAuthentification – если значение “on”, то используется аутентификация по паролю. Cap strikes back.
Banner – Сообщение, которое будет показано при попытке подключения. Можно написать что-нибудь по типу “This server is under Area 51 & Mario jurisdiction”, чтобы скрипткидисы, пытающиеся похакать ваш сервак, сразу убежали от страха, роняя кал.
2. Использование
В зависимости от выбранного типа аутентификации (повторюсь, наиболее предпочтительная аутентификация по открытому ключу) дальнейшие шаги настройки немного отличаются.
Парольная аутентификация:
Устанавливаем значения в конфиге:
PasswordAuthentification on
PubkeyAuthentification off
Настройка сервера на этом закончена. Теперь можно и подключаться клиентом. Для этого используется команда ssh в формате:
ssh <user_name>@<server_ip/server_hostname>
Т.е. в нашем сетапе полная команда будет выглядеть так:
ssh user@192.168.1.200
Далее вводим пароль пользователя user и получаем удаленную командную строку от его имени. ??? Profit!
Aутентификация по ключу
Устанавливаем значения в конфиге:
PasswordAuthentification off
PubkeyAuthentification on
Настройка сервера закончена. Далее нужно сгенерировать для клиента пару открытый-закрытый ключ (т.е. 1 файл с открытым ключом (расширение .pub) и 1 файл с закрытым ключом, , по умолачнию в имя ключеваых файлов – id_rsa). Делается это с помощью команды ssh–keygen:
ssh-keygen
Будет предложено ввести место сохранения нового ключа (можно оставить значение по умолчанию), а также опциональный пароль, с помощью которого сгенерированная ключевая пара будет защищена (таким олбразом если каким-либо образом ключевые файлы украдут/скопируют/сольют, то воспользоваться ими для аутентификации на SSH–сервере всё равно будет невозможно).
Для того, чтобы иметь возможность проводить аутентификацию по открытому ключу, серверу нужно хранить открытые ключи клиентов, у которых есть разрешение на подключение. У каждого пользователя на сервере есть специальный файл в его личной папке – /home/<user_name>/.ssh/authorized_keys – где как раз сохранён список открытый ключей тех клиентов, которым разрешено подключиться к серверу в качестве этого пользователя. Поэтому открытый ключ, сгенерированный на клиенте, надо передать на сервер. Есть несколько способов сделать это, например взять флешку, записать файла открытого ключа с клиента и перенести с её помощью его на сервер, записав в соответствующий файл authorized_keys. Другое решение – опять же сделать всё это по сети, удалённо, и для этого также предусмотрена специальная программа – ssh–copy–id:
ssh-copy-id -i <pub_key_path> <user_name>@<server_ip/server_hostname>
В нашей конфигурации соответственно вот так:
ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@192.168.1.200
Вводим пароль пользователя, и команда сама запишет открытый ключ в authorized_keys файл выбранного пользователя. Убедитесь в том, что вы отправляете именно файл открытого ключа, а не закрытого (этот файл должен быть только у вас).
И теперь когда сервер имеет нужный файл открытого ключа, можем подключаться:
ssh user@192.168.1.200
Если на файл ключа при создании был установлен пароль, вводим его, и наконец получаем командную строку нужного пользователя на удалённом хосте. По моему это безоговорочная победа, можете удовлетворённо похлопать себя по попке за проделанную работу 🙂.
Как нетрудно видеть, ничего сверхсложного в настройке SSH нет – всё для пользователя, это вам не сайт госуслуг :3
Еще пара слов про SSH–клиенты. Это такие программы, которые служат для подключения по SSH(обычно поддерживается не только он, но и telnet, rlogin, …) плюс имеют различные свистелки –перделки по типу GUI-интерфейса, сохранения деталей подключения (адрес сервера, креды, …) в профили и тд. Навскидку примеры таких прог: PuTTY, SecureCRT.
Outro
Сегодня мы посмотрели на SSH – чьих он будет, чем может быть полезен; разобрались как с его помощью организовать защищённый доступ к удалённой машине. Словом, отлично потрудились, и теперь пора на отдых, переваривать новую информацию и думать как жить дальше после такого (я вот лично в ахуе просто). А я может быть справлюсь со своей природной ленью и скромностью и сделаю видос по SSH для большей наглядности (и чтобы потеснить ютуб-индусов офк).
Подписывайтесь, ставьте лайки, оставляйте положительные комментарии. Имейте дело исключительно с надежными, проверенными серваками и практикуйте только безопасное подключение для здоровой и полноценной сетевой жизни 😉
Links: