como proteger uma porta aberta do PostgreSQL

29

Então, esta é a situação. Parece que precisamos ter uma porta TCP aberta 5432 para o mundo, onde um cliente tenha acesso ao seu banco de dados PostgreSQL.

Por razões óbvias, não podemos dizer apenas "não", apenas como último recurso.

Quais são os maiores problemas? Como posso defender nossa infraestrutura?

De qualquer forma: por que não deveria ser aberto ao mundo? Eu acho que talvez seja mais seguro do que um servidor FTP de 20 anos, não mantido.

P.S. VPN não está bem. Alguma criptografia talvez (se eu puder dar a ele uma URL de conexão JDBC que funcione ).

    
por Josip Rodin 09.09.2014 / 08:41

4 respostas

41

Exigir SSL, manter o SELinux ativado, monitorar os logs e usar uma versão atual do PostgreSQL .

Lado do servidor

Requer SSL

Em postgresql.conf set ssl=on e certifique-se de ter seu arquivo-chave e certfile instalado adequadamente (consulte os documentos e os comentários em postgresql.conf ).

Talvez seja necessário comprar um certificado de uma autoridade de certificação se você quiser que a confiança seja de clientes sem uma configuração especial no cliente.

Em pg_hba.conf use algo como:

hostssl theuser thedatabase 1.2.3.4/32 md5

... possivelmente com "todos" para usuário e / ou banco de dados, e possivelmente com um filtro de endereço IP de origem mais amplo.

Limite os usuários que podem efetuar login, negar login de superusuário remoto

Não permita "all" para os usuários, se possível; você não deseja permitir logins de superusuário remotamente se puder evitar a necessidade.

Limitar direitos dos usuários

Restringir os direitos do (s) usuário (s) que podem efetuar login. Não atribua a eles CREATEDB ou CREATEUSER direitos.

REVOKE the CONNECT de PUBLIC em todos os seus bancos de dados, em seguida, devolva apenas os usuários / funções que devem poder acessar esse banco de dados. (Agrupe usuários em funções e conceda direitos a funções, em vez de diretamente a usuários individuais).

Certifique-se de que os usuários com acesso remoto só possam se conectar aos DBs de que precisam e tenham apenas direitos sobre os esquemas, tabelas e colunas que realmente precisam. Esta é uma boa prática para os usuários locais também, é apenas uma segurança sensata.

Configuração do cliente

Em PgJDBC, passe o parâmetro ssl=true :

To instruct the JDBC driver to try and establish a SSL connection you must add the connection URL parameter ssl=true.

... e instale o certificado do servidor no armazenamento confiável do cliente ou use um certificado de servidor que seja de confiança de uma das CAs no armazenamento confiável integrado do Java, se você não quiser que o usuário tenha que instalar o certificado. / p>

Ação contínua

Agora certifique-se de manter o PostgreSQL atualizado . O PostgreSQL possui apenas algumas brechas de segurança anteriores à autenticação, mas isso é mais do que zero, portanto, mantenha-se atualizado. Você deve, de qualquer forma, correções de bugs são coisas legais para ter.

Adicione um firewall na frente se houver grandes netblocks / regiões de que você sabe que não precisa acessar.

Registrar conexões e desconexões (consulte postgresql.conf ). Log de consultas, se for prático. Execute um sistema de detecção de intrusão ou fail2ban ou similar na frente, se for prático. Para o fail2ban com postgres, há um prático como:

Monitore os arquivos de log.

Paranoia bônus

Passos extras para pensar ...

Requer certificados de cliente

Se desejar, você também pode usar pg_hba.conf para exigir que o cliente apresente um certificado de cliente X.509 confiável pelo servidor. Ele não precisa usar o mesmo CA como o certificado do servidor, você pode fazer isso com um homebrew openssl CA. Um usuário do JDBC precisa importar o certificado do cliente em seu keystore Java com keytool e, possivelmente, configurar algumas propriedades do sistema JSSE para apontar o Java em seu keystore, portanto, não é totalmente transparente.

Coloque em quarentena a instância

Se você quiser ser realmente paranóico, execute a instância do cliente em um contêiner / VM separado, ou pelo menos com uma conta de usuário diferente, apenas com os bancos de dados de que eles precisam.

Dessa forma, se eles comprometerem a instância do PostgreSQL, eles não irão avançar mais.

Use o SELinux

Eu não tenho que dizer isso, mas ...

Execute uma máquina com suporte ao SELinux, como RHEL 6 ou 7, e não desligue o SELinux ou configure-o para o modo permissivo . Mantê-lo em modo de execução.

