jueves, 8 de mayo de 2008

Como configurar un servidor seguro con OpenSSL

Aqui os dejo un tutorial paso a paso que he hecho para configurar un servidor Apache con OpenSSL, crear una autoridad certificadora capaz de emitir certificados y generar certificados tanto para el servidor como para los clientes. Espero que os quede claro:


1.- Instalar OpenSSl en el servidor (si no esta ya)

apt-get install openssl

2.- Crear la estructura de directorios que necesitamos (yo lo he hecho en /home/ pero eso depende del servidor. Como es en local, donde queramos)

mkdir ca ca/private ca/certs ca/conf

3.- Para tener un numero de serie que controle el numero de certificados emitimos

cd /ca
echo '01' > serial
touch index.txt

(Posteriormente declararemos index.txt como nuestra base de datos de certificados)

4.- Crear la Autoridad certificadora

4.1.- Creamos el fichero de configuracion en ca/conf:
cd /ca/conf
gedit caconfig.cnf

4.2.- Copiamos esta estructura con nuestra informacion en caconfig.cnf:
(también podemos actualizar el que viene por defecto en el servidor como openssl.cnf para ahorrarnos escribir tanto) -> rellenarlo con nuestros datos


#…………………………….
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /home/ca
serial = $dir/serial
database = $dir/index.txt
new_certs_dir = $dir/certs
certificate = $dir/certs/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 365
default_md = md5
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 1024 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = md5 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
# Variable name Prompt string
#————————- ———————————-
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64
# Default values for the above, for consistency and less typing.
# Variable name Value
#———————— ——————————
0.organizationName_default = My Organization
localityName_default = NEW YORK
stateOrProvinceName_default = NEW YORK
countryName_default = US
emailAddress_default = email@mydomain.net
[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash

5.- Generar la clave de la AC y su certificado raiz.
OJO este paso es importante: aqui se nos pedira informacion del nombre de la CA y tiene que ser siempre igual para todos los certificados, asi que hay que ponerse de acuerdo a la hora de escribirlo y ademas hay que pensar una frase generadora de la clave que sea larga y dificililla.

openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out certs/cacert.pem -days 365 -config conf/caconfig.cnf

Esto genera un certificado valido por 365 dias que se llama cacert.pem en la carpeta "certs" y una clave privada RSA cakey.pem que se guarda en el directorio "private"

6.- Crear el certificado del servidor cliente

Aqui creamos una clave privada como cliente y una petición de firma para la CA. Aquí tenemos que poner el nombre del servidor, que sera www.miTiendaChunga.com o el que sea.

6.1.- Nos vamos a nuestro directorio

cd /home/ca

6.2.- Lanzamos el comando de petición de certificado a la CA

openssl req -new -nodes -out certs/localhost.req.pem -keyout private/localhost.key.pem -config conf/caconfig.cnf

Y esto genera la clave en "private" y la peticion del certificado en "certs"

6.3.- Ahora, como CA, firmamos el certificado (motivos de seguridad) y generamos el certificado definitivo, actualizando la base de datos de certificados

openssl ca -in localhost.req.pem -notext -out certs/localhost.cert -config conf/caconfig.cnf

[A partir de aquí ya no es realmente necesario]
8.- Los certificados generados tienen la extension .pem. Para que sean mas manejables y compatibles con los navegadores deberian tener la extension .crt, asi que los cambiamos:

cd /home/ca

rename 's/\.pem/\.crt/' *

9.- A la hora de la implementacion real en el servidor, habria que llevar los certificados y claves a las carpetas correctas, ssl.key y ssl.crt y actualizar el fichero de configuracion del servidor, que debe acabar con algo asi como "ssl.conf". En caso de estar usando Lampp, está en /opt/lampp/etc/extra/httpd-ssl.conf. Esto es necesarios -> la creacion de un servidor virtual.
Habria que escribir algo asi: (esto es solo un ejemplo) [la ip del localhost es 127.0.0.1 pero una real seria de la forma 192.168.1.1]
NameVirtualHost *:443 #para que se active cuando se acceda por el puerto seguro

DocumentRoot /var/www/html
ServerName 127.0.0.1
ServerAdmin someone@your.domain

ErrorLog /etc/httpd/logs/ssl_error_log
TransferLog /etc/httpd/logs/ssl_access_log
SSLEngine On
SSLCertificateFile /opt/lampp/etc/ssl.crt/miCertificadoDelServidor.crt
SSLCertificateKeyFile /opt/lampp/etc/ssl.key/miClaveDelServidor.key

Ojo: Hay que reiniciar el servidor (/opt/lampp/lampp restart ) despues modificar los ficheros de configuracion

Nota: es MUY!!! importante comprobar que en un documento de configuracion existe una linea que ponga "Listen 443". Si no, debemos añadirla

Aqui hay un truco bastante importante que puede servirnos para redireccionar una url accedida como http a un https. Yo lo he probado y funciona:

Escribimos en la pagina, en vez de todo el html que contuviera, las siguientes lineas en la cabecera:

[Entre las etiquetas de apertura y cierre html]

MENOR_QUE
meta http-equiv="refresh" content="0;url=https://localhost/web_prueba/contacto_seguro.html"
MAYOR_QUE

(lo escribo así porque blogger no me deja escribir html:
MENOR_QUE es "<" y MAYOR_QUE es ">"
)


Y esto nos redirecciona a la web segura, que contiene todo el codigo html que tenia el anterior, pero emitiendo nuestro certificado.


Otra cosa interesante es (cito literalmente de http://www.linuxtotal.com.mx/ssl_apache.html):

"Si quieres evitar que a tus clientes cada vez que ingresen a tu sitio salga el molesto diálogo que pide aceptar el certificado, la única solución es que distribuyas el archivo cacert.pem, recuerda que este archivo es el que te identifica como una autoridad certificadora. Lo puedes poner a descarga desde tu propio sitio, o mandarlo por correo, como sea. Cuando el cliente lo tenga en su equipo deberá importarlo dentro del browser o navegador. Todos los navegadores en sus preferencias o herramientas tienen una opción de certificados y desde ahí existe un botón importar para realizar esto."


[Informacion extraida y traducida de
http://codeghar.wordpress.com/2008/03/17/create-a-certificate-authority-and-certificates-with-openssl/
http://www.flatmtn.com/article/setting-openssl-create-certificates#SSLCert-8
http://www.eclectica.ca//howto/ssl-cert-howto.php
https://help.ubuntu.com/7.10/server/C/httpd.html#https-configuration
http://www.linuxtotal.com.mx/ssl_apache.html
]


Espero que te haya sido util. Si te ha gustado, deja un comentario
Un saludo

6 comentarios:

Anónimo dijo...

suena bastante interezante pero como no se nada de programacion bueno, te felicito yo andaba buscando como instalar un servidor donde se conecten algunos amigos y me degen sus datos para contactarlos se conecten a la red inalambrica pero no puedan navegar por internet hasta que yo se los autorise un saludo cordial atte yashumashu@hotmail.com

Anónimo dijo...

Muy Bueno el material, podrias indicarnos como actualizar el openssl? muchas gracias..

Fandez dijo...

Buenas Elo950>
Primero gracias por dejar un comentario.
Despues: a que te refieres con actualizar el openssl? Cuando lo instales tendras la ultima version disponible.
Deja un comentario si no te refieres a eso.
Un saludo

Anónimo dijo...

Muy bien explicado, muchas gracias por este manual tan completo.

Fandez dijo...

Gracias a ti por el comentario.
Un saludo

Anónimo dijo...

Hola estimado Juan Carlos, muy bueno tu post. Tengo una duda, el cliente donde estoy necesita generar un certificado cuya OU con tiene acentos y caracteres especiales. Ejemplo OU=Diputació de Barcelona .Cuando los genero con OpenSSL a través del browser se ven caracteres basura. Existe alguna forma de generar los request para certificados con caracteres que no sean ASCII?

Mil gracias

El iberoamericano