Настройка SELinux для Apache/Nginx в Unix/Linux
И так, я за свои 5 лет администрирования, никогда не настраивал SELinux — я его просто выключал. Но всегда бывает первый раз и сейчас, пришло время разобраться как же устроен и как с ним работать.
Многие из вас, уже сталкивались со следующей проблемой: При попытки использовать httpd сервер ( как пример) с включенным SELinux на борту — апач не работал вообще ( и не спроста, т.к SELinux блокирует пакеты).
Сейчас я, воспроизведу проблему. Для начала, установлю httpd сервер ( на примере CentOS):
$ sudo yum install httpd -y
Или, проверим имеется ли он в ОС:
$ rpm -qa | grep httpd
Мой вывод такой:
httpd-2.2.15-54.el6.centos.x86_64 httpd-tools-2.2.15-54.el6.centos.x86_64
Видим что апач установлен. Проверим, работает ли SELinux, для этого служат несколько команд ( но речь не об этом), я возьму одну из них:
# getenforce Enforcing
Это означает что он включен на сервере.
PS: вот чтиво как можно выключить SELinux:
Как отключить SELinux на CentOS
Запускаем апач:
$ service httpd restart
Запустить команду для просмотра процессов httpd:
# ps -eZ | grep httpd unconfined_u:system_r:httpd_t:s0 3182 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 3185 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 3186 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 3187 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 3188 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 3189 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 3190 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 3191 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 3192 ? 00:00:00 httpd
Контекст SELinux, связанный с процессами httpd, является unconfined_u: system_r: httpd_t: s0. Вторая последняя часть контекста, httpd_t, является типом. Тип определяет домен для процессов и тип для файлов. В этом случае процессы httpd выполняются в домене httpd_t.
Политика SELinux определяет, как процессы, запущенные в ограниченных доменах, такие как httpd_t, взаимодействуют с файлами, другими процессами и системой в целом. Файлы должны быть помечены правильно, чтобы разрешить доступ httpd к ним. Например, httpd может читать файлы, типом httpd_sys_content_t, но не может их писать, даже если разрешения Linux разрешают доступ на запись. Например разрешение доступа к скрипта сети, позволяя httpd обращаться к файловым системам NFS и CIFS, а httpd разрешено выполнять сценарии Common Gateway Interface (CGI).
Когда вы настраиваете /etc/httpd/conf/httpd.conf для того, чтобы httpd прослушивал порт, отличный от TCP-порта 80, 443, 488, 8008, 8009 или 8443, команда semanage port должна использоваться для добавления нового номера порта Конфигурация политики SELinux. В следующем примере демонстрируется настройка httpd для прослушивания порта, который не определен в конфигурации SELinux для httpd.
Для начала, останавливаем апач:
# service httpd stop && service httpd status
При использовании semanage, у меня возникли проблемы, я получил следующую ошибку:
-bash: semanage: command not found
Исправление:
Исправляем «semanage: command not found» в Unix/Linux
Запустим команду для просмотра httpd портов SELinux ( которые дают возможность httpd, прослушивать порты):
# semanage port -l | grep -w http_port_t http_port_t tcp 80, 443, 488, 8008, 8009, 8443
Видим что стандартные порты используются и работают. Но если нас интересует кастомный проброс определенного порта? Давайте рассмотрим пример. Редактируем конфиг апача:
$ sudo vim /etc/httpd/conf/httpd.conf
И настраиваем прослушивание порта ( предположим, что нужно прослушивать порт 54321)
Находим строку:
Listen 80
Или:
Listen 127.0.0.1:80
И приводим к виду:
Listen 127.0.0.1:12345
Или ( как я сделал себе)
Listen 12345
Запускаем службу апач:
# service httpd restart
И, получаем ошибку:
Starting httpd: (13)Permission denied: make_sock: could not bind to address 127.0.0.1:12345 no listening sockets available, shutting down Unable to open logs [FAILED]
Смотрим лог:
[root@localhost ~]# cat /var/log/messages| grep SELinux Jan 19 19:29:22 localhost kernel: SELinux: Initializing. Jan 19 19:29:22 localhost kernel: dracut: Loading SELinux policy Sep 22 16:31:28 localhost kernel: SELinux: Initializing. Sep 22 16:31:28 localhost kernel: dracut: Loading SELinux policy Sep 22 16:36:52 localhost kernel: SELinux: Initializing. Sep 22 16:36:52 localhost kernel: dracut: Loading SELinux policy Apr 1 23:37:57 localhost kernel: SELinux: Initializing. Apr 1 23:37:57 localhost kernel: dracut: Loading SELinux policy Apr 4 10:16:06 localhost kernel: SELinux: Initializing. Apr 4 10:16:06 localhost kernel: dracut: Loading SELinux policy Apr 4 11:04:50 localhost kernel: SELinux: Initializing. Apr 4 11:04:50 localhost kernel: dracut: Loading SELinux policy Apr 5 01:07:48 localhost kernel: SELinux: Initializing. Apr 5 01:07:48 localhost kernel: dracut: Loading SELinux policy Apr 5 01:46:00 localhost kernel: SELinux: Initializing. Apr 5 01:46:00 localhost kernel: dracut: Loading SELinux policy [root@localhost ~]#
И так, нужно разрешить 12345 порт в SELinux, чтобы чтобы httpd мог прослушивать его 12345, как используется в этом примере, требуется следующая команда:
# semanage port -a -t http_port_t -p tcp 12345
Теперь, пробуем запустить снова апач:
# service httpd restart Starting httpd: [ OK ]
Теперь, когда SELinux был сконфигурирован так, чтобы httpd мог прослушивать нестандартный порт (в нашем примере TCP 12345), httpd успешно запускается на этом порту.
Чтобы доказать, что httpd прослушивает и передает на 12345 TCP-порт , откройте telnet-соединение с указанным портом и выполните команду HTTP GET, как показано ниже:
[root@localhost ~]# telnet localhost 12345 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. HTTP/GET/1.1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>501 Method Not Implemented</title> </head><body> <h1>Method Not Implemented</h1> <p>HTTP/GET/1.1 to / not supported.<br /> </p> <hr> <address>Apache/2.2.15 (CentOS) Server at localhost.localdomain Port 80</address> </body></html> Connection closed by foreign host. [root@localhost ~]#
Как-то так!
Создание политик.
Создайте политику, чтобы назначить httpd_sys_content_t контекст для /webapps папки, а также для всех дочерних каталогов и файлов:
# semanage fcontext -a -t http_sys_content_t "/webapps(/.*)?"
Создайте политику, чтобы назначить httpd_log_t контекст для ведения логов:
semanage fcontext -a -t httpd_log_t "/webapps/logs(/.*)?"
Создайте политику, чтобы назначить httpd_log_t контекст для использования кешей:
semanage fcontext -a -t httpd_cache_t "/webapps/cache(/.*)?"
Разрешаем чтение и запись (ReadWrite)
Apache теперь имеет право использовать наши собственные каталоги. Тем не менее, он не имеет доступа для чтения ко всему. Если у вашего приложения есть файлы или каталоги ( например WordPress), то можно создать правило и разрешить чтение-запись для определенных файлов\папок.
Следующему будет присвоен readwrite для Apache и он сможет писать или изменять данные:
# semanage fcontext -a httpd_sys_rw_content_t "/webapps/app1/public_html/uploads(/.*)?"
Создайте политику, чтобы назначить httpd_sys_rw_content_t контекст для файла с конфигурацией WordPress (wp-config.php):
# emanage fcontext -a httpd_sys_rw_content_t "/webapps/app1/public_html/wp-config.php"
Применяем SELinux политики
Наши политики созданы и готовы к применению. Чтобы все проделанные действия заработали, необходимо перечитать политики самого SELinux:
# restorecon -Rv /webapps
Все работает, а я завершаю свою статью «Настройка SELinux для Apache/Nginx в Unix/Linux».
Опечатка:
не
http_sys_content_t
а
httpd_sys_content_t
в команде:
semanage fcontext -a -t http_sys_content_t «/webapps(/.*)?»