ISPmanager и selinux

Материал из ISPWiki

Перейти к: навигация, поиск

Содержание

Используемое программное обеспечение

  • Centos 5.3
  • ISPmanager-Pro 4.3.32. - .34

Вступление

После некоторой пляски удалось их подружить, обеспечив тем самым неплохую изоляцию клиентского хостинга от сервера. Если за счет дыры в скриптах пользовательских сайтов злоумышленник сможет запихать на сервер эксплойт, и даже повысить привилегии до рута - все равно он останется в контексте вебсервера и будет сильно ограничен в своих действиях.
Основная идея, которая легла в основу метода: надо поднять два httpd, один для ispmgr, другой для клиентов хостинга. В качестве побочного эффекта - очень полезная фича: возможные ошибки в конфиге клиентского апача не пытаются уронить ispmanager. Клиентский апач работает в стандартном контексте selinux, а для апача ispmgr написан модуль, который запускает его в unconfined_c, тем самым фактически отключая для него selinux.


Создание модуля selinux для ispmgr

Эти действия можно (и желательно) делать не на той машине, где будет развернут хостинг. Для сборки модуля требуется та же версия дистрибутива, что будет стоять на хостинге. Если действия будут выполняться на той же машине, что и хостинг, то предварительно потребуется включить selinux и восстановить атрибуты (см следующее сообщение).

 yum install selinux-policy-devel.noarch  policycoreutils
 mkdir ~/policy
 cd ~/policy

Cоздаем в этом каталоге следующие файлы: ispmgr.fc ispmgr.if ispmgr.te

ispmgr.fc

 /usr/sbin/httpd_ispmgr  --      gen_context(system_u:object_r:ispmgr_exec_t,s0)
 /usr/sbin/httpd_ispmgr.worker   --      gen_context(system_u:object_r:ispmgr_exec_t,s0)


ispmgr.if

