18.9. Conexiones TCP/IP seguras con SSL #

18.9.1. Configuración básica
18.9.2. Configuración de OpenSSL
18.9.3. Uso de certificados de cliente
18.9.4. Uso de archivos SSL del servidor
18.9.5. Creación de certificados

PostgreSQL tiene soporte nativo para utilizar conexiones SSL para cifrar las comunicaciones cliente/servidor para mayor seguridad. Esto requiere que OpenSSL esté instalado tanto en el sistema cliente como en el servidor, y que el soporte en PostgreSQL esté habilitado en el momento de la compilación (consulta Chapter 17).

Los términos SSL y TLS se utilizan a menudo indistintamente para referirse a una conexión cifrada segura mediante un protocolo TLS. Los protocolos SSL son los precursores de los protocolos TLS, y el término SSL todavía se utiliza para conexiones cifradas a pesar de que los protocolos SSL ya no son compatibles. SSL se utiliza indistintamente con TLS en PostgreSQL.

18.9.1. Configuración básica #

Con el soporte de SSL compilado, el servidor PostgreSQL se puede iniciar con el soporte para conexiones cifradas utilizando protocolos TLS habilitado configurando el parámetro ssl a on en postgresql.conf. El servidor escuchará tanto conexiones normales como SSL en el mismo puerto TCP, y negociará con cualquier cliente que se conecte sobre si usar SSL. Por defecto, esto queda a elección del cliente; consulta Section 20.1 sobre cómo configurar el servidor para requerir el uso de SSL para algunas o todas las conexiones.

Para iniciar en modo SSL, deben existir los archivos que contienen el certificado del servidor y la clave privada. Por defecto, se espera que estos archivos se llamen server.crt y server.key, respectivamente, en el directorio de datos del servidor, pero se pueden especificar otros nombres y ubicaciones utilizando los parámetros de configuración ssl_cert_file y ssl_key_file.

En sistemas Unix, los permisos de server.key deben impedir cualquier acceso a todos (world) o grupo; logra esto con el comando chmod 0600 server.key. Alternativamente, el archivo puede ser propiedad de root y tener acceso de lectura para el grupo (es decir, permisos 0640). Esa configuración está pensada para instalaciones donde los archivos de certificado y clave son gestionados por el sistema operativo. El usuario bajo el cual se ejecuta el servidor PostgreSQL debería entonces ser miembro del grupo que tiene acceso a esos archivos de certificado y clave.

Si el directorio de datos permite el acceso de lectura al grupo, es posible que los archivos de certificado deban ubicarse fuera del directorio de datos para cumplir con los requisitos de seguridad descritos anteriormente. Generalmente, el acceso de grupo se habilita para permitir que un usuario sin privilegios realice una copia de seguridad de la base de datos, y en ese caso el software de copia de seguridad no podrá leer los archivos de certificado y probablemente producirá un error.

Si la clave privada está protegida con una frase de contraseña (passphrase), el servidor solicitará la frase de contraseña y no se iniciará hasta que se haya introducido. El uso de una frase de contraseña por defecto deshabilita la capacidad de cambiar la configuración SSL del servidor sin reiniciar el servidor, pero consulta ssl_passphrase_command_supports_reload. Además, las claves privadas protegidas con frase de contraseña no se pueden usar en absoluto en Windows.

El primer certificado en server.crt debe ser el certificado del servidor porque debe coincidir con la clave privada del servidor. Los certificados de autoridades de certificación intermedias también se pueden añadir al archivo. Hacer esto evita la necesidad de almacenar certificados intermedios en los clientes, asumiendo que los certificados raíz e intermedios se crearon con extensiones v3_ca. (Esto establece la restricción básica del certificado de CA a true). Esto permite una expiración más sencilla de los certificados intermedios.

No es necesario añadir el certificado raíz a server.crt. En su lugar, los clientes deben tener el certificado raíz de la cadena de certificados del servidor.

18.9.2. Configuración de OpenSSL #

PostgreSQL lee el archivo de configuración de OpenSSL de todo el sistema. Por defecto, este archivo se llama openssl.cnf y se encuentra en el directorio reportado por openssl version -d. Este valor por defecto se puede invalidar configurando la variable de entorno OPENSSL_CONF con el nombre del archivo de configuración deseado.

