Безопасная настройка виртуального хостинга Debian + Apache2 + vsftpd

0
5

Организовать работу нескольких проектов на сервере, чтобы люди, которые ими занимаются, не имели доступа к соседним проектам:

1. Задача

  • Ограничить возможность обзора файловой системы определенной папкой для пользователя проекта.
  • Ограничить возможность запуска бинарников пользователями
  • Организовать безопасность сервера

Дано
Debian-сервер «из коробки» (установлен из дистрибутива)

2. Решение

  • 2.0 Обновление системы
  • 2.1 SSH
  • 2.2 Файловая система
  • 2.3 Apache
  • 2.3.1 Права пользователей [apache2-mpm-itk ]
  • 2.3.2 Отдельные tmp для каждого сайта
  • 2.3.3 Sendmail
  • 2.4 FTP
  • 2.5 MySQL + Postgres
  • 2.6 Firewall
  • 2.7 chroot
  • 2.8 Автоматизация

2.0 Обновляемся

Ставим свежие версии пакетов. Вот мой список репозиториев:

# file: /etc/apt/sources.list
# Yandex
deb mirror.yandex.ru/debian/ lenny main
deb mirror.yandex.ru/debian/ lenny contrib non-free
deb-src mirror.yandex.ru/debian/ lenny main
deb-src mirror.yandex.ru/debian/ lenny contrib non-free
# Security fix
deb security.debian.org/ lenny/updates main
deb security.debian.org/ lenny/updates contrib non-free
deb-src security.debian.org/ lenny/updates main
deb-src security.debian.org/ lenny/updates contrib non-free
debian:~# apt-get update
debian:~# apt-get dist-upgrade

2.1 Генерируем ключи для SSH

Дабы исключить возможность перехвата парольной фразы, мы сгенерируем rsa ключи для входа на сервер.

[email protected]:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/neoveneficus/.ssh/id_rsa):
/home/neoveneficus/.ssh/id_rsa already exists.
Overwrite (y/n) y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/neoveneficus/.ssh/id_rsa.
Your public key has been saved in /home/neoveneficus/.ssh/id_rsa.pub.
The key fingerprint is:
cb:07:dd:67:21:37:ab:93:e1:60:40:ce:0e:b8:b8:e3 neoveneficus@book
The key‘s randomart image is:
+—[ RSA 2048]—-+
| . |
| . + |
|. . + . + |
|.. o . . + + |
|+ . o S . o o |
|.o . + = . o |
|.E . * o |
| . o |
| . |
+——————+

Обратите внимание — ключи генерируются на Вашей рабочей машине, а затем публичный ключ заливается на сервер:

neoveneficus@book:~/.ssh$ scp ~/.ssh/id_rsa.pub root@217.212.252.146:.ssh/authorized_keys
neoveneficus@book:~/.ssh$ cat ~/.ssh/id_rsa.pub | ssh root@217.212.252.146 «cat > ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys»

Теперь мы сможем заходить на сервер — по ключу, с паролем или без — в зависимости от Ваших настроек. Хочется подчеркнуть, что если Вы сгенерировали ключи без пароля, то уровень безопасности сервера эквивалентен уровню безопасности Вашего секретного ключа на Вашей машине. Будьте внимательны и берегите ключ.

2.2 Файловая система. Права пользователей.

Поговорим про файловую систему. Я предлагаю выделить для наших сайтов отдельную папку в корне файловой системы.

debian:~# cd /
debian:/# mkdir -m 755 web

Домашние папки наших пользователей будут такого вида:

  • /web/site1
  • /web/site2

Создаем пользователей и расставляем права:

debian:~# useradd site1 -b /web/ -m -U -s /bin/false
debian:~# passwd site1
debian:~# chmod 754 /web/site1
debian:~# mkdir -p -m 754 /web/site1/public_html/www
debian:~# mkdir -p -m 777 /web/site1/tmp
debian:~# chmod +t /web/site1/tmp
debian:~# chown -R site1:site1 /web/site1/

