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.
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.
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.
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.
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.
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
| Archivo | Contenido | Efecto |
|---|---|---|
ssl_cert_file ($PGDATA/server.crt) | certificado del servidor | enviado al cliente para indicar la identidad del servidor |
ssl_key_file ($PGDATA/server.key) | clave privada del servidor | demuestra que el certificado del servidor fue enviado por el propietario; no indica que el propietario del certificado sea de confianza |
| ssl_ca_file | autoridades de certificación de confianza | comprueba que el certificado del cliente esté firmado por una autoridad de certificación de confianza |
| ssl_crl_file | certificados revocados por autoridades de certificación | el 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.
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.