При обновлении рабочей системы до Red Hat Enterprise Linux 6.6 или CentOS 6.6, правила доступа SELinux для nginx меняют структуру. Новые правила могут не повлиять на nginx со стандартным конфигом, однако различные пользовательские конфигурации могут быть заблокированы и придется вручную прописывать разрешения для них.
Далее будут описаны некоторые проблемы, с которыми можно столкнуться при обновлении до RHEL/CentOS 6.6 и рекомендации по их решению.
Обзор SELinux
На серверах RHEL и CentOS SELinux включен по-умолчанию. Каждый объект операционной системы (процесс, файловый дескриптор, файл и т.д.) связан с контекстом SELinux, который определяет права доступа и возможные операции с объектом. При обновлении до версии операционной системы 6.6, nginx связывается с контекстом httpd_t:
# ps auZ | grep nginx unconfined_u:system_r:httpd_t:s0 3234 ? Ss 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf unconfined_u:system_r:httpd_t:s0 3236 ? Ss 0:00 nginx: worker process
Контекст httpd_t разрешает nginx прослушивать основные веб-порты, получать доступ к конфигурационным файлам в каталоге /etc/nginx и стандартному расположению корневого каталога документов веб /usr/share/nginx. Он не разрешает многие другие операции, такие как проксирование трафика и взаимодействие с другими процессами через сокеты.
Режимы работы SELinux
SELinux может быть запущен в одном из трех режимов работы: enforcing, permissive или disabled. В том случае, если вы делаете изменения конфигурации, которые могут идти в разрез с текущими правилами безопасности, можно перевести SELinux из режима enforcing в permissive, лучше это делать на тестовом окружении. В режиме permissive, SELinux разрешает все операции, но логирует все операции, которые были бы запрещены в режиме enforcing.
Добавление контекста httpd_t в список permissive:
# semanage permissive -a httpd_t
Удаление контекста httpd_t из списка permissive:
# semanage permissive -d httpd_t
Переключение глобального режима работы SELinux
Активация глобального режима permissive:
# setenforce 0
Активация глобального режима работы enforcing:
# setenforce 1
Исключения SELinux
В режиме permissive, все исключения безопасности логируются в /var/log/audit/audit.log. При возникновении проблем с nginx в режиме enforcing, можно переключиться в режим permissive, и откорректировать правила безопасности, основываясь на логах режима permissive.
Пример 1. Подключение прокси запрещено
Конфигурация SELinux по-умолчанию не разрешает nginx подключение к удаленному веб-серверу, fastCGI или другому серверу.
Что мы видим в логе audit.log:
type=AVC msg=audit(1415714880.156:29): avc: denied { name_connect } for pid=1349 comm="nginx" dest=8080 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket type=SYSCALL msg=audit(1415714880.156:29): arch=c000003e syscall=42 success=no exit=-115 a0=b a1=16125f8 a2=10 a3=7fffc2bab440 items=0 ppid=1347 pid=1349 auid=1000 uid=497 gid=496 euid=497 suid=497 fsuid=497 egid=496 sgid=496 fsgid=496 tty=(none) ses=1 comm="nginx" exe="/usr/sbin/nginx" subj=unconfined_u:system_r:httpd_t:s0 key=(null)
Подробности о сообщении 1415714880.156:29 можно узнать с помощью audit2why:
# grep 1415714880.156:29 /var/log/audit/audit.log | audit2why type=AVC msg=audit(1415714880.156:29): avc: denied { name_connect } for pid=1349 comm="nginx" dest=8080 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket Was caused by: One of the following booleans was set incorrectly. Description: Allow httpd to act as a relay Allow access by executing: # setsebool -P httpd_can_network_relay 1 Description: Allow HTTPD scripts and modules to connect to the network using TCP.
Предоставляем доступ:
# setsebool -P httpd_can_network_connect 1
audit2why рекомендует настройки для исправления данного запрета. Разрешить данное действие можно как на постоянной основе (-P), так и временно.
Что такое логические параметры
Разобраться в этом вопросе и лучше понять значение логических параметров поможет пакет setools.
Установим setools:
# yum -y install setools
Параметр httpd_can_network_relay
# sesearch -A -s httpd_t -b httpd_can_network_relay Found 10 semantic av rules: allow httpd_t gopher_port_t : tcp_socket name_connect ; allow httpd_t http_cache_client_packet_t : packet { send recv } ; allow httpd_t ftp_port_t : tcp_socket name_connect ; allow httpd_t ftp_client_packet_t : packet { send recv } ; allow httpd_t http_client_packet_t : packet { send recv } ; allow httpd_t squid_port_t : tcp_socket name_connect ; allow httpd_t http_cache_port_t : tcp_socket name_connect ; allow httpd_t http_port_t : tcp_socket name_connect ; allow httpd_t gopher_client_packet_t : packet { send recv } ; allow httpd_t memcache_port_t : tcp_socket name_connect ;
Очевидно, что can_network_relay разрешает подключения на различные порты, включая http_port_t:
# semanage port -l | grep http_port_t http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
Добавить порт к правилу не сложно:
# semanage port -a -t http_port_t -p tcp 8082
Если порт уже включен в другое правило:
# semanage port -a -t http_port_t -p tcp 8080 /usr/sbin/semanage: Port tcp/8080 already defined # semanage port -l | grep 8080 http_cache_port_t tcp 3128, 8080, 8118, 8123, 10001-10010
не нужно его переопределять, так как это может повлиять на другие сервисы.
Параметр httpd_can_network_connect
# sesearch -A -s httpd_t -b httpd_can_network_connect Found 1 semantic av rules: allow httpd_t port_type : tcp_socket name_connect ;
httpd_can_network_connect разрешает httpd_t подключение ко всем типам tcp сокетов, имеющим атрибут port_type. Их перечень можно получить следующей командой:
# seinfo -aport_type -x
Пример 2. Доступ к файлу запрещен
Конфигурация SELinux по-умолчанию разрешает доступ nginx только к файлам в определенных (традиционных) каталогах.
Что мы видим в логе audit.log:
type=AVC msg=audit(1415715270.766:31): avc: denied { getattr } for pid=1380 comm="nginx" path="/www/t.txt" dev=vda1 ino=1084 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
Результат утилиты audit2why:
# grep 1415715270.766:31 /var/log/audit/audit.log | audit2why type=AVC msg=audit(1415715270.766:31): avc: denied { getattr } for pid=1380 comm="nginx" path="/www/t.txt" dev=vda1 ino=1084 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access.
В случае с запретом доступа к файлам есть два выхода:
Первый: изменение атрибута файла
Изменение атрибута файла так, что бы httpd_t смог получить к нему доступ:
# chcon -v --type=httpd_sys_content_t /www/t.txt
Данное изменение может быть удалено при изменениях в файловой системе, так что, можно сделать его постоянным:
# semanage fcontext -a -t httpd_sys_content_t /www/t.txt # restorecon -v /www/t.txt
Так же, можно изменять атрибуты групп файлов:
# semanage fcontext -a -t httpd_sys_content_t /www(/.*)? # restorecon -Rv /www
Второй: добавление разрешений для httpd_t
Расширенные разрешения httpd_t для доступа к разным файлам:
# grep nginx /var/log/audit/audit.log | audit2allow -m nginx > nginx.te # cat nginx.te module nginx 1.0; require { type httpd_t; type default_t; type http_cache_port_t; class tcp_socket name_connect; class file { read getattr open }; } #============= httpd_t ============== allow httpd_t default_t:file { read getattr open }; #!!!! This avc can be allowed using one of the these booleans: # httpd_can_network_relay, httpd_can_network_connect allow httpd_t http_cache_port_t:tcp_socket name_connect;
Создаем готовое правило используя ключ -M:
# grep nginx /var/log/audit/audit.log | audit2allow -M nginx
Загружаем его semodule -i и проверяем результат с ключом -l:
# semodule -i nginx.pp # semodule -l | grep nginx nginx 1.0
Эти изменения будут актуальны и после перезагрузки системы.