Пользователь site1 будет иметь домашнюю папку /web/site1. Ключ -m означает, что папка будет создана автоматически. -U — так же будет создана одноименная группа, куда пользователь будет помещен. Пользователь не будет иметь шелла. Все, что будет доступно из веба — будет находится в папке public_html. Если когда-нибудь захочется иметь поддомены — разместим их в папках рядом с www.

2.3 Apache

2.3.1 Права пользователей. Модификация Apache [apache2-mpm-itk]

Как нам известно, по умолчанию web-сервер apache работает от одного пользователя для всех сайтов, находящихся на сервере. А это означает, что, воспользовавшись web-шеллом, можно прочитать файлы соседних проектов.

Для исправления этого недоразумения нам понадобится установить модифицированную версию аpache. Пакет называется apache2-mpm-itk. Установив пакет, мы получим возможность в конфигах файла указывать, от какого пользователя и группы должен работать apache при обработке сайта.

debian:~# apt-get install apache2-mpm-itk

Пользователь и группа задается строкой в конфиге:

AssignUserId site1 site1

В тоже время мы хотим, чтобы, используя web-шелл, нельзя было править файлы нашего проекта, кроме тех, на которыx стоят права o+w.

drwxr-xr— 2 site1 site1 4096 Мар 5 10:17 .
drwxr-xr-x 3 site1 site1 4096 Мар 5 10:14 ..
-rwxr-x— 1 site1 site1 0 Мар 5 10:14 index.php
-rwxrw—- 1 site1 site1 0 Мар 5 10:17 tmp.txt

Для этого в нашем конфиге мы будем писать:

AssignUserId www-data site1

Таким образом apache сможет прочитать index.php, выполнить и отдать в браузер, но не сможет изменить его. А tmp.txt изменить сможет.
Важный момент — нужно запретить консоль у пользователя www-data

debian:~# usermod -s /bin/false www-data
2.3.2 Отдельный tmp для каждого сайта

Предотвращаем инклуд сессий с соседнего сайта. + Запрещаем php выходить выше пользовательской домашней дирректории.

В конфиг нашего сайта нужно добавить диррективы open_basedir, upload_tmp_dir, session.save_path

Получаем такой минималистичный конфиг:

# file: /etc/apache2/sites-available/site1
DocumentRoot «/web/site1/public_html/www/»
ServerName «test1»
ErrorLog /web/site1/error_log
CustomLog /web/site1/access_log combined
AssignUserId www-data site1
php_admin_value open_basedir «/web/site1/:.»
php_admin_value upload_tmp_dir «/web/site1/tmp»
php_admin_value session.save_path «/web/site1/tmp»

После создания конфига нужно сделать сайт активным с помощью команды:

debian:~# a2ensite site1

А затем перечитать конфиги:

debian:~# /etc/init.d/apache2 reload
2.3.3 Sendmail

Почему я вынес Sendmail отдельным пунктом Потому что по умолчанию он не работал. Пришлось повозится. Я расскажу самый простой способ. Чтобы php умел отправлять письма, проделываем следующие операции.

# file: /etc/php5/apacge2/php.ini [раскомментируем и изменим строку]
++ sendmail_path = /usr/sbin/exim4 -t

Для конфигурации Exim4 (по умолчанию в качестве Mail Transfer Agent используется именно он) существует пакет exim4-config. Воспользоваться им можно так:

debian:~# dpkg-reconfigure exim4-config

После этого вам начнут задавать вопросы. На первый (Общий тип почтовой конфигурации) отвечаем:

  • интернет-сайт; прием и отправка почты напрямую, используя SMTP

А далее жмем Enter до конца настройки. Теперь все должно работать.

2.4 vsftpd

Теперь разберемся с FTP. Для работы был выбран vsftpd.

debian:~# apt-get install vsftpd

Далее меняем конфиг:

# file:/etc/vsftpd.conf
listen=YES
# Запрещаем анонимный доступ
anonymous_enable=NO
# Открываем локальным пользователям доступ к домашним директориям по FTP
local_enable=YES
# Разрешаем команды на запись
write_enable=YES
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
ascii_upload_enable=YES
ascii_download_enable=YES
ftpd_banner=Welcome to our FTP service.
# «Запираем» пользователей в домашних папках
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/vsftpd.pem