OpenSSL admite una amplia gama de cifrados (ciphers) y algoritmos de autenticación, de variada robustez. Aunque se puede especificar una lista de cifrados en el archivo de configuración de OpenSSL, puedes especificar cifrados específicamente para su uso por parte del servidor de bases de datos modificando ssl_ciphers en postgresql.conf.

Note

Es posible tener autenticación sin la sobrecarga del cifrado utilizando los cifrados NULL-SHA o NULL-MD5. Sin embargo, un intermediario (man-in-the-middle) podría leer y transmitir las comunicaciones entre el cliente y el servidor. Además, la sobrecarga del cifrado es mínima en comparación con la sobrecarga de la autenticación. Por estas razones, no se recomiendan los cifrados NULL.

18.9.3. Uso de certificados de cliente #

Para exigir que el cliente suministre un certificado de confianza, coloca los certificados de las autoridades de certificación (CA) raíz en las que confíes en un archivo en el directorio de datos, establece el parámetro ssl_ca_file en postgresql.conf al nuevo nombre de archivo, y añade la opción de autenticación clientcert=verify-ca o clientcert=verify-full a la(s) línea(s) hostssl correspondiente(s) en pg_hba.conf. Entonces se solicitará un certificado al cliente durante el inicio de la conexión SSL. (Consulta Section 32.19 para obtener una descripción de cómo configurar certificados en el cliente).

Para una entrada hostssl con clientcert=verify-ca, el servidor verificará que el certificado del cliente esté firmado por una de las autoridades de certificación de confianza. Si se especifica clientcert=verify-full, el servidor no solo verificará la cadena de certificados, sino que también comprobará si el nombre de usuario o su mapeo coincide con el cn (Common Name) del certificado proporcionado. Ten en cuenta que la validación de la cadena de certificados siempre está garantizada cuando se utiliza el método de autenticación cert (ver Section 20.12).

Los certificados intermedios que se enlazan con certificados raíz existentes también pueden aparecer en el archivo ssl_ca_file si deseas evitar almacenarlos en los clientes (asumiendo que los certificados raíz e intermedios se crearon con extensiones v3_ca). Las entradas de la Lista de Revocación de Certificados (CRL) también se comprueban si el parámetro ssl_crl_file o ssl_crl_dir está configurado.

La opción de autenticación clientcert está disponible para todos los métodos de autenticación, pero solo en las líneas de pg_hba.conf especificadas como hostssl. Cuando no se especifica clientcert, el servidor verifica el certificado del cliente con su archivo de CA solo si se presenta un certificado de cliente y la CA está configurada.

Existen dos enfoques para obligar a los usuarios a proporcionar un certificado durante el inicio de sesión.

El primer enfoque utiliza el método de autenticación cert para las entradas hostssl en pg_hba.conf, de modo que el certificado mismo se usa para la autenticación mientras que también proporciona seguridad en la conexión SSL. Consulta Section 20.12 para obtener más detalles. (No es necesario especificar ninguna opción clientcert explícitamente cuando se utiliza el método de autenticación cert). En este caso, el cn (Common Name) proporcionado en el certificado se comprueba con el nombre de usuario o un mapeo aplicable.

El segundo enfoque combina cualquier método de autenticación para entradas hostssl con la verificación de certificados de cliente estableciendo la opción de autenticación clientcert a verify-ca o verify-full. La primera opción solo obliga a que el certificado sea válido, mientras que la segunda también asegura que el cn (Common Name) en el certificado coincida con el nombre de usuario o un mapeo aplicable.

18.9.4. Uso de archivos SSL del servidor #

Table 18.2 resume los archivos que son relevantes para la configuración de SSL en el servidor. (Los nombres de archivo mostrados son nombres por defecto. Los nombres configurados localmente podrían ser diferentes).

Table 18.2. Uso de archivos SSL del servidor

ArchivoContenidoEfecto
ssl_cert_file ($PGDATA/server.crt)certificado del servidorenviado al cliente para indicar la identidad del servidor
ssl_key_file ($PGDATA/server.key)clave privada del servidordemuestra que el certificado del servidor fue enviado por el propietario; no indica que el propietario del certificado sea de confianza
ssl_ca_fileautoridades de certificación de confianzacomprueba que el certificado del cliente esté firmado por una autoridad de certificación de confianza
ssl_crl_filecertificados revocados por autoridades de certificaciónel certificado del cliente no debe estar en esta lista

