- Estréllate y Arde - https://www.estrellateyarde.org -
HTTP seguro: SSL bajo Linux
SSL (Secure Socket Layer) es un protocolo cliente-servidor que permite conexiones seguras (confidencialidad, autentificación e integridad) a cualquier protocolo basado en TCP/IP, lo que se denomina "entunelar". Se usa normalmente con HTTP (formando HTTPS), para asegurar páginas web de comercio electrónico, entidades bancarias, etc. En Linux se utiliza la implementación SSL de OpenSSL (openssl.org, paquete openssl, archivo de configuración /etc/ssl/openssl.cnf).
Equivalencias en Windows: MS-IIS.
El funcionamiento de SSL es muy similar a SSH:
Veamos paso a paso cómo implementar conexiones seguras SSL en un servidor web.
Necesitamos un dominio registrado, por ejemplo domain.com
Generamos la clave privada RSA (archivo domain.com.key) y la clave pública CSR (Certificate Signing Request, solicitud de certificado, archivo domain.com.csr). La clave privada es usada como input para generar la clave pública CSR. Para obtener un certificado hay que hacer una solicitud CSR, que contiene la clave pública junto con la información sobre el propietario del certificado.
# openssl req -newkey rsa:2048 -nodes -subj "/C=GB/ST=Yorks/L=York/O=MyCompany Ltd./OU=IT/CN=domain.com" -keyout domain.com.key -out domain.com.csr
Cuando el certificado es para un servidor puede ser conveniente que la clave privada no tenga password, ya que de lo contrario tendremos que introducirlo cada vez que reiniciemos el servidor. Para ello utilizaremos la opción -nodes.
Mediante el paramétro -subj suministramos los datos para el campo DN (Distinguished Name), que contiene información sobre el propietario del certificado:
Una vez creada la solicitud de certificado CSR podemos comprobar la información contenida en domain.com.csr utilizando:
# openssl req -noout -text -in domain.com.csr
Los certificados soportan el uso de wildcards, útiles para asegurar múltiples subdominios. Si usamos en la solicitud de certificado CSR domain.com aseguraremos el dominio domain.com pero no www.domain.com. En cambio, si utilizamos *.domain.com aseguraremos todos los subdominios (pero no domain.com).
# openssl req -newkey rsa:2048 -nodes -subj "/C=GB/ST=Yorks/L=York/O=MyCompany Ltd./OU=IT/CN=*.domain.com" -keyout domain.com.key -out domain.com.csr
Ahora necesitamos obtener el certificado SSL (domain.com.crt) para lo cual debe firmarlo una CA (Certification Authority, Autoridad Certificadora).
Los navegadores incorporan de origen un listado de CA reconocidas, de manera que si nuestro certificado va firmado por una de ellas el navegador lo aceptará directamente como válido. El inconveniente es que estas CA reconocidas son empresas que cobran por emitir sus certificados, como Go Daddy (20 $/año) o VeriSign (350 $/año). Existen también CA gratuitas, como CAcert, pero no están reconocidas por los navegadores.
Así pues, si no queremos que nuestros usuarios reciban un mensaje de alerta al entrar en nuestro sitio web SSL tendremos que adquirir un certificado de pago en una CA reconocida. Para ello, enviaremos la solicitud de certificado CSR (domain.com.csr) a la CA, quien, tras verificar que somos los propietarios del sitio web, nos remitirá el certificado con su firma (domain.com.crt).
En ocasiones, como medida de seguridad, la CA no firma nuestro certificado con su certificado raíz sino con un certificado intermedio, que es un certificado subordinado al certificado raíz. En ese caso recibiremos de la CA el certificado intermedio (CA_issuing.crt).
Si sólo queremos asegurar una página de login, podemos crear nuestra propia CA para validar nuestro certificado. Se crean los archivos mi_ca.key (clave privada RSA de nuestra CA) y mi_ca.pem (clave pública auto-firmada de nuestra CA):
# openssl req -x509 -newkey rsa:2048 -nodes -subj "/C=GB/ST=Yorks/L=York/O=MyCA/OU=IT/CN=MyCA" -keyout mi_ca.key -out mi_ca.pem
Emitimos el certificado. Se crean los archivos domain.com.crt (el certificado) y mi_ca.srl (CA serial number file):
# openssl x509 -CA mi_ca.pem -CAkey mi_ca.key -req -in domain.com.csr -days 3650 -sha1 -CAcreateserial -out domain.com.crt
Podemos comprobar los datos contenidos en mi_ca.pem con:
# openssl x509 -noout -text -in mi_ca.pem
Un certificado de nuestra propia CA no puede usarse en producción, ya que como no está firmado por una autoridad certificadora reconocida, en el browser obtendremos un mensaje de alerta:
www.domain.com usa un certificado de seguridad no válido. No se confía en el certificado porque el emisor es desconocido.
Para asegurar la página de login de nuestra aplicación podemos generar un certificado auto-firmado:
# openssl x509 -req -days 365 -in domain.com.csr -signkey domain.com.key -out domain.com.crt
Al igual que ocurre con los certificados de nuestra propia CA, un certificado auto-firmado no puede usarse en producción, ya que como no está firmado por una autoridad certificadora reconocida obtendremos en el browser un mensaje de alerta:
www.domain.com usa un certificado de seguridad no válido. No se confía en el certificado porque está autofirmado.
Una vez obtenido el certificado, para comprobar los datos contenidos en domain.com.crt haremos:
# openssl x509 -noout -text -in domain.com.crt
Ahora vamos a crear el archivo PEM (domain.com.pem), que no es más que el archivo .key y a continuación el archivo .crt concatenados:
# cat domain.com.key domain.com.crt > domain.com.pem
Estos serán los archivos que tendremos en /etc/<webserver>/domain.com/ (/etc/lighttpd/domain.com/ si usamos Lighttpd, /etc/apache/domain.com/ si usamos Apache):
Hay que establecer en los archivos los permisos adecuados, que el propietario sea el usuario que ejecuta el webserver y que sólo puedan ser accedidos por él.
# lighttpd -v lighttpd-1.4.19 (ssl) - a light and fast webserver
$SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/domain.com/domain.com.pem" ssl.ca-file = "/etc/lighttpd/domain.com/CA_issuing.crt" server.name = "domain.com" server.document-root = "/var/www/domain.com/" }
# /etc/init.d/lighttpd restart
Password:
Listen 443
NameVirtualHost *:443 <VirtualHost *:443> ServerAdmin webmaster@localhost DocumentRoot /var/www/domain.com SSLEngine on SSLCertificateFile /etc/apache/domain.com/domain.com.pem SSLCertificateKeyFile /etc/apache/domain.com/domain.com.key SSLCertificateChainFile /etc/apache/domain.com/CA_issuing.crt ServerName domain.com <Directory /var/www/domain.com> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> </VirtualHost>
# /etc/init.d/apache restart
# netstat -ntulp Active Internet connections (only servers) Proto R S Local Address Foreign Address State PID/Program name ... tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 4367/mysqld tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 19436/lighttpd tcp6 0 0 :::80 :::* LISTEN 20249/lighttpd tcp6 0 0 :::22 :::* LISTEN 4277/sshd ...
Veamos cómo implementar conexiones seguras SSL en un servidor web multi-dominio (Name-Based Virtual Host) con una única IP. Utilizaremos para ello un único certificado SSL con extensiones X509v3 y múltiples campos subjectAltName.
req_extensions = v3_req # The extensions to add to a certificate request
[ v3_req ] subjectAltName = @alt_names [alt_names] DNS.1 = *.domain1.com DNS.2 = domain1.com DNS.3 = *.domain2.com DNS.4 = domain2.com DNS.5 = *.domain3.com DNS.6 = domain3.com
# openssl req -newkey rsa:2048 -nodes -keyout domain.com.key -out domain.com.csr -config ./openssl.cnf # openssl req -noout -text -in domain.com.csr
# openssl x509 -req -days 365 -in domain.com.csr -signkey domain.com.key -out domain.com.crt -extensions v3_req -extfile ./openssl.cnf # openssl x509 -noout -text -in domain.com.crt
# cat domain.com.key domain.com.crt > domain.com.pem
Article printed from Estréllate y Arde: https://www.estrellateyarde.org
URL to article: https://www.estrellateyarde.org/discover/ssl
Click here to print.
Copyright © 2010 Estrellate y Arde