Hace unos días veíamos un ejemplo de un cliente web SSL con ayuda de openSSL. Ahora vamos a hacer un servidor al que se pueda conectar. Se trata sólo de una prueba de concepto, nada que podamos utilizar en el mundo real, pero está bien para ver cómo funciona la biblioteca.
Creando un certificado auto-firmado
Lo primero que vamos a hacer es crear una llave y un certificado para utilizarlos. Como estamos probando y no vamos a gastar dinero ni nada en un certificado, podemos crear un autofirmado, ya sabéis, los navegadores no nos detectarán como fuentes de confianza pero tendremos una conexión segura.
Para ello, nos ponemos en un directorio de confianza (vamos a colocar ahí archivos sensibles, al menos vamos a crearlos ahí... por lo menos que no sea una carpeta compartida en emule) y en nuestra consola pondremos:
$ openssl genrsa -out itsme.key 2048
Podremos hacer las claves más complejas, he puesto 2048 porque lo suelo utilizar en muchos casos, y muchas autoridades certificadoras piden claves de este tamaño.
Si queremos cifrar esta clave, o como practican algunos, el famoso y antiguo arte de encerrar datos en una cripta (encriptar), podemos utilizar el argumendo (-des3, -aes256, entre otros), aunque en este caso, nos pedirá una contraseña para empezar a trabajar, y no está bien que un servidor nos pida una contraseña, aunque también podremos manejarla con un callback... bueno, eso ya es decisión vuestra.
Una vez creada la clave, queremos crear una petición de firmado (signing request) porque alguien tiene que dar fe de que soy quien digo que soy, aunque más tarde veremos que yo mismo voy a firmarme... y por eso mismo los navegadores no se fiarán de mí.
$ openssl req -new -key itsme.key -out itsme.csr
Este comando es interactivo, y nos preguntará una serie de datos que mandaremos cuando se conecten a nosotros, para que la gente sepa dónde se está metiendo.
Si no queremos poner un password, lo podemos dejar en blanco.
Tras la creación de la petición de firmado, sólo nos queda firmar, y listo, para ello
$ openssl x509 -req -days 365 -in itsme.csr -signkey itsme.key -out itsme.crt
El parámetro days lo podemos hacer más grande o más pequeño, según decidamos la validez de nuestra firma, podemos poner 1000 años y nadie nos dirá nada, aunque sería un milagro que nuestros datos sobrevivieran tanto.
Ya tenemos nuestros archivos itsme.key e itsme.crt para trabajar con ellos. Podéis visitar esta web para más info sobre creación de certificados.
Creando nuestro servidor
Es sólo una prueba, le pidamos lo que le pidamos, lo hagamos bien o lo hagamos mal, siempre nos devolverá la misma página ( tengo en el horno un pequeño proyecto algo más completo al que ya le integraré también SSL).
El caso es que hacemos la conexión TCP, el handshake SSL, leemos la petición del usuario y enviamos una respuesta. Tal vez tenga un montón de bugs en el servidor, no es concurrente y su respuesta es fija, pero para el caso nos vale.
Algunas notas finales
Puede que no tengamos sólo un certificado (puede que tengamos varios certificados intermedios), y debamos incluirlos todos en nuestra conexión segura. Gracias a que utilizamos SSL_CTX_use_certificate_chain_file() para cargar el certificado, podemos meter varios certificados concatenados, del tipo:
$ cat certificado1.pem certificado2.pem certificado3.pem > cadena_certificados.pem
Los archivos de certificado y clave pueden ser especificados en la parte superior del archivo, con las constantes CERTFILE y KEYFILE.
El método con el que trabajaremos será TLSv1_2_server_method(), aunque podemos utilizar cualquier otra versión de TLS, incluso SSLv3 (será insegura, pero para fines académicos vale, o para ver si hay servidores que aún pueden conectarte con este método... ¡¡no he dicho nada!!). Tenemos también otro método que es SSLv23_server_method(), que actúa igual que el método cliente compañero. OpenSSL no suele venir compilado ya con soporte SSLv2, y el SSLv3 está prohibido hasta la saciedad, pero si queremos SSLv23_server_method() puede no utilizar ningún SSLvX, y tirar directamente para los TLS si definimos SSL_set_options(SSL*, long options). La opción sería SSL_OP_NO_SSLv3 (es una constante, podemos ver más en el manual de SSL_CTX_set_options).
Foto principal: zoetnet (Flickr CC-by)
Foto cripta: Ismael Alonso (Flickr CC-by)
Leave a Reply