PostgreSQL_OpenSSL
Click here to load reader
-
Upload
lu-ramirez -
Category
Documents
-
view
22 -
download
1
Transcript of PostgreSQL_OpenSSL
PostgreSQL y el uso de SSLMar, 01/12/2009 - 18:46 — rafaelma
En este artículo vamos a explicar como podemos configurar PostgreSQL 8.4 para
realizar conexiones seguras a nuestras bases de datos utilizando SSL.
Vamos a ver dos aspectos diferentes e independientes en el tema de las conexiones
seguras, el primero es como cifrar el tráfico entre nuestros clientes y el servidor, y el
segundo, como autentificar a los clientes/usuarios mediante certificados digitales.
Con el cifrado del tráfico entre los clientes y el servidor evitamos que alguien pueda interceptar el
tráfico de red y conseguir los datos que viajan por la conexión. Con la autentificación por medio de
certificados digitales evitamos que clientes/usuarios que no tengan instalado el certificado
correspondiente puedan conectarse a nuestro servidor, incluso si lo hacen cifrando el tráfico de red.
PostgreSQL soporta nativamente el uso de conexiones SSL para cifrar las comunicaciones, el único
requerimiento es tener OpenSSL instalado en nuestro servidor y PostgreSQL compilado con soporte
SSL. El soporte SSL durante la compilación se consigue usando el parametro --with-
ssl con ./configure antes de compilar. Más información sobre la instalación desde el código fuente se
puede encontrar en el artículo Instalación e inicialización básica de PostgreSQL desde el código
fuente. Los paquetes binarios disponibles para Unix/Linux y Windows suelen ser compilados con
soporte SSL.
Para activar el soporte SSL en un sistema que cumple los requerimientos que hemos nombrado hay
que hacer tres cosas:
•Definir el parámetro ssl en el fichero postgresql.conf
•Instalar el certificado de nuestro servidor, la clave privada correspondiente, el certificado CA
y un fichero crl con la lista de certificados revocados, en el directorio de datos PGDATA
•Arrancar de nuevo el servidor PostgreSQL
Una vez que tenemos el soporte SSL instalado y activado hay que configurar en el
ficheropg_hba.conf que conexiones van a utilizar SSL para cifrar el tráfico y/ó autentificarse con un
certificado digital.
Una cosa buena de PostgreSQL en lo referente al uso de SSL para cifrar las conexiones, es que el
servidor PostgreSQL escucha por conexiones estándares (no-SSL) y SSL por el mismo puerto y
negocia automáticamente con el cliente el uso de SSL ó no dependiendo de lo definido en pg_hba.conf.
Vamos a ver por pasos como configurar todo lo necesario.
Certificados
Lo primero que necesitamos es el certificado SSL que vamos a usar en nuestro servidor, la
correspondiente clave privada, el certificado CA y un fichero crl.
Normalmente los certificados digitales se suelen comprar a una entidad emisora y están vigentes por
un determinado periodo de tiempo. Estos certificados están firmados por unaautoridad de
certificación (CA) la cual es una entidad de confianza, responsable de emitir y revocar certificados
digitales.
Si las conexiones que van a usar SSL son internas y locales, no hace falta pagar a una autoridad de
certificación para que emita y firme nuestros certificados con su certificado CA. Nosotros mismos
podemos generar el certificado y firmarlo como un CA local. Para esto tenemos que hacer lo
siguiente:
•Instalar la infraestructura necesaria para ser una CA local
•Generar un certificado y llave CA que utilizaremos para firmar los certificados que vayamos a
usar en nuestros sistemas
•Generar el certificado y la llave que el servidor PostgreSQL necesita
•Firmar nuestro certificado del servidor con el CA que hemos generado
Instalar la infraestructura necesaria para ser una CA local
Primero tenemos que instalar openssl en nuestro ordenador, para esto podemos utilizar el sistema
de instalación por defecto de nuestro sistema operativo.
A continuación creamos como root el directorio que albergará la infraestructura CA:
# mkdir -m 0755 /etc/CA_local
Después creamos los subdirectorios que necesitaremos dentro de /etc/CA_local
# mkdir -m 0755 \
/etc/CA_local \
/etc/CA_local/private \
/etc/CA_local/certs \
/etc/CA_local/newcerts \
/etc/CA_local/crl
Ahora copiamos el fichero de configuración global de openssl (/etc/ssl/openssl.cnf en mi sistema) a
nuestro directorio CA_local.
# cp /etc/ssl/openssl.cnf /etc/CA_local/openssl.local.cnf
# chmod 0600 /etc/CA_local/openssl.local.cnf
A continuación teneis que actualizar el fichero /etc/CA_local/openssl.local.cnf. En la sección [ CA_default ],
cambiar los parámetros dir, certificate y private_key a lo siguiente:
dir = /etc/CA_local # Where everything is kept
certificate = $dir/certs/local_ca.crt # The CA certificate
private_key = $dir/private/local_ca.key # The private key
Tambien necesitamos tres ficheros extras que podemos crear de la siguiente manera:
# touch /etc/CA_local/index.txt
# echo '01' > /etc/CA_local/serial
# echo '01' > /etc/CA_local/crlnumber
Generar un certificado y llave CA y un fichero crl con la lista de certificados revocados
Primero vamos a crear un certificado CA que utilizaremos para firmar los certificados que usemos
localmente en nuestros sistemas.
# cd /etc/CA_local/
# openssl req -config openssl.local.cnf -new -x509 -extensions v3_ca \
-keyout private/local_ca.key -out certs/local_ca.crt -days 1825
Este último comando creará un certificado CA autofirmado con una validez de 5 años. Tendreis que
definir una contraseña para la llave privada CA (no olvidar esta contraseña!! ya que se necesitará
cada vez que usemos el certificado local CA) y rellenar algunos parámetros para vuestro sistema. En
mi sistema de ejemplo, estos son los datos introducidos.
Generating a 1024 bit RSA private key
...................++++++
writing new private key to 'private/local_ca.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be
incorporated into your certificate request. What you are about to
enter is what is called a Distinguished Name or a DN. There are quite
a few fields but you can leave some blank For some fields there will
be a default value, If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:NO
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Oslo
Organization Name (eg, company) [Internet Widgits Pty Ltd]:PostgreSQL-es.org
Organizational Unit Name (eg, section) []:.
Common Name (eg, YOUR name) []:postgresql-es.org
Email Address []:[email protected]
Una vez realizado estos pasos se habrán creado dos ficheros en vuestro sistema:
•/etc/CA_local/certs/local_ca.crt: Certificado CA local. Se puede distribuir públicamente y todo el
mundo puede acceder al mismo sin problemas de seguridad.•/etc/CA_local/private/local_ca.key: Llave CA privada. Se tiene que restringir el acceso a la misma
( chmod 0400 /etc/CA_local/private/local_ca.key) y no se puede distribuir públicamente.
El fichero CRL (Certificate Revocation List) con la lista de certificados revocados por este CA lo
podeis crear con:
openssl ca -config openssl.local.cnf -keyfile private/local_ca.key \
-cert certs/local_ca.crt -gencrl -out crl/local_ca.crl
Y comprobarlo y verificarlo con:
openssl crl -in crl/local_ca.crl -text -noout
Crear una solicitud de certificado para el servidor
Tenemos que generar una solicitud de certificado (server.csr) para generar un certificado que se
pueda usar en nuestro servidor. Para ello podemos utilizar los siguientes comandos:
# cd /etc/CA_local/
# openssl req -config openssl.local.cnf -new -nodes \
-keyout private/ejemplo.postgresql-es.org.key \
-out ejemplo.postgresql-es.org.csr -days 730
Con esto generamos la solicitud de certificado con una validez de 2 años, después de rellenar
algunos parámetros de nuestro sistema. En nuestro ejemplo, estos son los datos introducidos.
Generating a 1024 bit RSA private key
.........++++++
............................++++++
writing new private key to 'private/server.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:NO
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Oslo
Organization Name (eg, company) [Internet Widgits Pty Ltd]:PostgreSQL-es.org
Organizational Unit Name (eg, section) []:.
Common Name (eg, YOUR name) []:ejemplo.postgresql-es.org
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Los parámetros a rellenar más importantes son "Common Name" y "Email Address". "Common
Name" debería de tener el nombre de la máquina que va a estar utilizando el certificado, "Email
Address" es la dirección de contacto de vuestro sistema.
No teneis que introducir nada en los parametros "challenge password" y "optional company name"
del final. Hemos utilizado el parámetro -nodes para no tener que proteger nuestra llave privada con
una contraseña y no tener que escribir una contraseña cada vez que arranquemos un servicio que
use el certificado. Por ello es muy importante no perder ó publicar el fichero con la llave privada.
Firmar nuestra solicitud de certificado con nuestro CA para generar el certificado final
Una vez que tenemos la solicitud de certificado (server.csr), vamos a firmarla con nuestro certificado
CA. Para ello utilizamos este comando:
# cd /etc/CA_local/
# openssl ca -config openssl.local.cnf -policy policy_anything \
-days 730 -out certs/ejemplo.postgresql-es.org.crt \
-infiles ejemplo.postgresql-es.org.csr
Tendremos que utilizar la contraseña que usamos cuando creamos el certificado CA para terminar de
firmar nuestro certificado:
Using configuration from openssl.local.cnf
Enter pass phrase for /etc/CA_local/private/local_ca.key:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Nov 30 20:05:18 2009 GMT
Not After : Nov 30 20:05:18 2011 GMT
Subject:
countryName = NO
localityName = Oslo
organizationName = PostgreSQL-es.org
commonName = ejemplo.postgresql-es.org
emailAddress = [email protected]
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
58:40:FC:0A:85:C7:58:9D:9D:66:8A:7F:0A:CB:46:65:CD:A2:92:20
X509v3 Authority Key Identifier:
keyid:54:11:C7:CD:1A:1D:54:01:42:D1:FC:1A:1A:DD:ED:B5:5E:E6:89:BF
Certificate is to be certified until Nov 30 20:05:18 2011 GMT (730 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Vamos a asegurar mejor la clave privada del certificado. Este fichero es privado y no se debe de
distribuir:
# chown root:root /etc/CA_local/private/ejemplo.postgresql-es.org.key
# chmod 0400 /etc/CA_local/private/ejemplo.postgresql-es.org.key
Podeis ver la información contenida en el certificado con este comando:
# cd /etc/CA_local/
# openssl x509 -in certs/ejemplo.postgresql-es.org.crt -noout -text
Y comprobar y verificar el certificado con el siguiente comando:
# cd /etc/CA_local/
# openssl verify -purpose sslserver -CAfile /etc/CA_local/certs/local_ca.crt \
/etc/CA_local/certs/ejemplo.postgresql-es.org.crt
El fichero de solicitud de certificado ya no lo necesitais y lo podeis borrar
# rm /etc/CA_local/ejemplo.postgresql-es.org.csr
Esto es todo lo que necesitais saber sobre certificados si quereis hacerlo todo vosotros para uso
local/privado. Al final de todo el proceso tendreis los siguientes ficheros en el directorio /etc/CA_local
•/etc/CA_local/certs/local_ca.crt: Certificado CA local que podeis utilizar para firmar otros
certificados.•/etc/CA_local/certs/ejemplo.postgresql-es.org.crt: Certificado firmado por el CA local que vamos a usar
en ejemplo.postgresql-es.org•/etc/CA_local/private/local_ca.key: Llave privada del certificado CA local
•/etc/CA_local/private/ejemplo.postgresql-es.org.key: Llave privada del certificado firmado por el CA local
y que vamos a usar en ejemplo.postgresql-es.org•/etc/CA_local/crl/local_ca.crl: Fichero CRL (Certificate Revocation List) con la lista de certificados
revocados
Configuración de PostgreSQL para usar SSL
Una vez que tenemos todos los certificados que necesitamos, tenemos que configurar PostgreSQL
para activar y usar SSL.
Lo primero que hacemos es copiar los ficheros /etc/CA_local/certs/ejemplo.postgresql-
es.org.crt, /etc/CA_local/private/ejemplo.postgresql-es.org.key, /etc/CA_local/certs/local_ca.crt y/etc/CA_local/crl/local_ca.crl al
directorio de datos de nuestra instalación PostgreSQL. En nuestro ejemplo tenemos el directorio de
datos en /var/pgsql-8.4/data
# cp /etc/CA_local/certs/ejemplo.postgresql-es.org.crt \
/var/pgsql-8.4/data/server.crt
# cp /etc/CA_local/private/ejemplo.postgresql-es.org.key \
/var/pgsql-8.4/data/server.key
# cp /etc/CA_local/certs/local_ca.crt /var/pgsql-8.4/data/root.crt
# cp /etc/CA_local/crl/local_ca.crl /var/pgsql-8.4/data/root.crl
# chown postgres:postgres /var/pgsql-8.4/data/server.*
# chown postgres:postgres /var/pgsql-8.4/data/root.*
# chmod 0400 /var/pgsql-8.4/data/server.*
# chmod 0400 /var/pgsql-8.4/data/root.*
Después tenemos que actualizar nuestro fichero /var/pgsql-8.4/data/postgresql.conf. Tenemos que cambiar
el valor del parametro ssl.
ssl = on
Y arrancar PostgreSQL de nuevo usando el script det arranque de nuestro sistema. En nuestro
servidor ejemplo ejecutamos esto:
/etc/init.d/postgresql stop
/etc/init.d/postgresql start
Ahora actualizamos el fichero /var/pgsql-8.4/data/pg_hba.conf con esta linea:
hostssl all postgres 127.0.0.1/32 md5
Y volvemos a leer el fichero de configuración para activar los cambios.
/etc/init.d/postgresql reload
Si hemos hecho las cosas correctamente deberiamos de poder conectar con nuestro servidor
PostgreSQL via SSL y cifrando nuestro tráfico. La linea que hemos definido en pg_hba.conf define
que el usuario postgres puede conectarse desde 127.0.0.1/32 a todas las bases de datos de nuestra
instalacion solamente via SSL y escribiendo la clave de acceso (Teneis que haber definido la clave del
usuario postgres con antelación para que esto funcione). Vosotros tendreis que configurar vuestro
sistema para dar acceso a los clientes de vuestro sistema.
postgres@core4:~$ psql -h 127.0.0.1
password:
psql (8.4.1)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
postgres=#
La linea SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256) que se muestra al conectar con el servidor nos
indica que la conexión está cifrada via SSL.
Si habeis llegado hasta aquí, ya teneis el servidor PostgreSQL configurado para recibir conexiones
via SSL y cifrar el tráfico entre los clientes y el servidor de bases de datos.
Autentificar a los clientes mediante certificados SSL
También podemos utilizar certificados digitales para autentificar a los clientes que se quieran
conectar con nuestro servidor. De esta manera solamente podrán conectarse a nuestro servidor los
clientes que tengan instalado un certificado que esté firmado por una autoridad de certificación (CA)
registrada en el fichero /var/pgsql-8.4/data/root.crt de nuestro servidor.
Para activar esta posibilidad lo primero que tenemos que hacer es crear un certificado para nuestro
cliente y firmarlo con nuestro certificado CA local. A continuación debemos crear un subdirectorio
(~/.postgresql/) en el directorio HOME del usuario que va a ejecutar el programa cliente, y para
terminar tenemos que copiar a este subdirectorio cuatro ficheros. En nuestro ejemplo creamos el
directorio /home/postgresql/.postgresql y copiamos en el los ficheros necesarios:
•/home/postgresql/.postgresql/postgresql.crt: Certificado firmado por el CA local que hemos creado
para nuestro cliente•/home/postgresql/.postgresql/postgresql.key: Llave privada del certificado creado para el cliente
•/home/postgresql/.postgresql/root.crt: Certificado CA local utilizado para firmar el certificado creado
para el cliente•/home/postgresql/.postgresql/root.crl: Fichero CRL (Certificate Revocation List) con la lista de
certificados revocados
Definimos los permisos necesarios:
# chmod 0400 /home/postgresql/.postgresql/*
A continuación actualizamos el fichero /var/pgsql-8.4/data/pg_hba.conf con una linea similar a esta:
hostssl all postgres 127.0.0.1/32 md5 clientcert=1
Y leemos el fichero de configuración para activar los cambios.
/etc/init.d/postgresql reload
Los dos parámetros importantes en esta linea son hostssl y clientcert=1. De esta manera podemos
definir que la conexión se pueda realizar solamente desde clientes que tengan instalado un
certificado que esté firmado por una autoridad de certificación (CA) que reconozcamos. Si no
tuviesemos los ficheros necesarios en /home/postgresql/.postgresql/, nos daria un error al intentar
conectarnos.
# psql -h 127.0.0.1 -U postgres
psql: could not open certificate file "/home/postgres/.postgresql/postgresql.crt":
No such file or directory
FATAL: connection requires a valid client certificate
FATAL: no pg_hba.conf entry for host "127.0.0.1", user "postgres",
database "postgres", SSL off
Autentificar a los usuarios mediante certificados SSL
Hasta ahora hemos visto como encriptar el trafico de red y como autentificar a clientes con
certificados digitales. A partir de la versión 8.4.0 de PostgreSQL tambien se pueden utilizar
certificados digitales para autentificar a los usuarios que se quieran conectar con nuestro servidor.
Este tipo de autentificación se activa usando el metodo 'cert' en la opción método cuando definamos
el acceso en pg_hba.conf. Si usamos este método de autentificación no necesitaremos escribir ninguna
clave de acceso pero deberemos de proveer un certificado valido.
El atributo CN (lo que se define en 'Common Name (eg, YOUR name) []:') del certificado es el
atributo que se comprueba para ver si corresponde con el usuario con el que se intenta conectar. Si
el CN no es igual al usuario de la base de datos con el que se intenta conectar podemos usar mapas
de usuario en el servidor para hacer la conversión.
Lo primero que tenemos que hacer es crear un certificado para nuestro usuario ('Common Name
(eg, YOUR name) []: postgres') y firmarlo con nuestro certificado CA local. A continuación copiamos
este certificado y la llave privada
a/home/postgresql/.postgresql/postgresql.crt y /home/postgresql/.postgresql/postgresql.key en el ordenador cliente.
Después tenemos que actualizar el fichero /var/pgsql-8.4/data/pg_hba.conf con una linea similar a esta:
hostssl all postgres 127.0.0.1/32 cert
Y por último leemos el fichero de configuración para activar los cambios.
/etc/init.d/postgresql reload
Si no tuviesemos el certificado correcto instalado, el sistema nos daria un error similar al que se
obtiene cuando la autentificación con certificado del ordenador cliente falla.