Введение
Доброго времени суток, хабр! В этом туториале я кратко распишу базовую настройку безопасного vps сервера для личного пользования(например pet проектов) на ubuntu 22.04. На истину в последней инстанции не претендую, поэтому с радостью буду дополнять статью советами и коммандами из комментариев)
Примечания
Везде где я использую vim для работы с текстовыми файлами, вы можете использовать nano, так как он более понятный.
В этом туториале предполагается, что vps вы уже выбрали и приобрели, с выбором оного может помочь вот эта статья
Настройка
Обновления
После покупки vps обычно вы получаете пароль от рута и ip адрес вашего севера, используйте их для входа.
ssh root@your_ip
Подключаемся на сервер, нажимаем yes и вводим пароль.
apt update && apt dist-upgrade -y && reboot
Обновляем данные о пакетах, апгрейдим все что есть на сервере и перезагружаемся, после чего заново входим на сервер.
Я использую apt dist-upgrade
, вместо apt upgrade
потому что это безопаснее и надежнее, подробнее можно почитать тут
Создание пользователя и настройка sudo
useradd -m super -G sudo -s /bin/bash
Создаем пользователя по имени super для работы с правами на sudo, собственной директорией и с bash в шелла.
Отдельного пользователя для работы мы делаем, так как работать из под рута небезопасно из-за неограниченных привилегий.
visudo
Правим sudo конфиг через специальную тулзу, встроенную в sudo. Здесь нам нужно исправить несколько вещей:
1. Даем возможность пользователям группы sudo использовать sudo без ввода пароля, добавляя NOPASSWD
, так как мы не будем устанавливать пароли.
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD:ALL
2. Запрещаем использовать дополнительные конфиги для безопасности, поэтому комментируем эту строчку.
#includedir /etc/sudoers.d
3. Запрещаем группе admin использовать sudo, комментируя эту строчку.
# Members of the admin group may gain root privileges
#%admin ALL=(ALL) ALL
итоговый /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
#%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD:ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
su super
cd
Заходим под созданным пользователем в его домашнюю директорию для дальнейшей настройки.
echo 'umask 0077' >> .bashrc
Ставим маску на все создаваемые файлы, чтобы максимально ограничить доступ к ним.
mkdir .ssh && chmod 700 .ssh
Создаем папку для хранения ssh ключей и оставляем доступ только пользователю.
Почему именно 700 можно почитать здесь
Настройка ssh
Для безопасного входа на сервер нам нужно сгенерировать ssh ключи, чтобы использовать их вместо паролей. На этом этапе нужно две консоли, одна на сервере, а другая на локале.
# locale
ssh-keygen -t rsa -b 4096
Генерируем ssh ключи на локальном компьютере, не на сервере! И получаем два ключа в папке ~/.ssh/
: публичный(у него на конце .pub
), который мы грузим на сервер, и приватный, который мы никуда никогда не загружаем!
# locale
scp .ssh/id_rsa.pub root@your_ip:/home/super/.ssh/
Загружаем полученный на предыдущем шаге ключ на сервер в папку нашего пользователя.
# server
sudo chown super:super .ssh/id_rsa.pub && chmod 700 .ssh/id_rsa.pub && mv .ssh/id_rsa.pub .ssh/authorized_keys
В консоли которая уже на сервере 'передаем' загруженный ключ под нашего пользователя, т.к. загружали мы его под рутом, ограничиваем права доступа к нему и переименовываем в authorized_key.
# locale
ssh -i .ssh/id_rsa super@your_ip
Проверяем, что удачно можем авторизоваться на сервере с помощью ключа под нашим пользователем и продолжаем настройку.
# server
sudo vi /etc/passwd
Выключаем пользователя root, чтобы никаким способом нельзя было работать из под него. Меняем его shell на /usr/sbin/nologin
, должно получиться вот так:
# server
sudo vi /etc/ssh/sshd_config
Теперь нам нужно настроить ssh сервер. Нам нужно исправить следующие строчки:
Меняем порт на нестандартный
Port 2220
Явно запрещаем авторизацию под root, меняя yes на no
PermitRootLogin no
Запрещаем авторизацию по паролю, оставляя только по ключу:
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no
Выходим и сохраняем конфиг, после чего перезапускаем ssh сервер.
# server
sudo systemctl restart sshd
Итоговый /etc/ssh/sshd_config
# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
Include /etc/ssh/sshd_config.d/*.conf
Port 2220
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
PubkeyAuthentication yes
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
Banner /etc/ssh/banner
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
# override default of no subsystems
Subsystem sftp /usr/lib/openssh/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
# locale
vi .ssh/config
Настраиваем ssh config, чтобы каждый раз не прописывать ip адрес, путь до ключа и пользователя.
Host pet
# Меняем на свой ip
HostName your_ip
# Меняем на своего пользователя
User super
IdentitiesOnly yes
IdentityFile ~/.ssh/id_rsa
# Меняем на свой порт, если не меняли порт, то ставим 22
Port 2220
Теперь мы можем подключаться на сервер с помощью команды:
ssh pet
Подключаемся на сервер и продолжаем настройку.
Установка доп. программ
sudo apt install git ufw nmap net-tools curl
Устанавливаем дефолтные тулзы для работы.
ufw - надстройка над
iptables
, упрощает настройку файрволла сервера.git - часто необходим для скачивания и развертывания программ на сервере, лишним не будет.
nmap - для 'простукивания' портов, помогает проверить что на сервере лишние порты не открыты.
net-tools - сюда входит популярный
ifconfig
иnetstat
, часто облегчает работу.curl - для выполнения http запросов прямо из консоли.
(Опционально) Если нужен докер, то инструкция здеcь
Firewall
# Если меняли порт ssh
sudo ufw allow 2220/tcp
# Если не меняли
sudo ufw allow ssh
Разрешаем подключение по ssh.
sudo ufw default deny incoming
sudo ufw default allow outgoing
Запрещаем все входящие подключения и разрешаем все выходящие.
sudo ufw enable
Включаем firewall.
На этом базовая настройка сервера закончена, надеюсь туториал вам помог :-)
Комментарии (41)
Revertis
24.08.2023 22:23Если я захожу на сервер, то чтобы что-то настроить или обновить. Значит мне нужны рут-права. Смысл создавать себе препоны в виде отдельного юзера, но с правами запускать что угодно без пароля через sudo? Тупость какая-то.
А если у меня там крутятся не совсем доверенные сервисы, то их как раз можно разнести по отдельным юзерам, без прав на sudo.
aborouhin
24.08.2023 22:23+1Снижаем риск случайной ошибки при запуске тех команд / программ, где нам sudo не нужно.
Делаем неизвестным для атакующего ещё и имя пользователя. Но его, конечно, покреативнее надо назвать, чем автор статьи предлагает.
Да и в целом, стандартная же практика.
cat_chi
24.08.2023 22:23+2sudo-пользователь с фактическими правами рута, получаемыми без пароля – стандартная практика? Для чего, для Ubuntu Desktop?
Стандартная практика – не запускать приложения под рутом. Особенно если они как-то доступны снаружи.
А для обслуживания сервера нет проблемы заходить под рутом.
Запрет входа по паролю – уже защитит вас куда лучше, чем "креативное" имя sudo-пользователя, учитывая, что боты не только стучатся под рутом, но и активно перебирают имена.Ну, чтобы потешить паранойю можно добавить fail2ban, сменить ssh-порт на нестандартный или даже ограничить доступ к серверу определённым пулом адресов.
Revertis
24.08.2023 22:23Менять порт SSH надо хотя бы для того, чтобы не засирались логи :))
А так да, выключение входа по паролю, разрешение входа только по ключам, и не надо запутывать всех дополнительными юзерами.CherryPah
24.08.2023 22:23Флуд в логе не беда, его можно удобно грепать регуляркой и превентивно банить особо отличившиеся ботофермы ещё на входе, где-нить в районе бордера.
Не руками разумеется )
isden
24.08.2023 22:23Флуд в логе очень сильно мешает, особенно если есть какой-нибудь logcheck.
Приходится менять порт примерно раз в полгода.
Плюс не увидел в статье ничего про fail2ban — очень помогает при набегах ботов.Из недавнегоИ их там сотни 2 таких было
CherryPah
24.08.2023 22:23У меня есть некий самописный аналог распределенного f2b, работает на /22 уже лет 5 и подкопил некую базу и статистику. Бордер по bgp эту базу регулярно синхронизирует и дальше атаки до серверов уже не долетают, режутся прям на нем. Простыни типа вашей давно уже в логе не видел.
Но тут вопрос масштаба разумеется, единичную впску конечно проще прикрыть f2b или упороться в порт-кноккинг. Ну или просто hosts.allow заполнить и deny all. Прикрывать сеть - проще централизованно
isden
24.08.2023 22:23У меня была мысль сделать общую блэклист базу с детектом и добавлением на всех хостах. Но у меня сейчас 2 сервера (планируется еще один), решил не заморачиваться и просто вручную обновлять списки :)
atshaman
24.08.2023 22:23Со сменой порта легко поиметь connectivity-problems при попытке доступа к своей VPS'ке из каких корпоративных интранетов и\или у особо упоротых провайдеров - причем узнать об этом можно в самый неподходящий момент. КМК больше вреда, чем пользы.
NutsUnderline
24.08.2023 22:23Были тут такие статьи, тут есть вариант сделать резервный вебшел shellina либо ttyd
len2367 Автор
24.08.2023 22:23Если нужен доступ к ssh из корп сетей, то уже нужно отталкиваться от конкретных настроек, т.к. я встречал проблемы с подключением по 22 порту из корп сети и помогала только перенастройка на 80/443 порт.
atshaman
24.08.2023 22:23Да, и такое тоже бывает. Но "в целом" смена дефолтных портов для стандартных протоколов как представитель методов "security through obscurity" как по мне - не лучшая идея. Сканирование портов нонеча дешевое и быстрое...
len2367 Автор
24.08.2023 22:23Это не главный способ защиты, а просто мелочь, позволяющая отсечь какой-то процент не очень умных ботов, лишним не будет)
MountainGoat
24.08.2023 22:23Это только чтобы отсечь тупых ботов, коих однако большинство. Не ради безопасности, а чтобы они не нагружали CPU запросами. Особенно заметно на соло VPS за 200 рублей.
aborouhin
24.08.2023 22:23Стандартная практика - запрещать вход под рутом, как минимум удалённый. Первая же страница результатов поиска по словам "why should you not use root" в гугле даёт такое количество описаний и обсуждений, что этого точно должно хватить для подобного вывода.
Заходя "для обслуживания" (раз уж у нас сервер, куда мы в принципе заходим вручную), мы тоже делаем много чего, не требующего административных прав. И не запускать от рута то, что можно от него не запускать, - как минимум не помешает. Собираем из исходников? Configure и make от пользователя, make install через sudo - стандартно. Используем питон? pip install от рута вообще весело конфликтует с модулями, поставленными через apt. Так что отдельный пользователь-администратор нам нужен, если мы на сервере руками копаемся.
Вход только по ключу, смена порта и fail2ban - безусловно. Про первое и второе написал сам автор, третье добавил я в первом своём комменте. Но это от всё только от ботов и прочих удалённых атак. Ограничение входа по IP не всегда применимо (хотя в случае с виртуалками, на которые всегда можно зайти через консоль в гипервизоре, логично вообще пускать по SSH только через VPN, а вот если сервер физический, да ещё без IP-KVM, тут сто раз подумаешь, как самому не лишиться доступа в нештатной ситуации). А нестандартное и несловарное имя пользователя в добавок к этому всему нам может помочь, скажем, в ситуации, если, флэшку с нашим ключиком у нас целенаправленно увели/отобрали/изъяли.
NutsUnderline
24.08.2023 22:23ключиком у нас целенаправленно увели/отобрали/изъяли
Вот тут не совсем понял: если увели то логично (только надо проследить чтобы это имя в коменте к ключу не засветилось), а если изъяли -то скорее всего вместе с нестандартным именем
MountainGoat
24.08.2023 22:23А не надо хранить нестандартное имя на том же носителе, что и ключ. Его можно иметь одно на группу машин одного рода, и тогда и запомнить не грех.
NutsUnderline
24.08.2023 22:23Мы рассматриваем сценарий "отобрали" а это уже подразуемвает физическое воздействие вплоть до критического.
Просто хочу понять что имелось в ввиду
aborouhin
24.08.2023 22:23+1Имелось в виду - пришли с обыском в офис, забрали со стола админа флэшку. Терморектальный криптоанализ не применяли. Комп админа не изъяли или изъяли, но там всё зашифровано. А вот флэшка в ключиком, зараза, незашифрованная лежала, т.к. админ её с собой таскал на всякий пожарный случай. Вполне реальный сценарий, гораздо чаще в жизни встречается, чем более жёсткие варианты, если мы про обычные бизнес-разборки, а не про политику и т.п. Опера на обыске вообще особо ничего не расспрашивают, просто загребают всё, что отдалённо напоминает электронику (у меня док-станцию к ноуту без самогó ноута пытались тут изъять недавно :)
Тут, конечно, надо и админа за хранение ключика в таком виде дружно осудить всем коллективом. И на ключики passphrase ставить. И много что ещё. Но при важности всех остальных мер ещё одна лишней тоже не будет. Тем более отдельный от рута пользователь-админ по другим изложенным выше причинам всё равно пригодится, так несложно заодно и назвать его как-нибудь позаковыристее.
NutsUnderline
24.08.2023 22:23+1внезапно - да, стандартная практика. Здесь автор вообще предлагает удивить ботов и сделать root еще более не логинным, но тупых ботов отлуп по ключу вообще не останавливает, они тупо перебирают весь запас
cat_chi
24.08.2023 22:23Весь запас чего? :) Ключей?
Ну это уже полный бред. Если у вас есть хоть капля подозрений, что ключ скомпрометирован, его надо менять. Если нет – то что они будут перебирать?
MountainGoat
24.08.2023 22:23+1На этот случай есть забавный сервер SSH tar pit. Стоит на машине, занимает порт 22. Сначала имитирует успешный логин от SSH, а потом начинает отдавать консольный промпт со скоростью 2 буквы в час. Ресурсов при этом не тратит почти, на графиках его не видно.
Naves
24.08.2023 22:23+1-
Запрещаем использовать дополнительные конфиги для безопасности, поэтому комментируем эту строчку.
#includedir /etc/sudoers.d
О сколько чудных нам открытий дает man sudoers
Hidden text
Including other files from within sudoers It is possible to include other sudoers files from within the sudoers file currently being parsed using the @include and @includedir directives. For compatibility with sudo versions prior to 1.9.1, #include and #includedir are also accepted. An include file can be used, for example, to keep a site-wide sudoers file in addition to a local, per-machine file. For the sake of this example the site-wide sudoers file will be /etc/sudoers and the per-machine one will be /etc/sudoers.local. To include /etc/sudoers.local from within /etc/sudoers one would use the following line in /etc/sudoers: @include /etc/sudoers.local
-
atshaman
24.08.2023 22:23Если про "радости параноика" говорить - то надо еще какой file integrity checker настраивать - mtree, afick - что-нибудь такое. Для ssh можно хостовые ключи в DNS прописать - при наличии DNSSEC даже осмысленно. Плюс - сразу же бэкапом всего, имеющего ценность озаботиться, чтоб потом по потолку не бегать - пока бэкап не настроен, "сервер не готов".
Кстати, по ssh рекомендация использовать rsa ключ кмк не самая лучшая в наши дни идея, если нет явных ограничений по использованию каких-нибудь очень древних клиентов.
ubx7b8
24.08.2023 22:23+3scp .ssh/id_rsa.pub root@your_ip:/home/super/.ssh/
Есть команда ssh-copy-id
Supme
24.08.2023 22:23Она и проверит существование добавляемого ключа, и наличие файла с ключами, права на папку и файл сделает нужными, и добавит к существующим, если есть другие. Вобщем правильно пользовать эту команду. И ключи делать уже не rsa, а ed25519 лучше.
aruslantsev
24.08.2023 22:23+3Запрещаем авторизацию по паролю, оставляя только по ключу
Еще стоит проверить, что в конфиге явно указано
KbdInteractiveAuthentication no
илиChallengeResponseAuthentication no
. Иначе такая команда может привести к удивительным результатам:ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no example.com
Выключаем пользователя root
А это лучше делать не через правку
/etc/passwd
руками, а черезsudo chsh -s /sbin/nologin root
. И еще рекомендую посмотреть ключи--expire
и--lock
для командыpasswd
.isden
24.08.2023 22:23KbdInteractiveAuthentication
ChallengeResponseAuthentication is a deprecated alias for this.
Araki_Satoshi
24.08.2023 22:23Хорошие базовые практики, сам аналогично делаю, лишь другими "словами". А хардить систему, я смотрю по комментариям, можно бесконечно.
aborouhin
Даже для базовой настройки маловато будет.
Обновления недостаточно один раз накатить, их регулярность надо и потом как-то обеспечивать. И тут или unattended-upgrades настраиваем, или, если у нас там всё настолько mission critical, что любой простой из-за непротестированного обновления вообще неприемлем, - как-то организуем процесс сложнее, но позаботиться об этом надо.
Для Ubuntu полезно на каждые 5 серверов заводить новый аккаунт Ubuntu Pro (ну или если у Вас всё серьёзно - купить подписку) и привязываться к нему, чтобы получить livepatch.
Раз уж мы про безопасность - то можно добавить к списку для установки и настройки fail2ban.
Опять же, что за сервер без мониторинга, так что сюда же - установка Prometheus Node Exporter, Zabbix Agent или что там по вкусу.
Отправку почты через SMTP relay неплохо бы настроить, ну и адрес админа в нужные конфиги вбить, чтобы сервер, если что захочет по почте сообщить, имел такую возможность.
И в завершение оформить всё это плейбуком Ansible - вот тогда будет красота :)
len2367 Автор
Идея хорошая, но мне кажется для vps для пет проекта многовато будет)
Добавлю, спасибо!)
Хорошая мысль, но опять же мне кажется многовато для маленького сервачка под пет. Но настройка всего этого как мне кажется тянет на еще один туториал :) Спасибо за наводку!
Joyz
Поделитесь своим плейбуком? ;)
aborouhin
"Колея это только моя - выбирайтесь своей колеёй!" :)
Мой плейбук - он мой, там много чего специфичного для моих конкретных потребностей. Если что конкретно интересует - пишите (лучше в личку, я комменты к старым постам редко смотрю).
Ну вот из неочевидного, для примера - такой кусок "bashsible" (антипаттерн, ага) для настройки того самого Ubuntu Pro (ubuntu_pro_account и ubuntu_pro_token задаются в group_vars, на каждые 5 хостов в пределах бесплатного лимита своя учётка и своя группа):
кусок плейбука
Ну или unattended-upgrades, тут вариант для убунт 20.04 и 22.04 и дебиана 11 как минимум:
ещё кусок плейбука