Безопасная настройка виртуального хостинга Debian + Apache2 + vsftpd 1. Постановка задачи Дано Debian-сервер "из коробки" (установлен из дистрибутива) Задача Организовать работу нескольких проектов на сервере, чтобы люди, которые ими занимаются, не имели доступа к соседним проектам: Ограничить возможность обзора файловой системы определенной папкой для пользователя проекта. Ограничить возможность запуска бинарников пользователями Ограничить возможность открытия портов на сервере (нужно как-то по другому сформулировать) Автоматизировать добавление пользователя в систему: создание папки, конфига apache, пользователей mysql или postgres 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 Обновляемся Ставим свежие версии пакетов. Вот мой список репозиториев: Code: [B][COLOR=White]# file: /etc/apt/sources.list[/COLOR][/B] # Yandex deb http://mirror.yandex.ru/debian/ lenny main deb http://mirror.yandex.ru/debian/ lenny contrib non-free deb-src http://mirror.yandex.ru/debian/ lenny main deb-src http://mirror.yandex.ru/debian/ lenny contrib non-free # Security fix deb http://security.debian.org/ lenny/updates main deb http://security.debian.org/ lenny/updates contrib non-free deb-src http://security.debian.org/ lenny/updates main deb-src http://security.debian.org/ lenny/updates contrib non-free Code: debian:~# apt-get update debian:~# apt-get dist-upgrade 2.1 Генерируем ключи для SSH Дабы исключить возможность перехвата парольной фразы, мы сгенерируем rsa ключи для входа на сервер. Code: neoveneficus@book:~$ 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 | | . | +-----------------+ Обратите внимание - ключи генерируются на Вашей рабочей машине, а затем публичный ключ заливается на сервер: Теперь мы сможем заходить на сервер - по ключу, с паролем или без - в зависимости от Ваших настроек. Хочется подчеркнуть, что если Вы сгенерировали ключи без пароля, то уровень безопасности сервера эквивалентен уровню безопасности Вашего секретного ключа на Вашей машине. Будьте внимательны и берегите ключ. 2.2 Файловая система. Права пользователей. Поговорим про файловую систему. Я предлагаю выделить для наших сайтов отдельную папку в корне файловой системы. Code: debian:~# cd / debian:/# mkdir -m 755 web Домашние папки наших пользователей будут такого вида: /web/site1 /web/site2 Создаем пользователей и расставляем права: Code: 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 при обработке сайта. Code: debian:~# apt-get install apache2-mpm-itk Пользователь и группа задается строкой в конфиге: Code: AssignUserId site1 site1 В тоже время мы хотим, чтобы, используя web-шелл, нельзя было править файлы нашего проекта, кроме тех, на которыx стоят права o+w. Code: 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 Для этого в нашем конфиге мы будем писать: Code: AssignUserId www-data site1 Таким образом apache сможет прочитать index.php, выполнить и отдать в браузер, но не сможет изменить его. А tmp.txt изменить сможет. Важный момент - нужно запретить консоль у пользователя www-data Code: debian:~# usermod -s /bin/false www-data 2.3.2 Отдельный tmp для каждого сайта Предотвращаем инклуд сессий с соседнего сайта. + Запрещаем php выходить выше пользовательской домашней дирректории. В конфиг нашего сайта нужно добавить диррективы open_basedir, upload_tmp_dir, session.save_path Получаем такой минималистичный конфиг: Code: [B][COLOR=White]# file: /etc/apache2/sites-available/site1[/COLOR][/B] <VirtualHost *:80> 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" </VirtualHost> После создания конфига нужно сделать сайт активным с помощью команды: Code: debian:~# a2ensite site1 А затем перечитать конфиги: Code: debian:~# /etc/init.d/apache2 reload 2.3.3 Sendmail Почему я вынес Sendmail отдельным пунктом? Потому что по умолчанию он не работал. Пришлось повозится. Я расскажу самый простой способ. Чтобы php умел отправлять письма, проделываем следующие операции. Code: [B][COLOR=White]# file: /etc/php5/apacge2/php.ini [раскомментируем и изменим строку][/COLOR][/B] ++ sendmail_path = /usr/sbin/exim4 -t Для конфигурации Exim4 (по умолчанию в качестве Mail Transfer Agent используется именно он) существует пакет exim4-config. Воспользоваться им можно так: Code: debian:~# dpkg-reconfigure exim4-config После этого вам начнут задавать вопросы. На первый (Общий тип почтовой конфигурации) отвечаем: интернет-сайт; прием и отправка почты напрямую, используя SMTP А далее жмем Enter до конца настройки. Теперь все должно работать. 2.4 vsftpd Теперь разберемся с FTP. Для работы был выбран vsftpd. Code: debian:~# apt-get install vsftpd Далее меняем конфиг: Code: [B][COLOR=White]# file:/etc/vsftpd.conf[/COLOR][/B] 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 перечитать конфиги: Code: debian:~# /etc/init.d/vsftpd reload 2.5 MySQL + PostgreSQL Ставим MySQL Code: debian:~# apt-get install mysql-server phpmyadmin Создаем нового пользователя. Ставим Postgres Code: debian:~# apt-get install postgressql phppgadmin Меняем пароль на пользователя postgres: Code: debian:~# echo "\password" | sudo -u postgres psql Enter new password: Новый_пароль_postgres Enter it again: Новый_пароль_postgres После установки рутового пароля для пользователя postgres нам мнужно поправить конфиг. По умолчанию любой локальный пользователь может запустить psql с правами суперпользователя без ввода пароля. Исправляем. Code: [B][COLOR=White]#file /etc/postgresql/8.3/main/pg_hba.conf[/COLOR][/B] -- local all postgres ident sameuser -- local all all ident sameuser ++ local all postgres md5 ++ local all postgres md5 В /etc/phppgadmin/apache.conf открываем доступ извне. Code: order deny,allow deny from all allow from 127.0.0.0/255.0.0.0 ::1/128 # allow from all Меняем на: Code: order deny,allow # deny from all # allow from 127.0.0.0/255.0.0.0 ::1/128 allow from all Говорим apache перечитать конфиги: Code: debian:~# /etc/init.d/apache2 reload У постгрес есть один нюанс. Юзеры всегда видят названия соседних БД. Чтобы они не мозолили глаз нашим пользователям в phppgadmin, правим конфиг: Code: [B][COLOR=White]# file:/etc/phppgadmin/config.inc.php[/COLOR][/B] -- $conf['owned_only'] = false; ++ $conf['owned_only'] = true; Пользователи создаются такой командой: 2.6 Firewall В нашем случае цели просты - запретить злоумышленнику открывать порты. Поэтому решение будет простым - мы не будем вдаваться в нюансы правил iptables, а воспользуемся пакетом arno-iptables-firewall, который упростит нам жизнь. Он сам спросит нас, что мы хотим во время установки. Ответы на вопросы ниже. Code: 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. В тоже время в изолированную среду нужно брать все, что нужно для работы. Code: debian:~# apt-get install libapache2-mod-chroot debian:~# a2enmod mod_chroot debian:~# /etc/init.d/apache2 restart Вообще это тема отдельной большой статьи. С кучей своих проблем, связанных с тем, что помимо apache обычно требуется туева хуча дополнительных программ, библиотек и средств. Поэтому я не буду делать статью в статье, и отправлю Вас на отличную статью по этой теме: http://sudouser.com/zapusk-web-servera-apache2-v-srede-chroot-v-debian-i-ubuntu.html 2.7 [Домашнее задание] Автоматизация добавления новых пользователей В принципе в статье все команды писались так, чтобы их потом просто было запихнуть в sh скрипт. Думаю, что читатель без труда напишет скрипт с нужным именно ему функционалом.
не знаю как сейчас, но раньше в постгрессе по дефолту в конфиге стояла трастовая аутентификация для локальных юзеров. Т.е можно подключиться к бд без пароля с привилегиями любого юзера Подробнее http://developer.postgresql.org/pgdocs/postgres/auth-methods.html#AUTH-TRUST
strace (http://sourceforge.net/projects/strace/) вам в помощь Плюс есть такой инструментарий для помощи в создании chroot окружения. Хотелось бы узнать мнение знающих: http://olivier.sessink.nl/jailkit/
Внес изменения в пункты 2.3 Отдельные tmp & настройка sendmail 2.5 Postgres - закрыл возможность беспаролевого коннекта локальных пользователей + исправлены некоторые мелкие косяки, которые были найдены в ходе настройки сервера по инструкции. Что касается chroot'а. Как только заходит речь о chroot'е начинается какой-то геморой с коннектом к БД и php функцией mail(). Надеюсь, что в ближайшее время удастся разобраться.
А как домен прикрепить?? Я в панели управление доменом указал так- нс сервера - ип адрес ns1.domen.ru - ip1 ns2.domen.ru - ip2 где ip1 и ip2 это ип моего сервера. После чего в файле mcedit /etc/apache2/sites-available/default (Устанавливал я apache2) прописал Code: <VirtualHost domen.ru:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/localhost/www ServerName localhost ErrorLog /var/log/apache2/error.log CustomLog /var/log/apache2/access.log combined </VirtualHost> Но когда перехожу domen.ru, пишет сервер не отвечает, а когда перехожу по адресу ns1.domen.ru я попадаю на сервер, как это исправиьт и делаю ли я все правильно?