¡Este último mes podríamos decir que he estado muy entretenida! Hace ya casi dos años, un cliente vino a mi harto de que los proveedores de hosting le cerrasen el servidor, durante todo este tiempo de maravilla, hasta que hace un mes y medio Movistar y Vodafone bloquearon el dominio. Ahí es cuando el cliente me contactó de nuevo para realizar un análisis y un informe pericial. El motivo es que el cliente no está realizando ningún acto delictivo que lleve a los proveedores de hosting e ISP a bloquear el servicio, aún así, lo hacen, estamos delante de un caso de Internet Blackout, bloqueo interesado de un servicio en concreto para que los usuarios no puedan acceder a él. ¿Algo ha tenido que ver el recién finalizado y polémico Mundial de Fútbol en Qatar?.
En la fecha del bloqueo del dominio del cliente, mi propuesta al identificar que el bloqueo se estaba realizando a nivel de dominio (que no de DNS, ya que estos si resolvían), le propuse al cliente de registrar otro dominio. La solución funcionó durante 2 semanas más hasta que Movistar y Vodafone bloquearon la dirección IP, como tal, la solución de añadir mas dominios apuntando al servidor, ya no era útil. Por mas INRI, el bloqueo se extendió a más ISP, aislando casi por completo el servidor de Internet (y no sólo en España, otros países de Europa y LatinoAmérica se vieron afectados), pero no todos lo bloquearon!
A partir de aquí se empezó a analizar qué soluciones teníamos para hacer llegar de nuevo el servicio a los usuarios (y a los propios servidores que conforman el servicio que algunos también perdieron comunicación). Lo primero era plantear usar un cdn, el mas conocido cloudflare.com, ¿a que no hay cojones de volver a bloquear un servicio de estos enteros?, pero los servidores de este servicio no llegaban a la IP del servidor. Así que opción descartada.
Se barajó la opción de usar un servidor o router intermedio con un operador que no estuviese realizando el bloqueo ilegal. Finalmente se optó por un servidor y VPN Wireguard.
Al realizar la configuración, al contratar el servidor más barato posible, evidentemente, una cosa de estas será un VPS, un servidor virtualizado con vete a saber qué tecnología (interfaz de red venet0), al levantar la interfaz wireguard dijo que na’ de na’:
# apt install wireguard # ip link add wg0 type wireguard
Por aquí no se podía seguir, además en un entorno de pruebas sin límite, las reglas de iptables conseguí que se mandasen los paquetes pero no que estos volviesen por donde yo quería.
Así que la solución, gracias a una recomendación de un amigo, fue usar haproxy. Así que veremos como lo he desarrollado:
HAProxy
Lo primero será instalarlo:
# apt -y install haproxy
Y lo siguiente configurarlo:
# cd /etc/haproxy/ # mv haproxy.cfg{,.old} # vi haproxy.cfg
#--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global log /dev/log local0 info info log /dev/log local1 notice info pidfile /var/run/haproxy.pid maxconn 4096 user haproxy group haproxy daemon # turn on stats unix socket stats socket /var/lib/haproxy/stats ############# SSL ################### # Tunning secure HTTPS ssl-default-bind-options no-sslv3 no-tls-tickets no-sslv3 no-tlsv10 no-tlsv11 ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:!aNULL:!MD5:!DSS tune.ssl.default-dh-param 2048 ######################################## defaults mode http # log global # option httplog option dontlognull option redispatch retries 3 timeout http-request 100s timeout queue 1m timeout connect 300s timeout client 10m timeout server 10m timeout http-keep-alive 10s timeout check 10s maxconn 3000 #--------------------------------------------------------------------- # Stats #--------------------------------------------------------------------- listen stats bind *:8083 mode http stats enable stats uri / stats realm HAProxy\ Statistics stats auth haproxy:*************** stats refresh 10s #--------------------------------------------------------------------- # Frontend #--------------------------------------------------------------------- frontend http-in-cliente mode http bind :::80 v4v6 bind *:443 ssl crt /etc/ssl/cliente/cliente.pem # comentat per laura (no funciona la renovacio de certificats amb això) #option forwardfor except 127.0.0.0/8 http-response set-header Server cliente-proxy # comentat per laura #acl is-blocked-ip src -f /usr/local/scripts/ipsfirewall1.conf #http-request deny if is-blocked-ip # Test URI to see if its a letsencrypt request acl letsencrypt-acl path_beg /.well-known/acme-challenge/ use_backend letsencrypt-backend if letsencrypt-acl # Redirects # comentat per laura #redirect prefix https://clientemalo.eu code 301 if { hdr(host) -i -f /etc/haproxy/clientemalo_eu_trusted.cfg } redirect scheme https if !{ ssl_fc } # Security Hardening http-response del-header (^Server.*|^X-Powered-By:.*|^X-Runtime.*|^X-Version.*|^X-AspNet-Version.*) http-response set-header Server cliente-proxy http-response set-header X-Content-Type-Options nosniff http-response set-header X-XSS-Protection 1;\ mode=block # ACLS # headers acl host_no_X_Frame_Options res.hdr(X-Frame-Options) -m found http-response set-header X-Frame-Options SAMEORIGIN if !host_no_X_Frame_Options # webserver hosts acl host_otrodominio_eu hdr(host) -i otrodominio.eu acl host_clientemalo_eu hdr(host) -i clientemalo.eu # backends # define backends use_backend backend_otrodominio_eu if host_otrodominio_eu use_backend backend_clientemalo_eu if host_clientemalo_eu #--------------------------------------------------------------------- # Backends WWW #--------------------------------------------------------------------- # LE Backend backend letsencrypt-backend server letsencrypt 127.0.0.1:8888 backend backend_otrodominio_eu option forwardfor http-request set-header X-Forwarded-Host %[req.hdr(Host)] http-request set-header X-Forwarded-Port %[dst_port] http-request add-header X-Forwarded-Proto https if { ssl_fc } server server_otrodominio_eu X.X.X.X:XXXX check maxconn 1024 backend backend_clientemalo_eu option forwardfor http-request set-header X-Forwarded-Host %[req.hdr(Host)] http-request set-header X-Forwarded-Port %[dst_port] http-request add-header X-Forwarded-Proto https if { ssl_fc } server server_clientemalo_eu X.X.X.X:XXXX check maxconn 1024
Aquí en esta configuración tengo generado el certificado usando letsencrypt y varios dominios en el mismo certificado:
# certbot certonly --standalone -d otrodominio.eu -d clientemalo.eu --non-interactive --agree-tos --email info@clientemalo.net --http-01-port=8888 --expand
Le indicamos que en lugar de usar el puerto 80 o 443 por defecto, use el puerto 8888 (que no lo hemos definido en el frontend ni tampoco tenemos ningún nginx o apache instalado en el servidor, el puerto lo crea internamente haproxy y no se hace ningún bind en el sistema)
En este post del foro de serverfault, hablan de varias formas de como usar certificados independientes para cada dominio.
En mi caso, he creado un script para adaptar los certificados de letsencrypt para que los pueda interpretar haproxy
# vi /root/scripts/renew_le.sh #!/bin/bash # Renew the certificate certbot renew --force-renewal --http-01-port=8888 # Concatenate new cert files, with less output (avoiding the use tee and its output to stdout) bash -c "cat /etc/letsencrypt/live/clientemalo.eu/fullchain.pem /etc/letsencrypt/live/clientemalo.eu/privkey.pem > /etc/ssl/cliente/cliente.pem" # Reload HAProxy service haproxy reload
Le damos permisos de ejecución y le indicamos que se actualice cada primer día del mes
# chmod +x /root/scripts/renew_le.sh # vi /etc/crontab # renew certificates * * 1 * * root /root/scripts/renew_le.sh
Y listos! una de las dudas que tenía era si Movistar había llegado a bloquear el dominio nuevo, y parece que no ;) así que durante unos días es posible saltar el bloqueo ilegal y digo ilegal porqué en estos casos es un juez quien debe dictar bloquear un servicio y no alguien a quien le pica la entrepierna y menos alguien fuera de la UE.
Ahora vamos a ver la segunda parte de este post, autossh.
autossh
El otro problema que se encontró el cliente es que los distintos servidores que ofrecían el servicio no se podían “ver” entre ellos. Así que se hizo uso de este servidor donde se configuró el HAProxy y se habilitó el servicio autossh, que sirve para tunelizar conexiones ssh.
Lo primero, instalarlo
# apt -y install autossh
Lo siguiente, generar el par de claves pública y privadas ssh en el servidor
# cd /root/.ssh # ssh-keygen -t rsa
Añadimos el contenido de id_rsa.pub al fichero /root/.ssh/authorized_keys del servidor al que queremos conectar y realizamos la conexión por SSH:
# ssh root@ip_servidor_1 # ssh root@ip_servidor_2
Ahora realizamos la conexión con autossh para comprobar que funciona:
# autossh -f -N -L \*:2XXX:localhost:22 ip_servidor_1 -i /root/.ssh/id_rsa # autossh -f -N -L \*:2XXX:localhost:22 ip_servidor_2 -i /root/.ssh/id_rsa
# netstat -lanp |grep 'LISTEN ' |grep ssh tcp 0 0 0.0.0.0:2XXX 0.0.0.0:* LISTEN 21284/ssh tcp 0 0 0.0.0.0:2XXX 0.0.0.0:* LISTEN 16070/ssh tcp 0 0 127.0.0.1:62XXX 0.0.0.0:* LISTEN 21299/autossh tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 297/sshd: /usr/sbin tcp 0 0 127.0.0.1:58XXX 0.0.0.0:* LISTEN 16069/autossh tcp6 0 0 ::1:54208 :::* LISTEN 21284/ssh tcp6 0 0 :::2XXX :::* LISTEN 21284/ssh tcp6 0 0 :::2XXX :::* LISTEN 16070/ssh tcp6 0 0 :::22 :::* LISTEN 297/sshd: /usr/sbin
Como podemos ver aparecen los dos puertos que hemos indicado a autossh
Para aplicar esta configuración al iniciar el sistema añadiremos un par de líneas en el fichero /etc/rc.local
# vi /etc/rc.local # Servidor 1 autossh -f -N -L \*:2XXX:localhost:22 ip_servidor_1 -i /root/.ssh/id_rsa # Servidor 2 autossh -f -N -L \*:2XXX:localhost:22 ip_servidor_2 -i /root/.ssh/id_rsa
Y todo accesible y conectado de nuevo! ;)
A ver cuál es el siguiente bloqueo que nos realizan, de momento todos han sido técnicos y ninguno jurídico, almenos nosotros como operador no hemos recibido ninguna petición de bloquear el servicio del cliente y aún sin ningún procedimiento judicial abierto.
PS: El cliente me ha dado permiso para publicar su caso
PS2: El abogado recomienda omitir la mención al cliente, por lo que ha sido reemplazado por clientemalo. El contenido de este post es para fines educativos y todo lo mencionado técnicamente es lo que se usa diariamente en sistemas de nube. Aprovecho para recordar que no me hago responsable del uso que le hagan los lectores de mi blog con su contenido.
Buenísimo de verdad aprendí mucho, y tengo muchas ganas de ser mejor sysadmin