Não é possível conectar ao soquete de domínio unix do PostgreSQL

5

Estou tentando conectar-me ao soquete de domínio Unix do PostgreSQL a partir de um aplicativo da Web PHP. Componentes relevantes do sistema:

  • CentOS 7 x64 (reforçado pelo SELinux)
  • postgresql93 9.3.5-2PGDG.rhel7
  • nginx 1.6.2-1.el7.ngx
  • php-common 5.4.16-23.el7_0.3
  • php-fpm 5.4.16-23.el7_0.3
  • php-pdo 5.4.16-23.el7_0.3
  • php-pgsql 5.4.16-23.el7_0.3

O PostgreSQL está escutando na porta padrão 5432 e não tenho problemas em usá-lo via TCP / IP em 127.0.0.1:5432, mas quando tento conectar ao seu soquete de domínio Unix, tenho o seguinte erro:

Cannot connect to database: SQLSTATE[08006] [7] could not connect to server:
No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

O arquivo /tmp/.s.PGSQL.5432 existe e eu posso conectar usando o psql :

$ psql -Uusername db_name
psql (9.3.5)
Type "help" for help.

db_name=>

Portanto, não deve haver problemas do lado do PostgreSQL. Ou tem?

Linha relevante de /var/lib/pgsql/9.3/data/pg_hba.conf :

local    all    username        trust

A mudança de local para o arquivo de soquete do domínio Unix em /var/lib/pgsql/9.3/data/postgresql.conf não ajudou:

unix_socket_directories = '/var/run/pgsql'

Não havia nada em /var/log/audit/audit.log , mas tentei desativar o SELinux, só para ter certeza:

# setenforce 0

Isso não ajudou, então não é o SELinux.

Linhas relevantes de strace de php-fpm :

[pid   882] socket(PF_LOCAL, SOCK_STREAM, 0) = 5
[pid   882] fcntl(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
[pid   882] fcntl(5, F_SETFD, FD_CLOEXEC) = 0
[pid   882] connect(5, {sa_family=AF_LOCAL, sun_path="/tmp/.s.PGSQL.5432"}, 110) = -1 ENOENT (No such file or directory)
[pid   882] close(5)                    = 0

O nome do arquivo está correto e, novamente, o arquivo /tmp/.s.PGSQL.5432 existe:

$ ls -l /tmp/.s.PGSQL.5432
srwxrwxrwx. 1 postgres postgres 0 Nov  1 09:47 /tmp/.s.PGSQL.5432

Parece que o processo do php-fpm não é chroot'ed:

# ls -l /proc/882/root
lrwxrwxrwx. 1 apache apache 0 Oct 31 19:54 /proc/882/root -> /

Neste ponto, não tenho mais ideias sobre onde o problema pode estar e agradeço qualquer ajuda.

    
por Sergii Bogomolov 01.11.2014 / 15:32

1 resposta

7

Eu resolvi o problema. A causa inicial foi no arquivo de serviço do systemd para php-fpm /usr/lib/systemd/system/php-fpm.service :

[Service]
PrivateTmp=true

Isso significa que o php-fpm não pôde ver /tmp/.s.PGSQL.5432 nem qualquer outra coisa localizada em / tmp . Para resolver o problema, mudei a localização do arquivo de soquete de domínio Unix do PostgreSQL com as seguintes etapas:

  • Crie um novo diretório / var / pgsql (observe a mudança do contexto do arquivo SELinux):

    # mkdir /var/pgsql
    # chown posgres:postgres /var/pgsql
    # chmod 0755 /var/pgsql
    # semanage fcontext -a -t httpd_var_run_t "/var/pgsql(/.*)?"
    # restorecon -R /var/pgsql
    
  • Remova o comentário e modifique o parâmetro unix_socket_directories em /var/lib/pgsql/9.3/data/postgresql.conf ( / tmp ainda é necessário para não quebrar o psql e outros programas):

    unix_socket_directories = '/tmp,/var/pgsql'
    

E aqui estava outra parte complicada ... Na postagem original, escrevi que tentei alterar a localização do arquivo de soquete do domínio Unix e realmente o fiz. O que eu perdi foi a mensagem de erro alterada. Eu pensei que o erro era o mesmo, mas não foi:

Error (256): Cannot connect to database: SQLSTATE[08006] [7] could not connect to
server: Permission denied
    Is the server running locally and accepting
    connections on Unix domain socket "/var/pgsql/.s.PGSQL.5432"?

Permissão negada - isso é algo que se pode combater.

Tudo funciona com

# setenforce 0

O problema é:

# audit2allow -a

#============= httpd_t ==============
allow httpd_t initrc_t:unix_stream_socket connectto;

E isso pode ser corrigido:

# audit2allow -a -M httpd_postgresql_unix_socket_connect
# semodule -i httpd_postgresql_unix_socket_connect.pp

Conteúdo do link :

module httpd_postgresql_unix_socket_connect 1.0;

require {
        type httpd_t;
        type initrc_t;
        class unix_stream_socket connectto;
}

#============= httpd_t ==============
allow httpd_t initrc_t:unix_stream_socket connectto;

Ativar o SELinux novamente:

# setenforce 1

E tudo funciona!

P.S. Eu ficaria feliz em saber se existe uma maneira de evitar o módulo SELinux personalizado alterando alguns contextos de arquivo ou booleanos. Pode ser o caso, porque o SELinux permite que o nginx use o soquete do domínio Unix do php-fpm ( /var/run/php5-fpm.sock ), mas por algum motivo bloqueia o uso do soquete do domínio Unix do PostgreSQL ( /var/pgsql/.s.PGSQL.5432 ).

    
por 03.11.2014 / 12:37