########################################
## <summary>
##      Execute a domain transition to run ispmgr.
## </summary> 
interface(`ispmgr_domtrans',`
       gen_require(`
               type ispmgr_t, ispmgr_exec_t;
       ')
       domain_auto_trans($1,ispmgr_exec_t,unconfined_t)
       allow $1 ispmgr_t:fd use;
       allow ispmgr_t $1:fd use;
       allow $1 ispmgr_t:fifo_file rw_file_perms;
       allow $1 ispmgr_t:process sigchld;
')


ispmgr.te

 policy_module(ispmgr,1.0.5)

 type ispmgr_t;
 type ispmgr_exec_t;
 require {
       type initrc_t;
       type unconfined_t;
 }
 domain_type(ispmgr_t)
 domain_entry_file(ispmgr_t, ispmgr_exec_t)
 ispmgr_domtrans(initrc_t)

Компиляция

Выполняем команду make

 make -f /usr/share/selinux/devel/Makefile
 Compiling targeted ispmgr module
 /usr/bin/checkmodule:  loading policy configuration from tmp/ispmgr.tmp
 /usr/bin/checkmodule:  policy configuration loaded
 /usr/bin/checkmodule:  writing binary representation (version 6) to tmp/ispmgr.mod
 Creating targeted ispmgr.pp policy package
 rm tmp/ispmgr.mod.fc tmp/ispmgr.mod

Загрузка модуля

Если все прошло успешно, должен появиться файл ispmgr.pp Если что-то пошло не так, перед повторным запуском make удаляем подкаталог tmp и файл ispmgr.pp

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

 semodule -i ispmgr.pp
 semodule -l

Если мы собирали модуль там же, где развернут хостинг, то удаляем пакет selinux-policy-devel.noarch

Активация selinux и установка модуля

Дальнейшие действия выполняются на машинах с развернутым ispmgr

Включаем selinux в режим permissive и восстанавливаем атрибуты файлов, т.к. инсталляция ispmgr при выключенном selinux их не устанавливала

В /etc/selinux/config прописываем SELINUX=permissive

 touch /.autorelabel
 shutdown -rf now

Перезагрузка займет значительное время, которое зависит от количества файлов на диске.

 yum install policycoreutils

Если мы собирали модуль не на той машине, где будет развернут хостинг, копируем модуль ispmgr.pp, загружаем его и убеждаемся в наличии модуля:

 semodule -i ispmgr.pp
 semodule -l


Создание клона httpd

 cp -ax /usr/sbin/httpd /usr/sbin/httpd_ispmgr
 cp -ax /usr/sbin/httpd.worker /usr/sbin/httpd_ispmgr.worker

Устанавливаем контекст и убеждаемся, что это именно ispmgr_exec_t

 restorecon -F /usr/sbin/httpd_ispmgr /usr/sbin/httpd_ispmgr.worker
 ls -lZ /usr/sbin/httpd_ispmgr /usr/sbin/httpd_ispmgr.worker

Если контекст будет иным, разбираемся, что с нашим ispmgr.pp
Разбираемся с логами:

 mkdir /var/log/httpd_ispmgr
 chmod 700 /var/log/httpd_ispmgr
 cd /etc/httpd
 ln -s ../../var/log/httpd_ispmgr  logs_ispmgr

Далее клонируем конфиги, каталоги и стартап-скрипты. Я буду приводить отличия от оригинала. cp -ax /usr/sbin/apachectl /usr/sbin/apachectl_ispmgr

diff -u /usr/sbin/apachectl /usr/sbin/apachectl_ispmgr

 --- /usr/sbin/apachectl 2009-07-14 14:03:18.000000000 +0400
 +++ /usr/sbin/apachectl_ispmgr  2009-10-19 07:34:44.000000000 +0400
 @@ -41,7 +41,7 @@
  # --------------------                              --------------------
  #
  # the path to your httpd binary, including options if necessary
 -HTTPD='/usr/sbin/httpd'
 +HTTPD='/usr/sbin/httpd_ispmgr'
  #
  #
  # a command that outputs a formatted text version of the HTML at the
 @@ -58,8 +58,8 @@
  STATUSURL="http://localhost:80/server-status"
  # Source /etc/sysconfig/httpd for $HTTPD setting, etc.
 -if [ -r /etc/sysconfig/httpd ]; then
 -   . /etc/sysconfig/httpd
 +if [ -r /etc/sysconfig/httpd_ispmgr ]; then
 +   . /etc/sysconfig/httpd_ispmgr
  fi
  #

При желании в обоих приведенных выше файлах стоит подправить строку STATUSURL="http://localhost:80/server-status" в соответствии с реалиями каждого из серверов.

cp -ax /etc/rc.d/init.d/httpd /etc/rc.d/init.d/httpd_ispmgr

diff -u /etc/rc.d/init.d/httpd /etc/rc.d/init.d/httpd_ispmgr

 --- /etc/rc.d/init.d/httpd      2009-07-14 14:08:09.000000000 +0400                                   
 +++ /etc/rc.d/init.d/httpd_ispmgr       2009-10-19 07:18:30.000000000 +0400                           
 @@ -5,16 +5,16 @@                                                                                     
  # chkconfig: - 85 15                                                                                 
  # description: Apache is a World Wide Web server.  It is used to serve \                             
  #             HTML files and CGI.                                                                    
 -# processname: httpd                                                                                 
 -# config: /etc/httpd/conf/httpd.conf                                                                 
 -# config: /etc/sysconfig/httpd                                                                       
 -# pidfile: /var/run/httpd.pid                                                                        
 +# processname: httpd_ispmgr                                                                          
 +# config: /etc/httpd/conf/httpd_ispmgr.conf                                                          
 +# config: /etc/sysconfig/httpd_ispmgr
 +# pidfile: /var/run/httpd_ispmgr.pid
  # Source function library.
  . /etc/rc.d/init.d/functions
 -if [ -f /etc/sysconfig/httpd ]; then
 -        . /etc/sysconfig/httpd
 +if [ -f /etc/sysconfig/httpd_ispmgr ]; then
 +        . /etc/sysconfig/httpd_ispmgr
  fi
  # Start httpd in the C locale by default.
 @@ -30,15 +30,15 @@
  # Path to the apachectl script, server binary, and short-form for messages.
  apachectl=/usr/sbin/apachectl
 -httpd=${HTTPD-/usr/sbin/httpd}
 -prog=httpd
 -pidfile=${PIDFILE-/var/run/httpd.pid}
 -lockfile=${LOCKFILE-/var/lock/subsys/httpd}
 +httpd=${HTTPD-/usr/sbin/httpd_ispmgr}
 +prog=httpd_ispmgr
 +pidfile=${PIDFILE-/var/run/httpd_ispmgr.pid}
 +lockfile=${LOCKFILE-/var/lock/subsys/httpd_ispmgr}
  RETVAL=0
  # check for 1.3 configuration
  check13 () {
 -       CONFFILE=/etc/httpd/conf/httpd.conf
 +       CONFFILE=/etc/httpd/conf/httpd_ispmgr.conf
       GONE="(ServerType|BindAddress|Port|AddModule|ClearModuleList|"
       GONE="${GONE}AgentLog|RefererLog|RefererIgnore|FancyIndexing|"
       GONE="${GONE}AccessConfig|ResourceConfig)"


cp -ax /etc/sysconfig/httpd /etc/sysconfig/httpd_ispmgr

diff -u /etc/sysconfig/httpd /etc/sysconfig/httpd_ispmgr

 --- /etc/sysconfig/httpd        2009-07-14 14:08:09.000000000 +0400
 +++ /etc/sysconfig/httpd_ispmgr 2009-10-19 07:39:15.000000000 +0400
 @@ -6,13 +6,13 @@
  # available, but does not work with some modules (such as PHP).
  # The service must be stopped before changing this variable.
  #
 -#HTTPD=/usr/sbin/httpd.worker
 +#HTTPD=/usr/sbin/httpd_ispmgr.worker
  #
  # To pass additional options (for instance, -D definitions) to the
  # httpd binary at startup, set OPTIONS here.
  #
 -#OPTIONS=
 +OPTIONS="-f conf/httpd_ispmgr.conf"
  #
  # By default, the httpd process is started in the C locale; to

cp -ax /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf_ispmgr mv /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf_others

diff -u /etc/httpd/conf.d/ssl.conf_others /etc/httpd/conf.d/ssl.conf_ispmgr

 --- /etc/httpd/conf.d/ssl.conf_others   2009-12-10 06:00:30.000000000 +0300
 +++ /etc/httpd/conf.d/ssl.conf_ispmgr   2009-11-28 02:39:26.000000000 +0300
 @@ -15,10 +15,7 @@
  # When we also provide SSL we have to listen to the
  # the HTTPS port in addition.
  #
 -Listen 192.168.8.69:443
 -Listen 123.456.78.202:443
 -Listen 123.456.78.203:443
 -Listen 123.456.78.204:443
 +Listen 123.456.78.198:443
  ##
  ##  SSL Global Context
 @@ -89,8 +86,8 @@
  # Use separate log files for the SSL virtual host; note that LogLevel
  # is not inherited from httpd.conf.
 -ErrorLog logs/ssl_error_log
 -TransferLog logs/ssl_access_log
 +ErrorLog logs_ispmgr/ssl_error_log
 +TransferLog logs_ispmgr/ssl_access_log
  LogLevel warn
  #   SSL Engine Switch:
 @@ -225,7 +222,7 @@
  #   Per-Server Logging:
  #   The home of a custom SSL log file. Use this when you want a
  #   compact non-error SSL logfile on a virtual host basis.
 -CustomLog logs/ssl_request_log \
 +CustomLog logs_ispmgr/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
  </VirtualHost>

Директиву Listen нужно править в обоих файлах в соответствии с вашими реалиями. Я вынес ispmgr на тот ip, на котором висит лицензия, а остальные отдал под пользовательский апач.

cp -ax /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd_ispmgr.conf

diff -U 1 /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd_ispmgr.conf

 --- /etc/httpd/conf/httpd.conf  2009-12-10 05:59:52.000000000 +0300                                                                         
 +++ /etc/httpd/conf/httpd_ispmgr.conf   2009-11-28 02:39:05.000000000 +0300                                                                 
 @@ -27,5 +27,5 @@                                                                                                                           
  # server will use that explicit path.  If the filenames do *not* begin                                                                     
 -# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"                                                                      
 +# with "/", the value of ServerRoot is prepended -- so "logs_ispmgr/foo.log"                                                               
  # with ServerRoot set to "/etc/httpd" will be interpreted by the                                                                           
 -# server as "/etc/httpd/logs/foo.log".                                                                                                     
 +# server as "/etc/httpd/logs_ispmgr/foo.log".                                                                                              
  #                                                                                                                                          
 @@ -62,3 +62,3 @@                                                                                                                           
  #                                                                                                                                          
 -PidFile run/httpd.pid                                                                                                                      
 +PidFile run/httpd_ispmgr.pid                                                                                                               
 @@ -133,6 +133,3 @@                                                                                                                         
  #Listen 12.34.56.78:80                                                                                                                     
 -Listen 192.168.8.69:80                                                                                                                     
 -Listen 123.456.78.202:80                                                                                                                   
 -Listen 123.456.78.203:80                                                                                                                   
 -Listen 123.456.78.204:80                                                                                                                   
 +Listen 123.456.78.198:80                                                                                                                   
 @@ -213,3 +210,3 @@                                                                                                                         
  Include conf.d/*.conf                                                                                                                      
 -Include conf.d/*.conf_others                                                                                                               
 +Include    conf.d/*.conf_ispmgr
 @@ -475,3 +472,3 @@                                                                                                                         
  #                                                                                                                                          
 -ErrorLog logs/error_log                                                                                                                    
 +ErrorLog logs_ispmgr/error_log
 @@ -504,3 +501,3 @@
  #
 -#CustomLog logs/access_log common
 +#CustomLog logs_ispmgr/access_log common
 @@ -510,4 +507,4 @@
  #
 -#CustomLog logs/referer_log referer
 -#CustomLog logs/agent_log agent
 +#CustomLog logs_ispmgr/referer_log referer
 +#CustomLog logs_ispmgr/agent_log agent
 @@ -517,3 +514,3 @@
  #
 -CustomLog logs/access_log combined
 +CustomLog logs_ispmgr/access_log combined
 @@ -854,6 +851,2 @@
      </Directory>
 -<Directory /var/www/u1/data/www/r.isptest.mns.ru>
 -       php_admin_value open_basedir "/var/www/u1/data:."
 -       Options +ExecCGI
 -</Directory>
 @@ -996,47 +989,6 @@
  #    ServerName dummy-host.example.com
 -#    ErrorLog logs/dummy-host.example.com-error_log
 -#    CustomLog logs/dummy-host.example.com-access_log common
 +#    ErrorLog logs_ispmgr/dummy-host.example.com-error_log
 +#    CustomLog logs_ispmgr/dummy-host.example.com-access_log common
  #</VirtualHost>

Опять-таки редактируем Listen в обоих файлах в соответствии с реалиями вашего хостинга. Вносим остальные нужные нам настройки (SSL-сертификаты ISPmanager и прочее) Перезапускаем пользовательский апач, чтобы освободить *.80 и *.443

 service httpd restart

Включаем вебсервер панели в rcX.d и запускаем его:

 chkconfig httpd_ispmgr --add
 chkconfig httpd_ispmgr on
 service httpd_ispmgr start

Если вы ничего не напутали, и самое главное, если я ничего не забыл, то должны запуститься оба апача, пользовательский в домене httpd_t и панельный в unconfined_t. Проверим это:

ps -Chttpd_ispmgr -Chttpd -Z

 root:system_r:httpd_t           23592 ?        00:00:00 httpd
 root:system_r:httpd_t           23593 ?        00:00:00 httpd
 root:system_r:httpd_t           23594 ?        00:00:00 httpd
 root:system_r:httpd_t           23595 ?        00:00:00 httpd
 root:system_r:httpd_t           23596 ?        00:00:00 httpd
 root:system_r:httpd_t           23597 ?        00:00:00 httpd
 root:system_r:httpd_t           23598 ?        00:00:00 httpd
 root:system_r:httpd_t           23599 ?        00:00:00 httpd
 root:system_r:httpd_t            2455 ?        00:00:01 httpd
 root:system_r:httpd_t           30644 ?        00:00:00 httpd
 system_u:system_r:unconfined_t   2235 ?        00:00:01 httpd_ispmgr
 system_u:system_r:unconfined_t  23602 ?        00:00:00 httpd_ispmgr
 system_u:system_r:unconfined_t  23603 ?        00:00:00 httpd_ispmgr
 system_u:system_r:unconfined_t  23604 ?        00:00:00 httpd_ispmgr
 system_u:system_r:unconfined_t  23605 ?        00:00:00 httpd_ispmgr
 system_u:system_r:unconfined_t  23606 ?        00:00:00 httpd_ispmgr
 system_u:system_r:unconfined_t  23607 ?        00:00:00 httpd_ispmgr
 system_u:system_r:unconfined_t  23608 ?        00:00:00 httpd_ispmgr
 system_u:system_r:unconfined_t  23617 ?        00:00:00 httpd_ispmgr


Послесловие

Уфф. Основная работа сделана!

Включаем selinux в режим Enforced и перегружаемся. Не используем setenforce! Перезагрузка нужна, т.к. процессы получают контекст в момент создания, и перезапускать их все вручную неудобно.

Редактируем /etc/selinux/config SELINUX=enforcing и перезагружаемся.

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

Свой файловый контекст вписываем сюда:

 /etc/selinux/targeted/contexts/files/file_contexts.local

Примеры, как это сделать, можно взять тут:

 /etc/selinux/targeted/contexts/files/file_contexts

Список полезных команд:

 getsebool
 setsebool
 getenforce
 setenforce
 audit2allow
 audit2who
 checkmodule
 semodule_package
 semodule

Алгоритм дальнейшей работы, в общих чертах, таков:

  • переходим в permissive
  • перезапускаем проблемный сервис
  • даем ему сделать то, что он хочет
  • смотрим, что он накидал в audit log
  • пропускаем его через audit2allow и получаем шаблон модуля
  • творчески анализируем полученный шаблон и думаем, надо ли пускать сервис куда не надо, редактируем шаблон и file_contexts.local
  • собираем и грузим модуль
  • устанавливаем правильный контекст у того, что мы вписали в file_contexts.local
  • переходим в enforced
  • перезапускаем проблемный сервис и проверяем его работу



WBR, Vadim Shkolin, vadim аt vsh.spb.su

Была ли эта информация полезной? Да | Нет
Личные инструменты