BLOG | NGINX

Usando NGINX e NGINX Plus com SELinux

NGINX-Parte-de-F5-horiz-preto-tipo-RGB
Miniatura de Owen Garrett
Owen Garrett
Publicado em 17 de agosto de 2018

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 nginx unconfined_u:system_r: httpd_t :s0 3234 ? Ss 0:00 nginx: processo mestre /usr/sbin/nginx \ -c /etc/nginx/nginx.conf unconfined_u:system_r: httpd_t :s0 3236 ? Ss 0:00 nginx: processo de trabalho

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.

Desabilitando temporariamente o SELinux para NGINX

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 permissivo -a httpd_t

Alterando os modos do SELinux

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 permissivo -a httpd_t

Para excluir httpd_t da lista de domínios permissivos , execute:

# semanage permissivo -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.

Edição 1: Conexão Proxy Proibida

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:

tipo=AVC msg=audit(1415714880.156:29): avc: negado { name_connect } para 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
tipo=SYSCALL msg=audit(1415714880.156:29): arch=c000003e syscall=42 sucesso=não \
saída=-115 a0=b \a1=16125f8 a2=10 a3=7fffc2bab440 itens=0 ppid=1347 pid=1349 \
auid=1000 uid=497 gid=496 euid=497 suid=497 fsuid=497 egid=496 sgid=496 fsgid=496 \
tty=(nenhum) 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 | audit2why type=AVC msg=audit(1415714880.156:29): avc: { name_connect } negado para 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 Foi causado por:
        Um dos seguintes valores booleanos foi definido incorretamente.
        Descrição:
        Permitir que o httpd atue como um relé Permitir acesso executando: # setsebool -P httpd_can_network_relay 1 Descrição:
        Permitir que scripts e módulos HTTPD se conectem à rede usando TCP.
 
        Permitir acesso executando: # 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.

Compreendendo opções booleanas

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 .

A opção booleana 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_relay Foram encontradas 10 regras av semânticas: permitir httpd_t gopher_port_t : tcp_socket name_connect ; permitir httpd_t http_cache_client_packet_t : pacote { enviar recebimento } ; permitir httpd_t ftp_port_t : tcp_socket name_connect ; permitir httpd_t ftp_client_packet_t : pacote { enviar recebimento } ; permitir httpd_t http_client_packet_t : pacote { enviar recebimento } ; permitir httpd_t squid_port_t : tcp_socket name_connect ; permitir httpd_t http_cache_port_t : tcp_socket name_connect ; permitir httpd_t http_port_t : tcp_socket name_connect ; permitir httpd_t gopher_client_packet_t: pacote {enviar recebimento}; permitir 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 porta -l | grep http_port_t http_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 porta -a -t http_port_t -p tcp 8082

Se a saída deste comando disser que uma porta 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 porta -a -t http_port_t -p tcp 8080 /usr/sbin/semanage: Porta tcp/8080 já definida # semanage port -l | grep 8080 http_cache_port_t tcp 3128, 8080, 8118, 8123, 10001-10010

A opção booleana 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_connect Encontradas 1 regras av semânticas: permitir 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

Edição 2: O acesso ao arquivo é proibido

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:

tipo=AVC msg=audit(1415715270.766:31): avc: negado { getattr } para 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 | audit2why type=AVC msg=audit(1415715270.766:31): avc: negado { getattr } para 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 Foi causado por:
        Regra de permissão de aplicação de tipo (TE) ausente.
 
        Você pode usar audit2allow para gerar um módulo carregável para permitir esse acesso.

Quando o acesso ao arquivo é proibido, você tem duas opções.

Opção 1: Modificar o rótulo do arquivo

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

Opção 2: Estenda as permissões de domínio 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 módulo nginx 1.0; require { tipo httpd_t; tipo default_t; tipo http_cache_port_t; classe tcp_socket nome_connect; classe arquivo { ler getattr aberto }; } #============= httpd_t =============== permitir httpd_t default_t:arquivo { ler getattr aberto }; #!!!! Este avc pode ser permitido usando um destes booleanos: # 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.

Edição 3: NGINX não pode vincular a portas adicionais

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 porta -l | grep http_port_t http_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:

AAAA / MM / DD hh : mm : ss [emerg] 46123#0: bind() para 0.0.0.0:8001 falhou (13: Permissão negada)

Você pode usar semanage para adicionar a porta desejada (aqui, 8001) ao tipo http_port_t :

# semanage porta -a -t http_port_t -p tcp 8001

Recarregue o NGINX com a nova configuração.

# nginx -s recarregar

Edição 4: Muitos arquivos estão abertos Erro

Quando o limite do número de arquivos abertos ( RLIMIT_NOFILE ) é excedido, a seguinte mensagem aparece no log de erros:

Muitos arquivos estão abertos

Quando o processo de trabalho do NGINX gera o erro

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+:

    AAAA / MM / DD hh : mm : ss [alerta] 12066#0: setrlimit(RLIMIT_NOFILE, 2342) falhou (13: Permissão negada)
    
  • Em /var/log/nginx/error.log para CentOS/RHEL 8.0+:

    AAAA / MM / DD hh : mm : ss [alerta] 3327#0: setrlimit(RLIMIT_NOFILE, 65535) falhou (1: Operação não permitida)
    
  • Em /var/log/audit/audit.log para CentOS/RHEL 7.4+ e /var/log/messages para CentOS/RHEL 8.0+:

    tipo=AVC msg=audit(1437731200.211:366): avc: negado { setrlimit } para 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

Quando o processo mestre NGINX gera o erro

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.

  1. Crie um diretório para a configuração nginx.service :

    $ mkdir /etc/systemd/system/nginx.service.d
    
  2. Adicione as seguintes linhas em /etc/systemd/system/nginx.service.d/nofile_limit.conf :

    [Serviço]LimitNOFILE=65535
    
  3. Recarregue a configuração do daemon systemd e reinicie o NGINX:

    $ systemctl daemon-reload $ systemctl reiniciar 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."