El servidor lee estos archivos al iniciar el servidor y cada vez que se recarga la configuración del servidor. En sistemas Windows, también se vuelven a leer cada vez que se crea un nuevo proceso backend para una nueva conexión de cliente.

Si se detecta un error en estos archivos al iniciar el servidor, el servidor se negará a iniciar. Pero si se detecta un error durante una recarga de configuración, los archivos se ignoran y se continúa utilizando la antigua configuración SSL. En sistemas Windows, si se detecta un error en estos archivos al inicio del backend, ese backend no podrá establecer una conexión SSL. En todos estos casos, la condición de error se informa en el registro del servidor.

18.9.5. Creación de certificados #

Para crear un certificado autofirmado simple para el servidor, válido por 365 días, utiliza el siguiente comando de OpenSSL, reemplazando dbhost.tudominio.com con el nombre de host del servidor:

openssl req -new -x509 -days 365 -nodes -text -out server.crt \
  -keyout server.key -subj "/CN=dbhost.tudominio.com"

Luego haz:

chmod og-rwx server.key

porque el servidor rechazará el archivo si sus permisos son más liberales que esto. Para obtener más detalles sobre cómo crear la clave privada y el certificado de tu servidor, consulta la documentación de OpenSSL.

Aunque se puede utilizar un certificado autofirmado para pruebas, en producción se debe utilizar un certificado firmado por una autoridad de certificación (CA) (generalmente una CA raíz empresarial).

Para crear un certificado de servidor cuya identidad pueda ser validada por los clientes, primero crea una solicitud de firma de certificado (CSR) y un archivo de clave pública/privada:

openssl req -new -nodes -text -out root.csr \
  -keyout root.key -subj "/CN=root.tudominio.com"
chmod og-rwx root.key

Luego, firma la solicitud con la clave para crear una autoridad de certificación raíz (utilizando la ubicación por defecto del archivo de configuración de OpenSSL en Linux):

openssl x509 -req -in root.csr -text -days 3650 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -signkey root.key -out root.crt

Finalmente, crea un certificado de servidor firmado por la nueva autoridad de certificación raíz:

openssl req -new -nodes -text -out server.csr \
  -keyout server.key -subj "/CN=dbhost.tudominio.com"
chmod og-rwx server.key

openssl x509 -req -in server.csr -text -days 365 \
  -CA root.crt -CAkey root.key -CAcreateserial \
  -out server.crt

server.crt y server.key deben almacenarse en el servidor, y root.crt debe almacenarse en el cliente para que el cliente pueda verificar que el certificado final (leaf) del servidor fue firmado por su certificado raíz de confianza. root.key debe almacenarse fuera de línea para su uso en la creación de futuros certificados.

También es posible crear una cadena de confianza que incluya certificados intermedios:

# raíz (root)
openssl req -new -nodes -text -out root.csr \
  -keyout root.key -subj "/CN=root.tudominio.com"
chmod og-rwx root.key
openssl x509 -req -in root.csr -text -days 3650 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -signkey root.key -out root.crt

# intermedio
openssl req -new -nodes -text -out intermediate.csr \
  -keyout intermediate.key -subj "/CN=intermediate.tudominio.com"
chmod og-rwx intermediate.key
openssl x509 -req -in intermediate.csr -text -days 1825 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -CA root.crt -CAkey root.key -CAcreateserial \
  -out intermediate.crt

# final (leaf)
openssl req -new -nodes -text -out server.csr \
  -keyout server.key -subj "/CN=dbhost.tudominio.com"
chmod og-rwx server.key
openssl x509 -req -in server.csr -text -days 365 \
  -CA intermediate.crt -CAkey intermediate.key -CAcreateserial \
  -out server.crt

server.crt e intermediate.crt deben concatenarse en un paquete de archivos de certificados y almacenarse en el servidor. server.key también debe almacenarse en el servidor. root.crt debe almacenarse en el cliente para que el cliente pueda verificar que el certificado final del servidor fue firmado por una cadena de certificados enlazada a su certificado raíz de confianza. root.key e intermediate.key deben almacenarse fuera de línea para su uso en la creación de futuros certificados.