Que políticas do SELinux se aplicam ao haproxy?

6

Eu encontrei outro problema relacionado ao SELinux. Parece que meu haproxy não tinha permissão para abrir conexões TCP com o back-end e eu consegui corrigi-lo rapidamente usando o Google. Agora, gostaria de saber como alguém resolveria esse problema se realmente soubesse como trabalhar com o SELinux?

O problema

Eu quero usar o haproxy para encaminhar minha porta acessível publicamente 5000 para 127.0.0.1:5601. Eu configurei o haproxy de acordo, e fiz systemctl restart haproxy e imediatamente obtive essa beleza no syslog:

May  9 09:38:45 localhost haproxy[2900]: Server kibana/app1 is DOWN, reason: Layer4 connection problem, info: "General socket error (Permission denied)", check duration: 0ms. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.

permission denied --> SELinux tornou-se a avaliação de curto-circuito dominante na minha solução de problemas do Linux. Não me falhou em anos!

A solução

A solução para este problema, de acordo com nossos amigos no Serverfault , é

semanage port --add --type http_port_t --proto tcp 5601

porque

SELinux only allow[s] the web server to make outbound connections to a limited set of ports

e aparentemente o comando semanage adiciona a porta 5601 a essa lista. Isso funciona e agora meu haproxy me serve Kibana. Ótimo!

O que eu não entendo / conhece

Quando eu ps fauxZ eu vejo o contexto do haproxy é system_u:system_r:haproxy_t:s0 . Com os comandos disponíveis no meu Linux, como posso descobrir que o haproxy é restrito pelas portas associadas a http_port_t ?

    
por Bananguin 09.05.2017 / 12:08

1 resposta

7

O SELinux tem uma certa reputação de ser arcano - e um que eu acho que é bem merecido.

Do jeito que eu entendo, o contexto de um programa que está sendo executado define o que a política atual permitirá que ele acesse ou faça. Assim, como você imaginou, o tipo haproxy_t tem permissão para algumas permissões baseadas no tipo http_port_t.

Agora, vamos tentar descobrir como encontrar esse relacionamento.

Obtenha o rótulo do SELinux

Como você sabe, ps -eZ listará os rótulos do SELinux dos processos em execução - no caso do haproxy, que user:role:type:sensitivity é system_u:system_r:haproxy_t:s0 . O bit importante é o tipo, neste caso haproxy_t.

Permissões

Agora, para descobrir quais permissões esse tipo tem, podemos usar sesearch [1]:

sesearch -d -A -s haproxy_t
  • -d mostra apenas resultados diretos - se você omitir isso, isso também mostrará todos os objetos de seinfo --type=haproxy_t -x !
  • -A procura por regras de permissão
  • -s haproxy_t define o tipo de fonte como haproxy_t

Agora obtivemos muitos resultados (106 na minha VM do CentOS 7), porque, por acaso, há muitas permissões granulares diferentes definidas. Neste ponto, você precisa saber algo mais sobre o que está procurando - a classe a que a permissão se aplica, o tipo de destino ou o próprio nome da permissão.

Pesquisa por classe

Vamos primeiro à aula: por isso sabemos que o nosso tipo de fonte é haproxy_t e pensamos que a nossa turma pode ter algo a ver com a internet, por isso é uma boa aposta que possa ser tcp_socket.

sesearch -d -A -s haproxy_t -c tcp_socket

Isso listará todas as regras de permissão para o tipo de origem haproxy_t que tem alguma coisa a ver com tcp_socket. Isso diminuiu bastante, mas ainda é um palpite de qual desses pode ser o que estamos procurando.

Pesquise por permissões específicas

Em seguida, vamos tentar com permissões - sabemos que precisamos do nosso haproxy para ligar e conectar em portas específicas, certo? por isso, tentamos as permissões name_bind e name_connect.

sesearch -d -A -s haproxy_t -p "name_bind, name_connect"

Found 4 semantic av rules:
    allow haproxy_t http_cache_port_t : tcp_socket { name_bind name_connect } ;
    allow haproxy_t commplex_main_port_t : tcp_socket { name_bind name_connect } ;
    allow haproxy_t http_port_t : tcp_socket { name_bind name_connect } ;
    allow haproxy_t port_type : tcp_socket name_bind ;

Isso mostra apenas 4 resultados, dos quais apenas 3 podem ser nossos culpados! Esses resultados são, no que diz respeito ao SELinux, as únicas portas que qualquer processo com o contexto de haproxy_t tem permissão para se ligar.

Pesquisar por tipo de segmentação

Este é um truque, porque neste caso estamos realmente procurando pelo tipo de alvo! Mas, por questão de integridade - por exemplo, se quisermos descobrir quais permissões haproxy_t obtém de http_port_t, podemos usar o seguinte:

sesearch -d -A -s haproxy_t -t http_port_t

Found 1 semantic av rules:
    allow haproxy_t http_port_t : tcp_socket { name_bind name_connect } ;

e isso, é claro, nos dá apenas um resultado e as permissões que se aplicam.

Portas

Agora que conhecemos os objetos de destino e que eles são definições de portas, podemos descobrir exatamente quais portas eles abrangem. Bem, vamos descobrir:

semanage port -l | grep -E 'http_cache_port_t|commplex_main_port_t|http_port_t'

commplex_main_port_t        tcp    5000
commplex_main_port_t        udp    5000
http_cache_port_t           tcp    8080, 8118, 8123, 10001-10010
http_cache_port_t           upd    3130
http_port_t                 tcp    80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t         tcp    5988

E assim, vemos que a porta tcp 5601 não está na lista. Agora, até onde o SELinux se importa, você pode adicionar essa porta a qualquer um desses tipos com o comando semanage port --add --type XXX --proto tcp 5601 , e isso funcionará. Mas como isso serve http, http_port_t parece o tipo mais aplicável.

Espero que isso o desmistifique um pouco.

[1] Disponível no pacote setools-console.

    
por 09.05.2017 / 15:17

Tags