Hoy vamos a ver como instalar unos certificados SSL en nuestro servidor Apache.
Esto es algo bastante necesario cuando queremos incluir pagos en nuestra página web, ya que proporciona una comunicación encriptada entre el cliente y el servidor, y por tanto, la seguridad de que los datos de la tarjeta que introduzca el usuario no son vistos por nadie más.
Podemos utilizar dos tipos de certificados SSL:
* Auto-firmados (nosotros decirmos que el certificado es válido)
* Firmados por una Autoridad Certificadora (CA)
Si firmamos el certificado nosotros mismos, el navegador mostrará una alerta conforme el certificado no es muy seguro que digamos (no nos concede credibilidad), así que para no espantar a nuestros usuarios, habrá que sacar la cartera y comprar un certificado de una CA.
Hay varios tipos de certificados, y de varios precios, pero si lo que queremos es lo más básico, y que nos cubra únicamente un dominio, nos bastará con un certificado SSL estándar (o de Nombre Único). Yo lo tengo con DigiCert, y la verdad, siendo una CA de prestigio, por unos 140€/año está bastante bien (un certificado equivalente con Symantec nos sale entorno a los 350€. Obviamente hay otras CA más baratas, pero es necesario que sea mínimamente conocida para que el navegador lo acepte como seguro.
Paso I: Comprar el certificado
La CA que hayamos contratado ya nos dará las instrucciones para crearlo, pero en general lo que necesitamos proporcionarles es una Solicitud de Firma de Certificado (CSR), que podemos obtener ejecutando por consola en nuestro servidor:
$ openssl req -new -newkey rsa:2048 -nodes -keyout miweb_com.key -out miweb_com.csr
Este comando iniciará un diálogo (pidiéndonos ciudad, país, empresa, etc). Lo más destacable es el Common Name, donde debemos introducir el nombre del dominio para el que queremos el certificado (por ejemplo, www.miweb.com). También nos pedirá un secure password. Eso es una clave que se utiliza para generar el certificado, y que nos permitiría crear de nuevo el mismo certificado en caso de perderlo. No extravieis esa clave.
Una vez finalizado, nos devuelve un archivo miweb_com.key y un archivo miweb_com.csr. Éste ultimo es el que nos pedirá la CA para generar el certificado.
Tras un periodo de validación, deberían enviarnos nuestro certificado miweb_com.crt y un certificado intermedio (su certificado), que para el ejemplo llamaremos CA.cert. Estos certificados son los que debemos instalar en nuestra máquina, junto con la clave que hemos generado nostros miweb_com.key.
Paso II: Instalar los certificados
1- Copiar los archivos al servidor
Debemos copiar estos archivos al servidor (un buen sitio sería /etc/apache2/ssl) y darle acceso solo de lectura al usuario root. Así que pasamos primero los archivos con alguna herramienta de FTP, y una vez estan en nuestro servidor, nos conectamos al mismo por SSH y ejecutamos:
# si no existe el directorio
$ sudo mkdir /etc/apache/ssl
# movemos los certificados al directorio
$ sudo mv miweb_com.crt /etc/apache2/ssl/
$ sudo mv CA.crt /etc/apache2/ssl/
# movemos la clave que ya teníamos en el servidor
$ sudo mv miweb_com.key /etc/apache2/ssl/
# les cambiamos el usuario para que sea el root a los nuevos archivos
$ cd /etc/apache2/ssl
$ sudo chown root:root miweb_com.crt
$ sudo chown root:root CA.crt
# les damos permiso solo de lectura para el usuario
$ sudo chmod 400 miweb_com.crt
$ sudo chmod 400 CA.crt
$ sudo chmod 400 miweb_com.key
2-Buscamos el archivo de configuración de Apache
La ubicación de este archivo puede variar, pero típicamente se encuentra en etc/httpd/httpd.conf o, en mi caso que dispongo de varias aplicaciones, en la carpeta /etc/apache2/sites-available/ dispongo de un archivo de configuración por cada site. En este caso, el archivo es /etc/apache2/sites-available/miweb.conf
3-Editamos el archivo de configuración
Abrimos el archivo que hemos encontrado en el punto anterior (sudo vi), encontramos el < VirtualHost>, que será algo del estilo:
<VirtualHost *:80>
ServerName miweb.com
#...some more content...
</VirtualHost>
y (suponiendo que queremos conservar el acceso por HTTP, ya que de lo contrario nos podemos cargar el < VirtualHost *:80>…< /VirtualHost>), duplicamos el contenido, pero esta vez con la información necesaria para SSL (atención al uso del puerto 443), es decir, dejamos un archivo del estilo:
<VirtualHost *:80>
ServerName miweb.com
#...some more content...
#..this in case we want to redirect from Http to Https
#Redirect permanent / https://miweb.com
</VirtualHost>
<VirtualHost *:443>
ServerName miweb.com
#...some more content...
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/miweb_com.crt
SSLCertificateKeyFile /etc/apache2/ssl/miweb_com.key
SSLCertificateChainFile /etc/apache2/ssl/CA.crt
</VirtualHost>
4. Comprobamos que la configuración sea correcta
Antes de reiniciar el servidor, vamos a asegurarnos de que el fichero de configuración es correcto. Para ello, utilizamos el siguiente comando:
$ sudo apachectl configtest
Es posible que nos aparezca un error del estilo Invalid command ‘SSLEngine’. Esta situación se debe a que no hemos instalado y/o habilitado las librerías de apache para dar soporte a SSL.
Para resolver esta situación, ejecutaremos:
$ sudo apt-get install libapache2-mod-gnutls
$ sudo a2enmod ssl
Hecho esto, comprobamos de nuevo con apachectl configtest que todo esté correcto.
Reiniciamos el servidor apache
Ahora solo nos falta reiniciar el servidor apache.
Esto podemos hacerlo con el comando:
sudo service apache2 restart
Solución de problemas
Habilitar puerto 443 en Apache
Es probable que tengamos que indicar a Apache que escuche en el puerto de SSL. Editamos /etc/apache2/ports.conf y añadimos:
NameVirtualHost *:443
Habilitar puerto 443 en el hosting
Además, es posible que tengamos que habilitar también la conexión HTTPS a través de nuestro servicio de hosting.
En mi caso, que utilizo Amazon Web Services (AWS), deberíamos entrar vía web en nuestra cuenta AWS, mirar el Security Group de la instancia de nuestra máquina, y posteriormente, mirar que dicho security group tenga permiso inbound de HTTPS. En caso contrario, habrá que añadirlo, para que aparezca como vemos en la imagen.
Consideraciones adicionales para Django
Si trabajamos con Django, deberemos tener más cosas en cuenta.
Fichero de configuración del servidor
En mi caso, estoy trabajando con un par de aplicaciones Django en la misma máquina, por lo que tendré que modificar los ficheros de sites-available, como comentaba antes, pero en este caso, tendré que ser cuidadoso, y darle un nombre distinto al WSGIDaemonProcess.
El archivo /etc/apache2/sites-available/miweb.conf preparado para Django, quedaría algo así como lo siguiente:
<VirtualHost *:80>
ServerName miweb.com
ServerAdmin yo@miweb.com
DocumentRoot /home/admin/miproyecto/miweb
WSGIPassAuthorization On
WSGIScriptAlias / /home/admin/miproyecto/miweb/miweb/wsgi.py
WSGIDaemonProcess miweb python-path=/home/admin/miproyecto/miweb:/home/admin/env_pre/lib/python2.7/site-packages
WSGIProcessGroup miweb
</VirtualHost>
<VirtualHost *:443>
ServerName miweb.com
ServerAdmin yo@miweb.com
DocumentRoot /home/admin/miproyecto/miweb
WSGIPassAuthorization On
WSGIScriptAlias / /home/admin/miproyecto/miweb/miweb/wsgi.py
WSGIDaemonProcess miweb_ssl python-path=/home/admin/miproyecto/miweb:/home/admin/env_pre/lib/python2.7/site-packages
WSGIProcessGroup miweb_ssl
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/miweb_com.crt
SSLCertificateKeyFile /etc/apache2/ssl/miweb_com.key
SSLCertificateChainFile /etc/apache2/ssl/CA.crt
</VirtualHost>
Cambios de Django
Nuestro código Django también deberá sufrir ciertas modificaciones.
Deberemos abrir el archivo settings.py de nuestra aplicación Django y añadir en algún lado:
##### SSL SETTINGS #####
# secure proxy SSL header and secure cookies
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# session expire at browser close
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# wsgi scheme
os.environ['wsgi.url_scheme'] = 'https'
##### END SSL SETTINGS #####
Así mismo -suponiendo que estamos utilizando mod_wsgi para servir Django desde Apache, deberíamos abrir el archivo wsgi.py y añadir:
# SSL settings
os.environ['HTTPS'] = "on"
Eso es todo por el momento. Dejo aquí otros artículos interesantes que detallan bastante este tema, desde la creación de certificados, a explicaciones detalladas para Django aquí y aquí pasando por la Wiki de apache.
Saludos,