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

Discussion in 'Статьи' started by Neoveneficus, 14 Mar 2010.

  1. Neoveneficus

    Neoveneficus Elder - Старейшина

    Joined:
    10 Apr 2008
    Messages:
    235
    Likes Received:
    126
    Reputations:
    23
    Безопасная настройка виртуального хостинга 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 скрипт. Думаю, что читатель без труда напишет скрипт с нужным именно ему функционалом.
     
    #1 Neoveneficus, 14 Mar 2010
    Last edited: 15 Apr 2010
    19 people like this.
  2. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    не знаю как сейчас, но раньше в постгрессе по дефолту в конфиге стояла трастовая аутентификация для локальных юзеров. Т.е можно подключиться к бд без пароля с привилегиями любого юзера
    Подробнее
    http://developer.postgresql.org/pgdocs/postgres/auth-methods.html#AUTH-TRUST
     
    2 people like this.
  3. Neoveneficus

    Neoveneficus Elder - Старейшина

    Joined:
    10 Apr 2008
    Messages:
    235
    Likes Received:
    126
    Reputations:
    23
    Spyder
    Сейчас все по-прежнему. Допишу.
     
  4. Gifts

    Gifts Green member

    Joined:
    25 Apr 2008
    Messages:
    2,494
    Likes Received:
    807
    Reputations:
    614
    strace (http://sourceforge.net/projects/strace/) вам в помощь

    Плюс есть такой инструментарий для помощи в создании chroot окружения. Хотелось бы узнать мнение знающих: http://olivier.sessink.nl/jailkit/
     
    _________________________
    #4 Gifts, 15 Mar 2010
    Last edited: 15 Mar 2010
    1 person likes this.
  5. Neoveneficus

    Neoveneficus Elder - Старейшина

    Joined:
    10 Apr 2008
    Messages:
    235
    Likes Received:
    126
    Reputations:
    23
    Внес изменения в пункты

    2.3 Отдельные tmp & настройка sendmail
    2.5 Postgres - закрыл возможность беспаролевого коннекта локальных пользователей

    + исправлены некоторые мелкие косяки, которые были найдены в ходе настройки сервера по инструкции.

    Что касается chroot'а. Как только заходит речь о chroot'е начинается какой-то геморой с коннектом к БД и php функцией mail(). Надеюсь, что в ближайшее время удастся разобраться.
     
  6. Ins3t

    Ins3t Харьковчанин

    Joined:
    18 Jul 2009
    Messages:
    939
    Likes Received:
    429
    Reputations:
    139
    Вполне не плохо, но вот только:

    Это вроде как всем известно ;)
     
  7. RAINUR

    RAINUR New Member

    Joined:
    24 May 2010
    Messages:
    151
    Likes Received:
    0
    Reputations:
    0
    А как домен прикрепить?? Я в панели управление доменом указал так-
    нс сервера - ип адрес
    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 я попадаю на сервер, как это исправиьт и делаю ли я все правильно?