Editor – A postagem do blog intitulada “NGINX: Alterações no SELinux ao atualizar para RHEL 6.6/CentOS 6.6” redireciona para aqui. Este artigo fornece informações atualizadas e generalizadas.
As configurações padrão do Security-Enhanced Linux (SELinux) no Red Hat Enterprise Linux (RHEL) moderno e distribuições relacionadas podem ser muito rígidas, focando mais na segurança do que na conveniência. Embora as configurações padrão não limitem o funcionamento do NGINX Open Source e do NGINX Plus em suas configurações padrão, outros recursos que você pode configurar podem ser bloqueados, a menos que você os permita explicitamente no SELinux. Este artigo descreve os possíveis problemas e as maneiras recomendadas para resolvê-los.
[Editor – Este artigo se aplica tanto ao NGINX Open Source quanto ao NGINX Plus. Para facilitar a leitura, o termo “NGINX” é usado em todo o texto.
CentOS é uma distribuição relacionada originalmente derivada do RHEL e é suportada pelo NGINX e NGINX Plus. Além disso, o NGINX Plus oferece suporte às distribuições relacionadas Amazon Linux e Oracle Linux. As configurações padrão do SELinux podem ser diferentes do CentOS e do RHEL; consulte a documentação do fornecedor.]
Visão geral do SELinux
O SELinux é habilitado por padrão em servidores RHEL e CentOS modernos. Cada objeto do sistema operacional (processo, descritor de arquivo, arquivo, etc.) é rotulado com um contexto SELinux que define as permissões e operações que o objeto pode executar. No RHEL 6.6/CentOS 6.6 e posteriores, o NGINX é rotulado com o contexto httpd_t
:
# ps auZ | grep nginxunconfined_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
O contexto httpd_t
permite que o NGINX escute em portas comuns do servidor web, acesse arquivos de configuração em /etc/nginx e acesse conteúdo no local docroot padrão ( /usr/share/nginx ). Ele não permite muitas outras operações, como proxy para locais upstream ou comunicação com outros processos por meio de soquetes.
Para desabilitar temporariamente as restrições do SELinux para o contexto httpd_t
, para que o NGINX possa executar todas as mesmas operações que em sistemas operacionais não SELinux, atribua o contexto httpd_t
ao domínio permissivo . Veja a próxima seção para mais detalhes.
# semanage permissive -a httpd_t
O SELinux pode ser executado nos modos de imposição , permissivo ou desabilitado (também chamados de domínios ). Antes de fazer uma alteração na configuração do NGINX que possa violar as permissões padrão (estritas), você pode alterar o SELinux do modo forçado para o modo permissivo , no seu ambiente de teste (se disponível) ou no ambiente de produção. No modo permissivo , o SELinux permite todas as operações, mas registra operações que violariam a política de segurança no modo de imposição .
Para adicionar httpd_t
à lista de domínios permissivos , execute este comando:
# semanage permissive -a httpd_t
Para excluir httpd_t
da lista de domínios permissivos , execute:
# semanage permissive -d httpd_t
Para definir o modo globalmente como permissivo , execute:
# setenforce 0
Para definir o modo globalmente como forçado , execute:
# setenforce 1
Resolvendo exceções de segurança do SELinux
No modo permissivo , as exceções de segurança são registradas no log de auditoria padrão do Linux, /var/log/audit/audit.log . Se você encontrar um problema que ocorre apenas quando o NGINX está sendo executado no modo de imposição , revise as exceções registradas no modo permissivo e atualize a política de segurança para permiti-las.
Por padrão, a configuração do SELinux não permite que o NGINX se conecte a servidores HTTP, FastCGI ou outros servidores remotos, conforme indicado por uma mensagem de log de auditoria como a seguinte:
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)
O comando audit2why
interpreta o código da mensagem ( 1415714880.156:29
):
# grep 1415714880.156:29 /var/log/audit/audit.log | audit2whytype=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.
Allow access by executing:
# setsebool -P httpd_can_network_connect 1
A saída de audit2why
indica que você pode permitir que o NGINX faça conexões proxy habilitando uma ou ambas as opções booleanas httpd_can_network_relay
e httpd_can_network_connect
. Você pode habilitá-los temporariamente ou permanentemente, este último adicionando o sinalizador -P
conforme mostrado na saída.
O comando sesearch
fornece mais informações sobre as opções booleanas e está disponível se você instalar o pacote setools ( yum
install
setools
). Aqui mostramos a saída para as opções httpd_can_network_relay
e httpd_can_network_connect
.
httpd_can_network_relay
Aqui está a saída do comando sesearch
sobre a opção httpd_can_network_relay
:
# sesearch -A -s httpd_t -b httpd_can_network_relayFound 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 ;
Esta saída indica que httpd_can_network_relay
permite que processos rotulados com o contexto httpd_t
(como NGINX) se conectem a portas de vários tipos, incluindo o tipo http_port_t
:
# semanage port -l | grep http_port_thttp_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
Para adicionar mais portas (aqui,8082
) para o conjunto de portas permitidas para http_port_t
, execute:
# semanage port -a -t http_port_t -p tcp 8082
Se a saída deste comando disser que uma porta já
está definida
, como no exemplo a seguir, isso significa que a porta está incluída em outro conjunto. Não o reatribua para http_port_t
, porque outros serviços podem ser afetados negativamente.
# 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
Aqui está a saída do comando sesearch
sobre a opção httpd_can_network_connect
:
# sesearch -A -s httpd_t -b httpd_can_network_connectFound 1 semantic av rules:
allow httpd_t port_type : tcp_socket name_connect ;
Esta saída indica que httpd_can_network_connect
permite que processos rotulados com o contexto httpd_t
(como NGINX) se conectem a todos os tipos de soquete TCP que tenham o atributo port_type
. Para listá-los, execute:
# seinfo -aport_type -x
Por padrão, a configuração do SELinux não permite que o NGINX acesse arquivos fora de locais autorizados conhecidos, conforme indicado por uma mensagem de log de auditoria como a seguinte:
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
O comando audit2why
interpreta o código da mensagem ( 1415715270.766:31
):
# grep 1415715270.766:31 /var/log/audit/audit.log | audit2whytype=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.
Quando o acesso ao arquivo é proibido, você tem duas opções.
Modifique o rótulo do arquivo para que o NGINX (como um processo rotulado com o contexto httpd_t
) possa acessar o arquivo:
# chcon -v --type=httpd_sys_content_t /www/t.txt
Por padrão, essa modificação é excluída quando o sistema de arquivos é renomeado. Para tornar a alteração permanente, execute:
# semanage fcontext -a -t httpd_sys_content_t /www/t.txt
# restorecon -v /www/t.txt
Para modificar rótulos de arquivos para grupos de arquivos, execute:
# semanage fcontext -a -t httpd_sys_content_t '/www(/.*)?'# restorecon -Rv /www
httpd_t
Estenda a política para httpd_t
para permitir acesso a locais de arquivo adicionais:
# 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 these booleans:
# httpd_can_network_relay, httpd_can_network_connect
allow httpd_t http_cache_port_t:tcp_socket name_connect;
Para gerar uma política compilada, inclua a opção -M
:
# grep nginx /var/log/audit/audit.log | audit2allow -M nginx
Para carregar a política, execute semodule
-i
e verifique o sucesso com semodule
-l
:
# semodule -i nginx.pp
# semodule -l | grep nginx
nginx 1.0
Essa alteração persiste após reinicializações.
Por padrão, a configuração do SELinux não permite que o NGINX escute ( bind()
) portas TCP ou UDP diferentes das padrão que estão na lista de permissões no tipo http_port_t
:
# semanage port -l | grep http_port_thttp_port_t tcp 80, 443, 488, 8008, 8009, 8443
Se você tentar configurar o NGINX para escutar em uma porta não permitida (com a diretiva listen
no contexto http
, stream
ou mail
na configuração do NGINX), você receberá um erro ao verificar ( nginx
-t
) ou recarregar a configuração do NGINX, conforme indicado por esta entrada de log do NGINX:
YYYY/MM/DD hh:mm:ss [emerg] 46123#0: bind() to 0.0.0.0:8001 failed (13: Permission denied)
Você pode usar semanage
para adicionar a porta desejada (aqui, 8001) ao tipo http_port_t
:
# semanage port -a -t http_port_t -p tcp 8001
Recarregue o NGINX com a nova configuração.
# nginx -s reload
Muitos arquivos estão abertos
ErroQuando o limite do número de arquivos abertos ( RLIMIT_NOFILE
) é excedido, a seguinte mensagem aparece no log de erros:
Too many files are open
Na maioria dos casos, o processo de trabalho do NGINX relata esse erro, mas você não pode usar a diretiva NGINX worker_rlimit_nofile
para aumentar o limite porque o SELinux não permite a chamada de sistema setrlimit()
, conforme relatado nas seguintes mensagens nos logs de erro e auditoria.
Em /var/log/nginx/error.log para CentOS/RHEL 7.4+:
YYYY/MM/DD hh:mm:ss [alert] 12066#0: setrlimit(RLIMIT_NOFILE, 2342) failed (13: Permission denied)
Em /var/log/nginx/error.log para CentOS/RHEL 8.0+:
YYYY/MM/DD hh:mm:ss [alert] 3327#0: setrlimit(RLIMIT_NOFILE, 65535) failed (1: Operation not permitted)
Em /var/log/audit/audit.log para CentOS/RHEL 7.4+ e /var/log/messages para CentOS/RHEL 8.0+:
type=AVC msg=audit(1437731200.211:366): avc: denied { setrlimit } for pid=12066 \ comm="nginx" scontext=system_u:system_r:httpd_t:s0 \
tcontext=system_u:system_r:httpd_t:s0 tclass=process
Para aumentar o limite, execute este comando como usuário root
:
$ setsebool -P httpd_setrlimit 1
Se o processo mestre do NGINX relatar o erro, você precisa atualizar o arquivo de unidade
systemd
para o NGINX. Isso define o limite do descritor de arquivo para os processos mestre e de trabalho.
Crie um diretório para a configuração nginx.service
:
$ mkdir /etc/systemd/system/nginx.service.d
Adicione as seguintes linhas em /etc/systemd/system/nginx.service.d/nofile_limit.conf :
[Service]LimitNOFILE=65535
Recarregue a configuração do daemon systemd e reinicie o NGINX:
$ systemctl daemon-reload$ systemctl restart nginx.service
Recursos adicionais
O SELinux é um recurso complexo e poderoso para gerenciar permissões do sistema operacional. Informações adicionais estão disponíveis nos seguintes documentos.
"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."