Use uma porta não padrão

Segurança por somente obscuridade é estupidez. Segurança que usa um pouco de obscuridade uma vez que você tenha feito as coisas sensatas provavelmente não vai doer.

Execute a Pg em uma porta não padrão para tornar a vida um pouco mais difícil para atacantes automatizados.

Coloque um proxy na frente

Você também pode executar o PgBouncer ou o PgPool-II na frente do PostgreSQL, atuando como um pool de conexão e proxy. Dessa forma, você pode deixar o proxy manipular o SSL, não o host do banco de dados real. O proxy pode estar em uma VM ou máquina separada.

O uso de proxies de pool de conexão geralmente é uma boa idéia com o PostgreSQL, a menos que o aplicativo cliente já tenha um pool integrado. A maioria dos servidores de aplicativos Java, Rails, etc, tem pool integrado. Mesmo assim, um proxy de pool do lado do servidor é, na pior das hipóteses, inofensivo.

    
por 09.09.2014 / 09:03
2

Uma simples extensão do plano de ação impressionante de Craig:

Talvez o usuário esteja usando apenas um conjunto relativamente pequeno de provedores de rede (por exemplo, seu provedor de rede móvel enquanto está em movimento, sua rede a cabo de casa e o ip de saída do local de trabalho).

A maioria dos provedores de rede tem muitos IPs, mas não muitas sub-redes. Assim, você pode fornecer um filtro iptables, que limita o acesso postgresql aos segmentos de rede que são usados por seu cliente. Isso reduziu bastante as possibilidades de ataque de fontes de problemas selecionadas aleatoriamente na rede.

Um cenário de suporte simples:

  1. Seu cliente liga para você, "não consigo fazer login" .
  2. Você descobre com um comando tcpdump -i eth0 -p tcp port 5432 , de onde ele vem.
  3. Com um whois 1.2.3.4 você pode obter o endereço ip usado por este ip. Por exemplo, pode ser 1.2.3.0/24 .
  4. Com um iptables -A INPUT -s 1.2.3.0/24 -p tcp --dport 5432 -j ACCEPT (ou algum similar), você permite as conexões tcp com sua nova sub-rede.

Existe um script perl muito bom chamado uif que pode fornecer conjuntos de regras iptables declaráveis permanentes e intuitivos. (Google para "uif iptables").

    
por 09.09.2014 / 10:59
1

Aqui está uma configuração Fail2ban bastante simples para o PostgreSQL baseada no HOWTO linkado acima, mas ajustada para trabalhar com pacotes do Ubuntu, pegar outra condição de erro e pular várias mensagens de depuração para torná-lo mais rápido:

/etc/fail2ban/filter.d/local-postgresql.conf :

[Definition]

failregex = <HOST>\(\d+\) FATAL:  password authentication failed for .+$
            <HOST>\(\d+\) FATAL:  no pg_hba.conf entry for host .+$

ignoreregex = duration:

/etc/fail2ban/jail.d/local-postgresql.conf :

[local-postgresql]
enabled  = true
filter   = local-postgresql
action   = iptables[name=PostgreSQL, port=5432, protocol=tcp]
           sendmail-whois[name=PostgreSQL, dest=root@localhost]
logpath  = /var/log/postgresql/postgresql-9.3-main.log
maxretry = 3
    
por 28.01.2016 / 11:16
0

O Fail2ban é uma ferramenta poderosa, mas não confie que um filtro funcionará como está. Teste qualquer filtro usando a ferramenta failregex e lembre-se de evitar as aspas (ou seja, "admin" seja \ "admin \"). Por exemplo, testar a seguinte linha de failregex de filtro do meu /etc/log/postgresql/postgresql-9.3-main.log não funcionou para mim.

fail2ban-regex '2016-09-20 14:30:09 PDT FATAL:  password authentication failed for user "admin"' '<HOST>\(\d+\) FATAL:  password authentication failed for .+$'

O acima me deu

Failregex: 0 total

Eu tive que atualizar o failregex para corresponder ao formato de log.

fail2ban-regex '2016-09-20 14:30:09 PDT FATAL:  password authentication failed for user "admin"' 'FATAL:  password authentication failed for user \"<HOST>\"'

Isso me deu um resultado positivo.

Failregex: 1 total

O teste fail2ban-regex também pode ser implementado em arquivos de log inteiros.

fail2ban-regex /var/log/postgresql/postgresql-9.3-main.log /etc/fail2ban/filter.d/postgresql.local

O acima me deu o seguinte resultado positivo com o failregex atualizado.

Failregex: 169 total

    
por 21.09.2016 / 00:41