Форум твоего направления

Форум твоего направления (http://pcvector.ru/forum.php)
-   nginx (http://pcvector.ru/f152)
-   -   FAQ Создание собственного хостинга (http://pcvector.ru/t85)

Vector 22.06.2009 16:00

Создание собственного хостинга
 
Создание собственного хостинга или Сам Себе ISP

Процесс сетапа системы для массового виртуального вебхостинга.

Введение

Собственно говоря, только ленивый не писал на тему виртуального вебхостинга. Это хорошо. Плохо то, что бОльшая часть информации очень слабо структурирована и не имеет отношения к собственно высокопроизводительному, безопасному и массовому виртуальному вебхостингу.

В этой статье описано создание полностью рабочей системы "с нуля".

Задачи

- создать максимально производительный и в то же время безопасный вебхостинг

- позволить mod_php создавать файлы от имени пользователя, а не с правами вебсервера

- обезопасить пользователей друг от друга

- обезопасить систему от вторжения пользователей

- обезопасить систему от вторжения извне

Общая схема построения хостинга

В качестве вебсервера будем использовать Apache 1.3 с модулем mod_php и возможностью запуска cgi скриптов, как наиболее популярный среди вебмастеров. СУБД - MySQL 5.1.

Для "продвинутых" клиентов предоставим в пользование компилятор gcc. Не следует бояться давать пользователю доступ к компилятору - на правильно настроенной системе даже при наличии компилятора ничего сломать не получится. Мы строим именно правильно настроенную систему, поэтому в распоряжении пользователя будет весь комплекс программного обеспечения.

Чтобы снизить нагрузку на Apache, установим акселерирующий прокси-сервер. Из собственной многолетней практики, наиболее подходящим акселератором на данный момент является nginx - стабильный и качественный многофункциональный вебсервер/акселератор, разрабатываемый Игорем Сысоевым.

Таким образом, сначала запрос от пользователя поступает на акселератор nginx, который ожидает приема всех данных и проксирует данные на Apache только после полного его получения. Этим мы снижаем нагрузку на Apache, который каждый запрос обрабатывает в отдельном тяжеловесном процессе.

Для по-настоящему безопасной работы необходимо чтобы программы на площадке каждого клиента выполнялись от своего пользователя. Для CGI скриптов эта задача решается путем настройки suexec. Модуль PHP, который по определению является частью Apache, выполняется с правами пользователя, от которого запущен вебсервер. Есть альтернативный вариант с использованием suphp, однако это очень сильно грузит систему и потому такая схема для массового вебхостинга неприменима.

Мы выберем компромиссный вариант: PHP будет работать как модуль Apache, а безопасность обеспечим настройками файловой системы и модуля PHP.

Осталось решить последнюю проблему, а именно - создание файлов при работе mod_php с правами пользователя-владельца площадки, а не с правами вебсервера. Обратимся к руководству по команде mount(8) , из которого следует, что для наследования владельца при создании объектов внути каталога, необходимо замонтировать раздел с опцией suiddir.

Доступ по FTP следует предоставлять только через виртуальных пользователей. Это требование обусловлено тем, что пароли по протоколу FTP передаются в нешифрованном виде и их очень легко перехватить. Чтобы исключить возможность вторжения в систему по SSH, перехватив пароль для FTP и необходимы виртуальные пользователи - не существующие в системе, следовательно, бесполезные для потенциального взломщика.

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

+--------------+ http +-------------------+ http +--------+
пользователь | ---> | Акселератор nginx | ---> | Apache |
+--------------+      +-------------------+      +--------+
                                                  | 
                                                  |   +---------+    
                                                  |-> | 
mod_php | >-+--------------+
                                                  |   +---------+   | 
suiddir      |
                                                  |   +---------+   |              |
                                                  |-> |   
cgi   | >-|              |
                                                  |   +---------+   | 
Каталог      |
                                                  |   +---------+   | 
пользователя |
                                                  |-> |   
SSI   | >-|              |
                                                      +---------+   |              |
                                                                    |              |
+-----------------+ 
ssh   +-----------+  Пользователь               |              |
клиент хостинга | ----> | SSHD      | --------------------------> |              |
+-----------------+       +-----------+                             |              |
                                                                    |              |
+-----------------+ 
ftp   +-----------+  Виртуальный пользователь   |              |
клиент хостинга | ----> | Pure-FTPD | --------------------------> |              |
+-----------------+       +-----------+                             +--------------+ 

Помните, все сервисы, собранные в одном месте - не более чем тестовая машина. В реальной конфигурации, способной обслуживать тысячи запросов в секунду, сервер MySQL должен быть на отдельной машине. Это же касается и акселератора nginx. Попытка собрать все воедино на одном физическом сервере резко снизит скорость работы всего комплекса ПО из-за слишком высокой нагрузки на дисковую систему.

Первоначальная подготовка сервера

Конфигурация сервера: Intel(R) Xeon(TM) 3.0GHz / 2G RAM / Mirror SATA RAID (2 * 150G).

Операционная система: FreeBSD 6.2-STABLE SMP i386.

Диски:

PHP код:

/      - 400M
/tmp   2G
/home  85G
/var   - 40G
/usr   20G 

К сожалению, стандартные GENERIC и SMP ядра не позволяет монтировать файловые системы с SUIDDIR, а потому требуется пересборка. Также неплохо было бы поменять в сторону увеличения параметры, заведующие выделением разделяемой памяти и оперативной памяти на процесс. Создаем файл /usr/src/sys/i386/conf/SMP-stellar со следующим содержимым

PHP код:

include GENERIC

ident           SMP
-GENERIC-STELLAR

options         SMP
options         SUIDDIR

options         SYSVSHM
options         SYSVSEM
options         SYSVMSG
options         SHMMAXPGS
=65536
options         SEMMNI
=40
options         SEMMNS
=240
options         SEMUME
=40
options         SEMMNU
=120

options         MAXDSIZ
=(1024UL*1024*1024)
options         MAXSSIZ=(128UL*1024*1024)
options         DFLDSIZ=(1024UL*1024*1024

пересобираем ядро и перегружаемся:
PHP код:

cd /usr/src
make buildkernel KERNCONF
=SMP-stellar
make installkernel KERNCONF
=SMP-stellar
shutdown 
-r now 

После перезагрузки FreeBSD может монтировать файловые системы с опцией suiddir.

Изменяем файл /etc/fstab так, чтобы раздел /home монтировался с suiddir. Дополнительно отключаем запись времени последнего доступа к файлам; это дает некоторый выигрыш в производительности:

PHP код:

/dev/ar0s1g    /home   ufs     rw,suiddir,noatime              2       2 

Проверяем результат:

PHP код:

umount /home
mount 
/home
mount 
grep /home

/dev/ar0s1g on /home (ufslocalnoatimesuiddirsoft-updates

Сборка и настройка комплекса ПО

Перед установкой добавляем в /etc/make.conf

PHP код:

WITHOUT_X11=yes 

Устанавливаем MySQL. Собственно, здесь нет ничего экстраординарного:

PHP код:

cd /usr/ports/databases/mysql51-server
export WITH_CHARSET
=cp1251
export WITH_XCHARSET
=all
export BUILD_OPTIMIZED
=yes
make install clean 

После установки сервера указываем в /etc/rc.conf
PHP код:

#
# MySQL for virtual hosts
#
mysql_enable="YES" 

Записываем файл конфигурации MySQL /var/db/mysql/my.cnf:

PHP код:

[client]
port            3306
socket          
= /tmp/mysql.sock
default-character-set=cp1251

[mysqld]
bind-address    127.0.0.1
port            
3306
socket          
= /tmp/mysql.sock
skip
-character-set-client-handshake
default-character-set=cp1251
skip
-locking

key_buffer              
32M
max_allowed_packet      
16M
table_cache             
256
sort_buffer_size        
1M
read_buffer_size        
1M
read_rnd_buffer_size    
4M
myisam_sort_buffer_size 
64M
thread_cache_size       
8
query_cache_size        
16M
thread_concurrency      
8
max_connections         
128
max_user_connections    
126
log
-slow-queries
log
binlog_ignore_db        
mysql
expire_logs_days        
5
max_binlog_size         
400M
# Если нет необходимости в работе по сети, включаем опцию skip-networking
#skip-networking
log-bin                 mysql-bin
server
-id               1

[mysqldump]
quick
max_allowed_packet      
16M

[mysql]
no-auto-rehash

[isamchk]
key_buffer              128M
sort_buffer_size        
128M
read_buffer             
2M
write_buffer            
2M

[myisamchk]
key_buffer              128M
sort_buffer_size        
128M
read_buffer             
2M
write_buffer            
2M

[mysqlhotcopy]
interactive-timeout 

запускаем сервер

PHP код:

/usr/local/etc/rc.d/mysql-server start 

и проверяем, все ли работает нормально

PHP код:

ps axw grep mysql

  780 con
I      0:00.01 /bin/sh /usr/local/bin/mysqld_safe
     
--defaults-extra-file=/var/db/mysql/my.cnf --user=mysql --datadir=/var/db/mysql --pid-file=/v
  862 con
S    107:52.92 /usr/local/libexec/mysqld --defaults-extra-file=/var/db/mysql/my.cnf
     
--basedir=/usr/local --datadir=/var/db/mysql --pid-file=/va
 7861  p0  S
+     0:00.00 grep mysql 

Задаем пароль для MySQL root:

PHP код:

mysql -uroot

Welcome to the MySQL monitor
.  Commands end with ; or g.
Your MySQL connection id is 24356
Server version
5.1.15-beta-log FreeBSD portmysql-server-5.1.15

Type 
'help;' or '\h' for helpType '\c' to clear the buffer.

mysqlGRANT ALL ON *.* TO 'root'@'localhost' IDENTIFIED BY 'topsecret';
mysqlGRANT ALL ON *.* TO 'root'@'127.0.0.1' IDENTIFIED BY 'topsecret'

На этом установка MySQL окончена.

В качестве фронтэнда у нас будет работать вебсервер nginx, задача которого - проксировать HTTP запросы на сервер Apache. Это дает резкое снижение нагрузки из-за того, что nginx - мультиплексирующий сервер, способный обслуживать десятки тысяч одновременных подключений без порождения сотен дополнительных процессов или тредов. Схема выглядит следующим образом:

PHP код:

+------------+         +-------------------+         +-------------------+
посетитель | ------> | Внешний IPNGINX | ------> | 127.0.0.1Apache |
+------------+         +-------------------+         +-------------------+ 

При такой схеме все запросы, приходящие на Apache, будут иметь один и тот же адрес - адрес, на котором запущен nginx. Для того чтобы Apache воспринимал запросы с IP адресов посетителей, а не прокси nginx, необходимо дополнительно установить модуль mod_realip.

Итак, устанавливаем nginx:

PHP код:

cd /usr/ports/www/nginx
make install clean 

Устанавливаем Apache:

PHP код:

cd /usr/ports/www/apache13
export WITH_APACHE_SUEXEC
=yes
export APACHE_SUEXEC_LOG
=/var/log/apache/suexec_log
export APACHE_SUEXEC_USERDIR
=www
export APACHE_SUEXEC_DOCROOT
=/home/www
make install clean 

Устанавливаем mod_realip:

PHP код:

cd /usr/ports/www/mod_realip
make install clean 

На этом собственно установка вебсервера окончена. Следующий шаг - сборка php и mod_php. Из портов можно установить PHP4 или PHP5 - принципиальной разницы в технологии установки и конфигурирования нет, а потому будет описана только сборка mod_php5. Для нормальной работы с временными файлами (сессии, загрузка файлов и т.п.) требуется дополнительный патч, изменяющий права доступа с 0600 до 0660, чтобы вебсервер имел право записи в них. Патч доступен по адресу PHP4, patch-main::open_temporary_file.c.4 и PHP5, patch-main::open_temporary_file.c.5

PHP код:

cd /usr/ports/lang/php5
fetch http
://reki.ru/products/samag/PHPPatchset.tar.gz
tar -xzf PHPPatchset.tar.gz
mv PHPPatchset
/patch-main::open_temporary_file.c.5 files/
make install clean 

В появившемся меню указываем требуемые опции:

PHP код:

+--------------------------------------------------------------------+
¦                     Options for php5 5.2.1_3                       ¦
¦ 
+----------------------------------------------------------------+ ¦
¦ ¦  
[XCLI        Build CLI version                              ¦ ¦
¦ ¦  
[XCGI        Build CGI version                              ¦ ¦
¦ ¦  
[XAPACHE     Build Apache module                            ¦ ¦
¦ ¦  
[ ] DEBUG      Enable debug                                   ¦ ¦
¦ ¦  
[XSUHOSIN    Enable Suhosin protection system               ¦ ¦
¦ ¦  
[XMULTIBYTE  Enable zend multibyte support                  ¦ ¦
¦ ¦  
[ ] IPV6       Enable ipv6 support                            ¦ ¦
¦ ¦  
[ ] MAILHEAD   Enable mail header patch                       ¦ ¦
¦ ¦  
[XREDIRECT   Enable force-cgi-redirect support (CGI only)   ¦ ¦
¦ ¦  
[XDISCARD    Enable discard-path support (CGI only)         ¦ ¦
¦ ¦  
[ ] FASTCGI    Enable fastcgi support (CGI only)              ¦ ¦
¦ ¦  
[XPATHINFO   Enable path-info-check support (CGI only)      ¦ ¦
¦ ¦                                                                ¦ ¦
¦ ¦                                                                ¦ ¦
¦ ¦                                                                ¦ ¦
+-+----------------------------------------------------------------+-+
¦                       [  OK  ]       Cancel                        ¦
+--------------------------------------------------------------------+ 

проверить работоспособность установленного PHP можно командой echo "<? phpinfo(); ?>" | php

В выводе команды полностью отсутствуют упоминания о mysql, gd, iconv и прочих функциях. Что неудивительно, ибо в системе FreeBSD все дополнительные модули ставятся отдельно.

Чтобы установить необходимые модули можно воспользоваться двумя тактиками: поставить все за один раз, подав команды

PHP код:

cd /usr/ports/lang/php5-extensions
make install clean 

и выбрав необходимый набор модулей из меню.

Или - собрать каждый модуль по отдельности:

PHP код:

cd /usr/ports/www/php5-session
make install clean

cd 
/usr/ports/graphics/php5-gd
make install clean
...
и т.д

В случае необходимости можно дополнительно установить Zend Optimizer. Он также есть в портах FreeBSD (/usr/ports/devel/ZendOptimizer). Установка Zend не представляет никакой сложности; а сам продукт практически не нуждается в настройке.

По окончании установки, прописываем в файл /etc/rc.conf параметры для запуска nginx и Apache:

PHP код:

#
# Nginx Accelerator
#
nginx_enable="YES"

#
# Apache Backend
#
apache_enable="YES" 

Конфигурируем nginx (файл /usr/local/etc/nginx/nginx.conf):

PHP код:

user  www;
worker_processes  2;

pid         /var/run/nginx.pid;

events {
    
worker_connections  1024;
}

http {
    include       
mime.types;
    
default_type  application/octet-stream;

    
log_format  main  '$remote_addr - $remote_user [$time_local] $request '
                      '"$status" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
;

    
access_log         off;

    
sendfile           on;

    
keepalive_timeout  65;

    
gzip               on;

    
server {
        
listen       XXX.YYY.ZZZ.DDD:80;
        
server_name  localhost;

        
location /
        {
                
# Максимальный размер отдаваемого файла
                
client_max_body_size  20M;

                
# Адрес, на который будем проксировать
                
proxy_pass http://127.0.0.1:80;
                
proxy_redirect off;

                
proxy_set_header Host                 $host;
                
proxy_set_header X-Real-IP            $remote_addr;

                
proxy_connect_timeout 90;
                
proxy_send_timeout    90;
                
proxy_read_timeout    90;
                
proxy_send_lowat      12000;

                
proxy_buffer_size          4k;
                
proxy_buffers              4 32k;
                
proxy_busy_buffers_size    64k;
                
proxy_temp_file_write_size 64k;
                
proxy_temp_path            /var/tmp/nginx;
       }
    }


Конфигурируем Apache(файл /usr/local/etc/apache/httpd.conf):

PHP код:

LoadModule realip_module      libexec/apache/mod_realip.so

ServerName 127.0.0.1

Listen 127.0.0.1
:80

RealIP  localhost on

<Directory /home/www/*/*/www>
        
AllowOverride All
        Options 
+Indexes +ExecCGI FollowSymLinks
        DirectoryIndex index
.php index.html index.htm
</Directory>
<
Directory /home/www/*/*/cgi>
        
AllowOverride All
        Options 
-Indexes +ExecCGI FollowSymLinks
        DirectoryIndex index
.cgi index.html index.htm index.cgi
</Directory>

NameVirtualHost 127.0.0.1:80 

Запускаем nginx и Apache:

PHP код:

/usr/local/etc/rc.d/nginx start
/usr/local/etc/rc.d/apache.sh start 

Проверяем, все ли работает так, как надо:

PHP код:

ps axw grep nginx

 3803  
??  Is     0:00.00 nginxmaster process /usr/local/sbin/nginx
 3804  
??  S      0:22.79 nginxworker process (nginx)
 
3805  ??  S      0:22.31 nginxworker process (nginx)
 
8128  p0  D+     0:00.00 grep nginx

ps axw 
grep httpd
 1363  
??  Ss     0:03.24 /usr/local/sbin/httpd
 8124  
??  S      0:01.83 /usr/local/sbin/httpd
 8125  
??  R      0:01.16 /usr/local/sbin/httpd
 8126  
??  S      0:01.20 /usr/local/sbin/httpd
 8129  
??  S      0:01.16 /usr/local/sbin/httpd
 8130  
??  S      0:01.08 /usr/local/sbin/httpd
 8131  
??  S      0:01.23 /usr/local/sbin/httpd
 8132  
??  S      0:01.27 /usr/local/sbin/httpd 

Для FTP доступа установим сервер pure-ftpd. Pure-ftpd - один из самых надежных и одновременно удобных FTP серверов, зарекомендовавший себя великолепной работой на протяжении многих лет.

PHP код:

cd /usr/ports/ftp/pure-ftpd
make install clean 


Vector 22.06.2009 16:01

Указываем, что собирать сервер следует с поддержкой СУБД PostgreSQL, в которой будут храниться виртуальные пользователи. Выбор базы данных зависит от используемой системы управления хостингом. В нашем случае она построена на основе собственной разработки, базирующейся на СУБД PostgreSQL.

PHP код:

+--------------------------------------------------------------------+
¦                  Options for pure-ftpd 1.0.21_1                    ¦
¦ 
+----------------------------------------------------------------+ ¦
¦ ¦
[ ] LDAP           Support for users in LDAP directories        ¦ ¦
¦ ¦
[ ] MYSQL          Support for users in MySQL database          ¦ ¦
¦ ¦
[ ] PAM            Support for PAM authentication               ¦ ¦
¦ ¦
[XPGSQL          Support for users in PostgreSQL database     ¦ ¦
¦ ¦
[XPRIVSEP        Enable privilege separation                  ¦ ¦
¦ ¦
[XPERUSERLIMITS  Per-user concurrency limits                  ¦ ¦
¦ ¦
[XTHROTTLING     Bandwidth throttling                         ¦ ¦
¦ ¦
[XBANNER         Show pure-ftpd welcome upon session start    ¦ ¦
¦ ¦
[XUPLOADSCRIPT   Support uploadscript daemon                  ¦ ¦
¦ ¦
[ ] UTF8           Support for charset conversion (expreimental)¦ ¦
¦ ¦
[XSENDFILE       Support for the sendfile syscall             ¦ ¦
¦ ¦                                                                ¦ ¦
¦ ¦                                                                ¦ ¦
¦ ¦                                                                ¦ ¦
¦ ¦                                                                ¦ ¦
+-+----------------------------------------------------------------+-+
¦                       [  OK  ]       Cancel                        ¦
+--------------------------------------------------------------------+ 

При выборе установки с PostgreSQL, автоматически поставятся порты databases/postgresql82-client и databases/postgresql82-server После установки добавляем в файл /etc/rc.conf строчки

PHP код:

#
# BILLING DATABASE
#
postgresql_enable="YES" 

меняем домашний каталог для пользователя pgsql на /var/db/pgsql

PHP код:

mkdir /var/db/pgsql
chown pgsql
:pgsql /var/db/pgsql
chmod 0700 
/var/db/pgsql
pw usermod pgsql 
-/var/db/pgsql 

и инициализируем базу данных:

PHP код:

su pgsql
initdb 
--encoding=UTF8 --locale=ru_RU.UTF---pgdata=/var/db/pgsql/data

  The files belonging to this database system will be owned by user 
"pgsql".
  
This user must also own the server process.

  
The database cluster will be initialized with locale ru_RU.UTF-8.
...... 

конфигурируем файл /var/db/pgsql/data/postgresql.conf:

PHP код:

max_connections 150
shared_buffers 
40MB
max_fsm_pages 
76800
log_destination 
'syslog'
silent_mode on
autovacuum 
on
datestyle 
'iso, dmy'
lc_messages 'ru_RU.UTF-8'
lc_monetary 'ru_RU.UTF-8'
lc_numeric 'ru_RU.UTF-8'
lc_time 'ru_RU.UTF-8' 

файл прав доступа к базе данных /var/db/pgsql/data/pg_hba.conf

PHP код:

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
# "local" is for Unix domain socket connections only
local   all         all                               md5
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5
# IPv6 local connections:
host    all         all         ::1/128               md5 

и запускаем сервер PostgreSQL

PHP код:

/usr/local/etc/rc.d/postgresql start 

Проверяем работу:

PHP код:

ps axw grep postgres

  749  
??  Ss     0:05.39 /usr/local/bin/postgres -/var/db/pgsql/data
  751  
??  Ss     0:08.97 postgreswriter process    (postgres)
  
752  ??  Ss     0:00.64 postgresstats collector process    (postgres

Конфигурируем Pure-FTPD (/usr/local/etc/pure-ftpd.conf)

PHP код:

ChrootEveryone              yes
BrokenClientsCompatibility  no
MaxClientsNumber            50
Daemonize                   yes
MaxClientsPerIP             8
VerboseLog                  no
DisplayDotFiles             yes
AnonymousOnly               no
NoAnonymous                 yes
SyslogFacility              ftp
DontResolve                 yes
MaxIdleTime                 15
PGSQLConfigFile             
/usr/local/etc/pureftpd-pgsql.conf
LimitRecursion              2000 8
AnonymousCanCreateDirs      no
MaxLoad                     4
AntiWarez                   yes
Umask                       110
:007
MinUID                      100
AllowUserFXP                no
AllowAnonymousFXP           no
ProhibitDotFilesWrite       no
ProhibitDotFilesRead        no
AutoRename                  no
AnonymousCantUpload         no
MaxDiskUsage                99
CustomerProof               yes 

Указываем, откуда брать информацию о виртуальных пользователях (/usr/local/etc/pureftpd-pgsql.conf).

PHP код:

PGSQLServer     127.0.0.1
PGSQLPort       5432
PGSQLUser       pureftpd
PGSQLPassword   topsecret
PGSQLDatabase   billing
PGSQLCrypt      cleartext
PGSQLGetPW      SELECT passwd   FROM ftp
.ftpusers WHERE ftpuser='\L' AND enabled 1;
PGSQLGetUID     SELECT user_id  FROM ftp.ftpusers WHERE ftpuser='\L' AND enabled 1;
PGSQLGetGID     SELECT group_id FROM ftp.ftpusers WHERE ftpuser='\L' AND enabled 1;
PGSQLGetDir     SELECT homedir  FROM ftp.ftpusers WHERE ftpuser='\L' AND enabled 1

Создаем таблицу пользователей в СУБД PostgreSQL:

PHP код:

psql -U pgsql

CREATE USER billing WITH PASSWORD 
'supersecret' NOCREATEDB NOCREATEUSER;
CREATE DATABASE billing WITH ENCODING='UTF8' OWNER=billing;
CREATE SCHEMA ftp;
CREATE TABLE ftp.ftpusers
(
       
ftpuser   VARCHAR(255NOT NULL CHECK (LENGTH(ftpuser) > 0),
       
passwd    VARCHAR(255NOT NULL CHECK (LENGTH(passwd) > 0),
       
user_id   INT NOT NULL DEFAULT '-1',
       
group_id  INT NOT NULL DEFAULT '-1',
       
homedir   VARCHAR(255NOT NULL CHECK (LENGTH(homedir) > 0),
       
expires   bigint not null default '-1',
       
enabled   bigint not null default '0',
       
descr     text,
       
CONSTRAINT ftpusers_pk PRIMARY KEY (ftpuser)
WITHOUT OIDS;

CREATE USER pureftpd WITH PASSWORD 'topsecret' NOCREATEDB NOCREATEUSER;
GRANT USAGE  ON SCHEMA  ftp        TO pureftpd;
GRANT SELECT ON ftp.ftpusers       TO pureftpd

Продолжение - во второй части статьи

Во второй части мы проведем предварительный аудит безопасности системы, рассмотрим создание пользователей хостинга, вопросы нагрузочного тестирования полученного комплекса ПО, аудит системы во время работы и тонкости, связанные с работой некоторых модулей PHP.

Vector 22.06.2009 18:25

Создание собственного хостинга продолжение
 
Создание собственного хостинга продолжение

Введение

В предыдущей статье была описана общая схема вебхостинга, первоначальная подготовка сервера к настройке, установка необходимого программного обеспечения и его минимальная настройка.

В этой части статьи мы рассмотрим следующие вопросы:

- создание системы домашних каталогов пользователей

- отделение пользователей друг от друга и от системы

- настройка производительности системы

Общие концепции

Как уже упоминалось в предыдущей статье, мы разделяем типы пользователей. То есть, у нас есть отдельный пользователь c отдельным паролем для доступа к СУБД, FTP и для работы в шелле по SSH.

Чтобы не возникало неразберихи, следует как-то систематизировать все создаваемые сущности. Хорошим и проверенным методом является следующий: все пользователи данной техплощадки имеют один и тот же префикс в виде имени площадки. Пример: u00000, где u - сокращение от "user", а 00000 - порядковый номер площадки по базе данных.

То есть, для площадки с номером 12345 у нас будут следующие реквизиты:

PHP код:

 /home/www/u12345 каталог с сайтаминапример /home/www/u12345/somesite.ru
 u12345 
имя пользователя для работы по SSH и FTP
 u12345
.ftp.ourhosting.ru название хоста для доступа на техплощадку по FTP
 u12345
.ssh.ourhosting.ru название хоста для доступа на техплощадку по SSH
 u12345 
имя пользователя для работы c базой данных
 u12345 
собственно база данных
 и
 u12345
.mysql.ourhosting.ru имя хостана котором расположена БД 

Разумеется, у нашего хостинга должны быть настроены зоны DNS так, чтобы при запросе имен хостов отдавались правильные IP адреса.

Небольшое отступление. Очень плохая практика называть пользователей значимыми именами, например "alex" или "somesite_ru": это очень неудобно с точки зрения организации биллинга, системы резервного копирования и миграции данных между машинами, заставляет каждый раз придумывать новые имена, а самое главное - при наличии достаточного количества клиентов приводит к повторениям и дальнейшей путанице.

Профиль пользователя

На сегодняшний день реалии таковы, что большая часть сайтов имеют кодировку utf-8. Применительно к вопросу вебхостинга это означает что вся локализация консоли, вебсервера и сервера базы данных должна быть ru_RU.CP1251. Для локализации консоли необходимо создать дополнительный класс russianwww в файле /etc/login.conf:

PHP код:

#
# Russian Web Users Accounts. Setup proper environment variables.
#
russianwww|Russian Users Accounts:
        :
charset=CP1251:
        :
lang=ru_RU.CP1251:
        :
umask=0007:
        :
tc=default: 

Если мы хотим ограничить пользователя в системных ресурсах, а возникают ситуациии когда это единственный способ одновременно уместить много требовательных к ресурсам сайтов на одном сервере без передёргивания всего "одеяла" на кого либо одного можно добавить в созданный класс строки вида:

PHP код:

        :cputime=5m:
        :
datasize=32M:
        :
stacksize=4M:
        :
memorylocked=64M:
        :
memoryuse=96M:
        :
filesize=unlimited:
        :
coredumpsize=0:
        :
openfiles=256:
        :
maxproc=128:
        :
sbsize=unlimited:
        :
vmemoryuse=unlimited:
        :
priority=20:
        :
ignoretime@: 

Их необходимо вставить перед :tc=default: предложенные значения даны в иллюстративных целях и в Вашей системе могут быть другими и перед их установкой рекомендуется ознакомиться со страницей справочника man login.conf(5). После необходимых правок /etc/login.conf, пересоздаем базу данных:

PHP код:

cap_mkdb /etc/login.conf 

Для локализации Apache придется изменить файл /usr/local/sbin/apachectl внеся в него следующие строки:

PHP код:

#!/bin/sh
# Localization
umask 0002
LC_ALL
=ru_RU.CP1251export LC_ALL
LANG
=ru_RU.CP1251export LANG
MM_CHARSET
=CP1251export MM_CHARSET 

Чтобы локализация "подхватывалась" при автозапуске, следует заменить скрипт /usr/local/etc/rc.d/apache на предлагаемый:

PHP код:

#!/bin/sh

case "$1" in
start
)
        [ -
/usr/local/sbin/apachectl ] && /usr/local/sbin/apachectl start > /dev/null && echo -' apache'
        
;;
stop)
        [ -
/var/run/httpd.pid ] && /usr/local/sbin/apachectl stop > /dev/null && echo -' apache'
        
;;
*)
        echo 
"Usage: ${0##*/} { start | stop }" >&2
        
exit 64
        ;;
esac

exit 0 
END__VBULLETIN__CODE__SNIPPET 
?>

Для сервера MySQL достаточно будет создавать пользовательские базы данных с кодировкой cp1251 и cp1251_general_ci collation:

PHP код:

CREATE DATABASE `u00001` DEFAULT CHARACTER SET cp1251 COLLATE cp1251_general_ci

Система каталогов пользователей

Как уже было описано в предыдущей статье, пользователи виртуального хостинга размещаются на отдельном разделе /home в каталоге www. Если с течением времени место в /home/www закончится, мы сможем установить в сервер дополнительный физический диск и смонтировать его в /home/www1. При этом общая схема работы хостинга не изменится и дополнительная настройка не понадобится.

Для того чтобы пользователи не имели доступа к "чужим" даныым необходимо правильно выставить права и владельцев каталогов. Такая настройка - очень важный момент, поэтому остановимся на ней подробнее.

Итак, пользователи не должны иметь доступ к каталогам друг друга, но при этом надо позаботиться о доступности этих данных вебсерверу. К счастью, механизм UNIX permissions позволяет решить эту проблему: мы создадим специальную группу в которую будут входить пользователи вебхостинга и пользователь, от которого запущен вебсервер Apache

PHP код:

pw groupadd virtwww -M www 

Создаем каталоги:

PHP код:

mkdir -/home/www
chown root
:wheel /home/www 

Права на каталог /home/www должны быть 0711, чтобы нельзя было получить список файлов/каталогов внутри. Пользователи могут войти в каталог, но не могут получить листинг.

Создаем пользователя нашего вебхостинга:

PHP код:

pw useradd u00001 -g virtwww -/home/www/u00001 -/usr/local/bin/bash -L russianwww -m
pw groupadd u00001 
-M u00001 

Таким образом, каждый пользователь имеет две группы: первичную - virtwww и дополнительную, совпадающую по имени с именем пользователя.

Устанавливаем права на домашний каталог пользователя:

PHP код:

chmod 04710 /home/www/u00001 
chown u00001
:www /home/www/u00001 

При таких правах на каталог никто кроме пользователя u00001 и вебсервера не будет иметь доступа к данным пользователя, а созданные внутри файлы и каталоги будут наследовать ID и GID владельца.

Для хранения лог-файлов мы выберем каталог /var/log/apache.

Именно здесь нам потребуется введенная дополнительно группа у пользователя хостинга: при помощи нее мы выдадим права на просмотр лог-файлов.

Создаем каталог, в котором будут храниться лог-файлы:

PHP код:

mkdir -/var/log/apache
chmod 0711 
/var/log/apache
chown root
:wheel /var/log/apache

mkdir 
/var/log/apache/u00001
chmod 0750 
/var/log/apache/u00001
chown root
:u00001 /var/log/apache/u00001 

Теперь осталось расписать процедуру заведения виртуального хоста для пользователя. Сделаем это на примере сайта example.ru:

1) Создаем каталоги

PHP код:

mkdir -/home/www/u00001/example.ru/{www,cgi,tmp}

chown -R u00001:virtwww /home/www/u00001/example.ru
chmod 
-R 04770 /home/www/u00001/example.ru
chmod 0710 
/home/www/u00001/example.ru/cgi

mkdir 
/var/log/apache/u00001/example.ru
chmod 0750 
/var/log/apache/u00001/example.ru 

2) Прописываем конфигурацию для Apache

PHP код:

<VirtualHost 127.0.0.1:80>
        
ServerName example.ru
        ServerAlias www
.example.ru

        DocumentRoot 
/home/www/u00001/example.ru/www
        ScriptAlias  
/cgi /home/www/u00001/example.ru/cgi

        ErrorLog     
/var/log/apache/u00001/example.ru/error_log
        TransferLog  
/var/log/apache/u00001/example.ru/access_log

        php_admin_value upload_tmp_dir 
/home/www/u00001/example.ru/tmp
        php_admin_value doc_root       
/home/www/u00001/example.ru
        php_admin_value user_dir       www
        php_admin_value open_basedir   
/home/www/u00001:/usr/local/share/smarty:/usr/local/share/pear
        php_admin_value session
.save_path "0;0660;/home/www/u00001/example.ru/tmp"

        
User u00001
        Group virtwww
</VirtualHost

Обратите внимание на значение переменной session.save_path. В ней требуется указать права 0660.

3) Проверяем конфигурацию Apache:

PHP код:

/usr/local/sbin/apachectl configtest

Syntax OK 

4) Перезапускаем Apache и проверяем работу системы:

PHP код:

/usr/local/sbin/apachectl restart

echo "<? phpinfo(); ?>" > /home/www/u00001/example.ru/www/test.php
fetch http://example.ru/test.html

test.php                                         34 kB   13 MBps

rm /home/www/u00001/example.ru/www/test.php

5) Заводим FTP доступ для пользвателя Поскольку всех FTP пользователей мы храним в БД, вся процедура создания доступа по FTP сводится к созданию ровно одной записи:

PHP код:

INSERT INTO ftp.ftpusers VALUES('u00001''topsecret',  '1001''1000''/home/www/u00001'01''); 

где 1001 - UID пользователя, а 1000 - GID группы virtwww Проверяем доступ по FTP:

PHP код:

ftp localhost

Trying 
::1...
Connected to localhost.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 1 of 50 allowed.
220-Local time is now 01:58. Server port21.
220
-This is a private system No anonymous login
220 You will be disconnected after 15 minutes of inactivity
.
Name (localhost:stellar): u00001
331 User u00001 OK
Password required
Password
:
230-User u00001 has group access to:  u00001   virtwww
230 OK
Current restricted directory is /
Remote system type is UNIX.
Using binary mode to transfer files.
ftpquit
221
-GoodbyeYou uploaded 0 and downloaded 0 kbytes.
221 Logout

Для автоматизации создания пользователей можно воспользоваться скриптом, доступным по адресу http://www.reki.ru/products/webhosting/addftpuser

Vector 22.06.2009 18:27

Настройка параметров системы

Настройка параметров системы преследует две цели. Первая цель: повысить уровень безопасности путем изоляции пользователей друг от друга и от системы и вторая - достичь оптимальной производительности хостинга.

Для изоляции клиентов хостинга на уровне файловой системы мы воспользовались системой unix permissions. Теперь необходимо изолировать клиентов на уровне доступа к списку процессов, используемых ресурсов и т.п. Для этого в файл /etc/sysctl.conf вносим строчку

PHP код:

security.bsd.see_other_uids=

и перечитываем конфигурацию /etc/rc.d/sysctl restart.

Для того чтобы при падении программ система писала core-файлы в один каталог, а не во всю файловую систему, также добавляем строчки

PHP код:

kern.sugid_coredump=0
kern
.corefile=/var/tmp/%N.core 

Для оптимизации работы системы пропишем следующие параметры:

PHP код:

kern.ipc.maxsockbuf=16777216
net
.inet.tcp.rfc1323=1
net
.inet.tcp.sendspace=1048576
net
.inet.tcp.recvspace=1048576
net
.inet.tcp.sack.enable=1

kern
.maxfiles=204800
kern
.maxfilesperproc=200000

net
.inet.ip.portrange.first=1024
net
.inet.ip.portrange.last=65535

net
.inet.ip.portrange.randomized=0

net
.inet.tcp.nolocaltimewait=1

kern
.ipc.shmmax=268435456 

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

Выводы

Разумеется, это - всего лишь прототип реального хостинга и при количестве клиентов до нескольких сотен будет работать в предлагаемой конфигурации. Для развертывания системы в эксплуатацию с несколькими тысячами пользователей необходимо, как минимум, разнести вебсервер и сервер БД, а для биллинга выделить отдельную машину. Также следует рассмотреть вопросы организации резервных копий (backup), систему миграции пользователей между серверами хостнговой площадки, а также - систему миниторинга пользовательской активности.

Vector 22.06.2009 18:31

Создание собственного хостинга, faq
 
Создание собственного хостинга, FAQ

Настройка PHP

Q: Как увеличить скорость работы PHP?

A: Установить в систему eAccelerator или ZendOptimizer, обычно, это не представляет сложностей. На FreeBSD делается так:

1) eAccelerator:

PHP код:

cd /usr/ports/www/eaccelerator
make install clean 

2) Zend Optimizer:

PHP код:

cd /usr/ports/devel/ZendOptimizer
make install clean 

После установки придется в php.ini добавить для eAccelerator строчку с полным путем до файла eaccelerator.so:

PHP код:

zend_extension=/usr/local/lib/php/20060613/eaccelerator.so 

а для Zend Optimizer - строчки

PHP код:

[Zend]
zend_optimizer.optimization_level=15
zend_extension_manager
.optimizer="/usr/local/lib/php/20060613/Optimizer"
zend_extension_manager.optimizer_ts="/usr/local/lib/php/20060613/Optimizer_TS"
zend_extension="/usr/local/lib/php20060613/ZendExtensionManager.so"
zend_extension_ts="/usr/local/lib/php/20060613/ZendExtensionManager_TS.so" 

Q: При использовании eAccelerator, он постоянно пишет в лог строчки EACCELERATOR hit: "/home/www/u00001/example.com/www/index.php", это занимает слишеом много места, как отключить?

A: Прописать eaccelerator.debug = 0 и перезапустить apache

Q: Я настроил все так, как написано в статье, но сессии не работают!

A: Скорее всего, указана неверная umask в стартовых скриптах. Проверить это можно запустив скрипт <?php echo umask(); ?>. Если выведется '2', значит, umask прописана неверно. Внимательно изучите содержимое файлов /usr/local/sbin/apachectl и /usr/local/etc/rc.d/apache.sh. Во второй строке в них должна быть надпись umask 0022.

Q: Pure-ftpd не пускает пользователей!

A: ВНИМАТЕЛЬНО проверьте права и владельца пользовательского каталога.


Часовой пояс GMT +3, время: 20:36.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd. Перевод:
zCarot
Copyright © 2009 - 2014, pcvector.ru

.