Cómo activar SSL para conexiones PostgreSQL
Por defecto, todas las conexiones PostgreSQL son inseguras, lo que puede causar problemas de seguridad cuando se ejecutan en entornos de producción de alto tráfico. El cifrado SSL garantiza que los datos transferidos no sean interceptados por nadie en medio de una conexión.
Este tutorial te enseñará a habilitar SSL/TLS para las conexiones PostgreSQL.
Requisitos previos
- Un servidor Linux. Para nuestro tutorial, estamos ejecutando un servidor Ubuntu 22.04.
- Un usuario sudo no root.
- Un nombre de dominio completo (FQDN) como
postgresql.example.com
. - Asegúrate de que todo está actualizado.
$ sudo apt update $ sudo apt upgrade
- Pocos paquetes que necesite tu sistema.
$ sudo apt install curl nano software-properties-common apt-transport-https ca-certificates lsb-release ubuntu-keyring -y
Puede que algunos de estos paquetes ya estén instalados en tu sistema.
Paso 1 – Configurar el Cortafuegos
Antes de instalar ningún paquete, el primer paso es configurar el cortafuegos para que abra puertos para HTTP, HTTPS y PostgreSQL.
Comprueba el estado del cortafuegos.
$ sudo ufw status
Deberías ver algo como lo siguiente
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6)
Abre los puertos HTTP, HTTPS y PostgreSQL en el cortafuegos.
$ sudo ufw allow 5432 $ sudo ufw allow http $ sudo ufw allow https
Comprueba de nuevo el estado para confirmarlo.
$ sudo ufw status Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere 80/tcp ALLOW Anywhere 443 ALLOW Anywhere 5432 ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) 80/tcp (v6) ALLOW Anywhere (v6) 443 (v6) ALLOW Anywhere (v6) 5432 (v6) ALLOW Anywhere (v6)
Paso 2 – Instala PostgreSQL 14
Ubuntu 22.04 incluye PostgreSQL 14 por defecto. Para instalarlo, ejecuta el siguiente comando.
$ sudo apt install postgresql postgresql-contrib
El paquete postgresql-contrib
contiene algunas utilidades adicionales.
También puedes utilizar el repositorio oficial APT de PostgreSQL para realizar la instalación. Ejecuta el siguiente comando para añadir la clave GPG de PostgreSQL.
$ curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | sudo tee /usr/share/keyrings/postgresql-key.gpg >/dev/null
Añade el repositorio APT a tu lista de fuentes.
$ sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/postgresql-key.gpg arch=amd64] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
Actualiza el repositorio del sistema.
$ sudo apt update
Ahora, puedes instalar PostgreSQL utilizando el comando mencionado anteriormente.
Comprueba el estado del servicio PostgreSQL.
$ sudo systemctl status postgresql ? postgresql.service - PostgreSQL RDBMS Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled) Active: active (exited) since Mon 2022-12-12 00:01:06 UTC; 19s ago Main PID: 3497 (code=exited, status=0/SUCCESS) CPU: 1ms Dec 12 00:01:06 postgresql systemd[1]: Starting PostgreSQL RDBMS... Dec 12 00:01:06 postgresql systemd[1]: Finished PostgreSQL RDBMS.
Puedes ver que el servicio está habilitado y funcionando por defecto.
Establece la contraseña de la cuenta postgres
.
$ sudo -i -u postgres psql -c "ALTER USER postgres PASSWORD '<new_password>';"
Paso 3 – Instalar SSL
Para instalar un certificado SSL utilizando Let’s Encrypt, necesitamos descargar la herramienta Certbot. Para ello utilizaremos el instalador de paquetes Snapd. Ubuntu 22.04 viene preinstalado con Snap.
Asegúrate de que tu versión de Snapd está actualizada.
$ sudo snap install core $ sudo snap refresh core
Instala Certbot.
$ sudo snap install --classic certbot
Utiliza el siguiente comando para asegurarte de que se ejecuta el comando Certbot, creando un enlace simbólico al directorio /usr/bin
.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Genera un certificado SSL.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d postgresql.example.com
El comando anterior descargará un certificado en el directorio /etc/letsencrypt/live/postgresql.example.com
de tu servidor.
Genera un certificado de grupo Diffie-Hellman.
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
Paso 4 – Configurar la renovación de Certbot para PostgreSQL
PostgreSQL no tiene permiso para acceder a los certificados de la carpeta Let’s Encrypt, por lo que no podemos decirle que utilice directamente los certificados de la carpeta. La alternativa es copiar los certificados en el directorio PostgreSQL, pero esto sólo funciona temporalmente, ya que caducarán y tendrás que volver a copiarlos manualmente.
El mejor método es utilizar un gancho de renovación que se ejecute automáticamente en cada renovación y realice las operaciones de copia.
Busca el directorio de datos PostgreSQL.
$ sudo -i -u postgres psql -U postgres -c 'SHOW data_directory'
Crea el archivo del gancho de renovación y ábrelo para editarlo.
$ sudo nano /etc/letsencrypt/renewal-hooks/deploy/postgresql.sh
Pega en él el siguiente código.
#!/bin/bash umask 0177 DOMAIN=postgresql.example.com DATA_DIR=/var/lib/postgresql/15/main cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem $DATA_DIR/server.crt cp /etc/letsencrypt/live/$DOMAIN/privkey.pem $DATA_DIR/server.key chown postgres:postgres $DATA_DIR/server.crt $DATA_DIR/server.key # only for SELinux - CentOS, Red Hat # chcon -t postgresql_db_t $DATA_DIR/server.crt $DATA_DIR/server.key
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida.
Haz que el archivo sea ejecutable.
$ sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/postgresql.sh
Paso 5 – Configurar PostgreSQL
Busca la ruta del archivo de configuración de PostgreSQL.
$ sudo -i -u postgres psql -U postgres -c 'SHOW config_file'
Abre el archivo para editarlo.
$ sudo nano /etc/postgresql/15/main/postgresql.conf
Localiza la sección Configuración de la conexión y descomenta la variable listen_address
y cambia su valor a *
. Asegúrate de que tiene el siguiente aspecto.
listen_address = '*' # what IP address(es) to listen on;
Localiza la sección SSL y edita el archivo para que coincida con los siguientes valores.
ssl = on ssl_cert_file = 'server.crt' ssl_key_file = 'server.key' ssl_prefer_server_ciphers = on ssl_dh_params_file = '/etc/ssl/certs/dhparam.pem'
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Paso 6 – Configurar la conexión PostgreSQL
Abre el archivo /etc/postgresql/15/main/pg_hba.conf
para editarlo.
$ sudo nano /etc/postgresql/15/main/pg_hba.conf
Añade la siguiente línea para activar SSL para PostgreSQL.
hostssl all all 0.0.0.0/0 scram-sha-256
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Paso 7 – Renovar Certificado
Ejecuta el siguiente comando para realizar una renovación forzada. Esto activará el script de despliegue que copia los certificados en la ubicación correcta para que PostgreSQL los utilice.
$ sudo certbot renew --force-renewal
Comprueba que los certificados se copian en el directorio de datos de PostgreSQL.
$ sudo ls /var/lib/postgresql/15/main/
Verás la siguiente salida que te mostrará los certificados.
base pg_dynshmem pg_notify pg_snapshots pg_subtrans PG_VERSION postgresql.auto.conf server.crt global pg_logical pg_replslot pg_stat pg_tblspc pg_wal postmaster.opts server.key pg_commit_ts pg_multixact pg_serial pg_stat_tmp pg_twophase pg_xact postmaster.pid
Reinicia PostgreSQL para aplicar los cambios.
$ sudo systemctl restart postgresql
Paso 8 – Prueba la conexión
Conéctate a la base de datos desde otra máquina con el cliente PostgreSQL instalado.
$ psql -d "dbname=postgres sslmode=require" -h postgresql.example.com -U postgres
Deberías ver el siguiente prompt de PostgreSQL. Estamos utilizando un cliente con PostgreSQL 14 por lo tanto, verás una advertencia sobre versiones incompatibles.
Password for user postgres: psql (14.5 (Ubuntu 14.5-0ubuntu0.22.04.1), server 15.1 (Ubuntu 15.1-1.pgdg22.04+1)) WARNING: psql major version 14, server major version 15. Some psql features might not work. SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. postgres=#
Esto confirma que la conexión SSL se ha realizado correctamente.
Sal del intérprete de comandos.
postgres=# \q
Si tu aplicación utiliza una cadena de conexión, utilízala con el siguiente formato para una conexión SSL.
postgres://user:[email protected]:5432/database_name?sslmode=require
Puedes cambiar el modo SSL a verify-full
o verify-ca
si tienes el certificado raíz de Let’s encrypt disponible en la ubicación /var/lib/postgresql/.postgresql
en el lado del cliente.
Crea el directorio /var/lib/postgresql/.postgresql
.
$ sudo mkdir -p /var/lib/postgresql/.postgresql
El certificado raíz de Let’s Encrypt es ISRG Root X1 que se encuentra en el servidor en la ubicación /usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
.
Copia el certificado raíz en el directorio /var/lib/postgresql/.postgresql
.
$ sudo cp /usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt /var/lib/postgresql/.postgresql/root.crt
Prueba la conexión utilizando el modo verify-full
o verify-ca
y deberías ver una conexión correcta.
Paso 9 – Comprueba los Clientes
Accede al shell PostgreSQL del servidor.
$ sudo -i -u postgres psql
Ejecuta el siguiente comando SQL para comprobar los clientes conectados.
SELECT ssl.pid, usename, datname, ssl, ssl.version, ssl.cipher, ssl.bits, client_addr FROM pg_catalog.pg_stat_ssl ssl, pg_catalog.pg_stat_activity activity WHERE ssl.pid = activity.pid;
Deberías ver una salida similar.
pid | usename | datname | ssl | version | cipher | bits | client_addr ------+----------+----------+-----+---------+------------------------+------+---------------- 5126 | postgres | postgres | t | TLSv1.3 | TLS_AES_256_GCM_SHA384 | 256 | 122.161.84.220 5154 | postgres | postgres | f | | | | (2 rows)
Esto confirma la conexión del cliente desde el lado del servidor.
Conclusión
Con esto concluye el tutorial sobre la activación de SSL en las conexiones PostgreSQL. Si tienes alguna pregunta, publícala en los comentarios a continuación.