Говорим демону vsftpd перечитать конфиги:

debian:~# /etc/init.d/vsftpd reload

2.5 MySQL + PostgreSQL

Ставим MySQL

debian:~# apt-get install mysql-server phpmyadmin

Создаем нового пользователя.

debian:~# echo «CREATE USER ‘site1’@’localhost’ IDENTIFIED BY ‘Пароль_для_пользователя_site1’; GRANT USAGE ON * . * TO ‘site1’@’localhost’ IDENTIFIED BY ‘Пароль_для_пользователя_site1’ WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; CREATE DATABASE IF NOT EXISTS site1 DEFAULT CHARACTER SET utf8 COLLATE utf8_unipre lang=»bash«_ci; ; GRANT ALL PRIVILEGES ON site1 . * TO ‘site1’@’localhost’;» | mysql —user=root —password=Пароль_mysqlroot mysql

Ставим Postgres

debian:~# apt-get install postgressql phppgadmin

Меняем пароль на пользователя postgres:

debian:~# echo «\password» | sudo -u postgres psql
Enter new password: Новый_пароль_postgres
Enter it again: Новый_пароль_postgres

После установки рутового пароля для пользователя postgres нам мнужно поправить конфиг. По умолчанию любой локальный пользователь может запустить psql с правами суперпользователя без ввода пароля. Исправляем.

#file /etc/postgresql/8.3/main/pg_hba.conf
local all postgres ident sameuser
local all all ident sameuser
++ local all postgres md5
++ local all postgres md5

В /etc/phppgadmin/apache.conf открываем доступ извне.

order deny,allow deny from all allow from 127.0.0.0/255.0.0.0 ::1/128 # allow from all

Меняем на:

order deny,allow
deny from all
allow from 127.0.0.0/255.0.0.0 ::1/128
# allow from all

Говорим apache перечитать конфиги:

debian:~# /etc/init.d/apache2 reload

У постгрес есть один нюанс. Юзеры всегда видят названия соседних БД. Чтобы они не мозолили глаз нашим пользователям в phppgadmin, правим конфиг:

# file:/etc/phppgadmin/config.inc.php
$conf[‘owned_only’] = false; ++ $conf[‘owned_only’] = true;

Пользователи создаются такой командой:

debian:~# echo «CREATE USER site1 WITH PASSWORD ‘Пароль_для_пользователя_site1’ NOCREATEDB NOINHERIT NOCREATEUSER ; CREATE DATABASE site1 owner site1;» | sudo -u postgres psql

2.6 Firewall

В нашем случае цели просты — запретить злоумышленнику открывать порты. Поэтому решение будет простым — мы не будем вдаваться в нюансы правил iptables, а воспользуемся пакетом arno-iptables-firewall, который упростит нам жизнь. Он сам спросит нас, что мы хотим во время установки. Ответы на вопросы ниже.

debian:~# apt-get install arno-iptables-firewall
* Do you want to manage the firewall setup with debconf : Да
* External network interfaces: eth0
* Open external TCP-portrs: 21 22 53 80 443 3128 5432 5001 5900 6881:6889
* Open external UDP-portrs: 53 3130 5001 6881:6889
* Internal network interfaces: <в нашем случае оставляем пустым>
* Соглашаемся на перезагрузку firewall‘а.

2.7 Запуск Apache2 в chroot среде [посредством libapache2-mod-chroot]

Что такое chroot’инг Это создание специальной среды (песочницы), изолированной от окружения. Скажем, процесс apache не должен иметь доступа к папкам home. В тоже время в изолированную среду нужно брать все, что нужно для работы. Самый простой способ — это воспользоваться libapache2-mod-chroot.

debian:~# apt-get install libapache2-mod-chroot debian:~# a2enmod mod_chroot
debian:~# /etc/init.d/apache2 restart