msgbartop
Dale fuego a un hombre y estará caliente un día. Préndele fuego y estará caliente el resto de su vida
msgbarbottom

29 dic 22 Uso de un servidor público y ZeroTier para publicar servicios hacia Internet desde una red con CG-NAT

Desde hace algunos días vengo experimentando problemas con mi conexión doméstica a Internet. Esto es un problema bastante molesto para mí, porque hago uso de una serie de servicios en un servidor casero que publico hacia el exterior. El principal de ellos es este sitio web, pero hay algunos adicionales, como algunos servicios de domótica y una conexión VPN para acceder de manera segura desde el exterior. Hasta ahora, venía publicándolo todo de manera directa, ya que disponía de una IPv4 con mi conexión, pero desde la semana pasada han pasado a darme acceso a Internet detrás de un CG-NAT. Esto implica que ya no dispongo de una IPv4 propia, sino que salgo a través de una NAT del operador, por lo que no es posible acceder de manera remota a dichos servicios.

Mientras me lo solucionan, he optado por poner en pie un mecanismo para poder seguir publicando servicios, basado en el uso de un pequeño servidor público que se encarga de redireccionar los servicios hacia mi sistema detrás del CG-NAT. Y para ello, hago uso de una plataforma que permite establecer redes securizadas mediante una combinación de SG-NAT y VPN, llamada ZeroTier. La gracia de ZeroTier es que el entorno funciona como un concentrador de VPNs, de tal manera que entre los clientes que necesitemos conectar se establece una red privada, con lo que es posible dotar de conectividad entre ellos a los mismos, tan sólo instalando un agente del propio ZeroTier entre ellos, y establecer la visibilidad oportuna entre nodos. Haciendo que el servidor publicado en Internet sea uno de los nodos, puedo proporcionar servicios utilizándolo de pasarela pública.

La segunda pata del asunto es conseguir este servidor frontal público, y hacer que funcione de pasarela. En mi caso, he optado por hacer uso de Oracle Cloud Infrastructure, donde se puede desplegar de manera gratuita un servidor basado en Linux. Y una vez que me he hecho con este servidor, he montado la pasarela con un servidor NGINX, debido a que me permite redireccionar tanto servicios publicados por TCP (mi servidor web y mi servidor MQTT) como UDP (mi servidor VPN), con lo que me ahorro tener que andar instalando y gestionando servicios duplicados en este frontal. Sencillo y eficiente. El diagrama general de cómo ha quedado el entorno es el siguiente:

Configuración de acceso remoto con ZeroTier y Oracle Cloud

Configuración de acceso remoto con ZeroTier y Oracle Cloud

La configuración a nivel interno sí que tiene algunos puntos a tener en cuenta:

  • El primero de ellos es relativo a la instalación de ZeroTier. Ésta es bastante sencilla, se trata de descargar el cliente VPN que proporciona el propio proveedor. A nivel Linux se instala con un simple wget desde la plataforma, y el despliegue se basa en indicarle la red privada que hemos registrado en la misma, y los propios nodos se añaden a ella. El registro en la plataforma es gratuito para redes de hasta 25 nodos, y también permite desplegar sistemas autogestionados para entornos profesionales. Una vez añadidos los nodos, es preciso darles permiso para conectarse a la red privada que hemos creado al registrarnos. Una vez hecho, podrán verse entre ellos. A nivel de sistema operativo, esta conexión aparece como una nueva IP virtual, vinculada a la conexión VPN establecida con ZeroTier. En mi caso, lo he desplegado en dos sitios: el servidor VPS que he creado en Oracle Cloud, y en el servidor que hace de frontal web para las conexiones entrantes a mis sistemas, que actúa de proxy inverso para el resto de servidores.
  • El segundo es el relativo al NGINX en el VPN de Oracle Cloud. Como comentaba, he optado por utilizar NGINX como frontal para publicar servicios. Dado que publico servicios HTTP y HTTPS, no tenía ganas de andar gestionando el tema de un proxy inverso convencional, teniendo que duplicar certificados y gestionar las redirecciones entre ellos. En este caso, he optado por realizar una simple redirección mediante el uso de la directiva stream en nginx.conf, que viene a funcionar como un balanceador de carga, estilo F5 o HAProxy. La idea es que puedes definir un servicio upstream, en el que se indica a qué dirección IP y qué puerto de tu entorno interno quieres proporcionar acceso, y luego se define un server que publica los servicios. En mi caso, en el upstream declaro la IP interna correspondiente a mi servidor doméstico proporcionada por ZeroTier (que, recordemos, es privada y accesible sólo para mi VPS), con lo que me estoy saltando las limitaciones del CG-NAT, y en el server publico los servicios. La gracia del asunto, además, es que vale para conexiones TCP y UDP. Como lo que quiero publicar es un servidor HTTPS, un servidor MQTT y un servidor VPN, todo queda de la siguiente manera:

    stream {
    upstream web_server {
    server IP_PRIVADA_REMOTA_ZEROTIER:443;
    }

    server {
    listen 443;
    ssl_preread on;
    proxy_pass web_server;
    }

    upstream mqtt_server {
    server IP_PRIVADA_REMOTA_ZEROTIER:1883;
    }
    server {
    listen 1883;
    proxy_pass mqtt_server;
    proxy_connect_timeout 1s;
    }

    upstream vpn_server {
    server IP_PRIVADA_REMOTA_ZEROTIER:1194;
    }
    server {
    listen 1194 udp;
    proxy_pass vpn_server;
    }

    }

  • El tercer punto es la redistribución de servicios en el lado del servidor doméstico. Esto es importante para mí, dado que no hago uso de un solo servidor a nivel doméstico, sino de una serie de servidores desplegados en un entorno de virtualización. Mientras que el frontal web (que es un NGINX, a su vez) y mi servidor MQTT residen en el servidor que he conectado a ZeroTier, el servidor WordPress y el servidor de VPN están en sistemas distintos. Esto implica que tengo que encargarme de redirigir las conexiones provenientes del nuevo frontal en Oracle a estos sistemas. La parte de WordPress ya la tenía resuelta, pero quedaba por solucionar la parte del servidor VPN. En este caso, como en el anterior, la idea es utilizar un stream. Siguiendo con la idea anterior:

    stream {

    upstream vpn_server {
    server IP_SERVIDOR_LOCAL_VPN:1194;
    }
    server {
    listen 1194 udp;
    proxy_pass vpn_server;
    }

    }

  • Y por último, he tenido que jugar un poco con mi servidor DNS. He creado un nuevo nombre en mi dominio eniac2000.com para el frontal VPS de Oracle Cloud, y he redireccionado los alias que uso habitualmente (www, bitacora…) hacia este nuevo nombre. Con ello, todo queda configurado de manera transparente.

En realidad, me gusta tanto cómo ha quedado configurado, que es posible que lo deje así incluso cuando se solucione el tema del CG-NAT, ya que añade una capa extra de seguridad y disponibilidad a mis sistemas.

Referencias:
How to bypass CGNAT and expose your server to the internet using ZeroTier, a VPS and NGINX
Bypassing a CGNAT with Wireguard (Especialmente útil para la parte de configuración del entorno en Oracle Cloud)
How to set nginx reverse proxy to an SSL site without certificate?

VN:F [1.9.20_1166]
Rating: 10.0/10 (2 votes cast)

Etiquetas: , , , , , , , ,

29 jun 20 Uso de la cabecera X-Forwarded-For en un WordPress tras un proxy inverso

En fechas recientes he realizado un cambio de arquitectura en mi sitio web: he pasado de un servidor con WordPress colgado directamente en Internet a utilizar un frontal NGNIX como proxy inverso a la hora de acceder al sitio web. Hay diversas razones para ello, pero la principal está centrada en la seguridad. Sin embargo, esta arquitectura tiene una contrapartida: dado que el proxy inverso realiza una conversión SNAT de la dirección IP, el servidor WordPress interpreta que todas las peticiones vienen del proxy -lo que en realidad es rigurosamente cierto-, perdiéndose la información relativa a la IP real del equipo desde el que el usuario final accede.

Registros de WordPress mostrando la IP del servidor proxy inverso

Registros de WordPress mostrando la IP del servidor proxy inverso

Por suerte, este comportamiento se puede manipular. La idea general es incrustar la IP del cliente final en un campo cabecera (X-Forwarded-For), y luego modificar el comportamiento de WordPress para que haga uso de la IP contenida en esta cabecera como la IP del usuario. La receta para ello es la siguiente:

  • Configurar el proxy inverso que actúa de frontal para que incruste la IP del cliente en la cabecera X-Forwarded-For: En el caso de un servidor NGINX se realiza añadiendo la siguiente entrada al fichero nginx.conf:
    proxy_set_header X-Forwarded-For $remote_addr;
  • Verificar que la cabecera se inserta adecuadamente: En este caso, se puede realizar mediante una captura tcpdump en el servidor WordPress. Aquí dejo una pequeña guía de cómo realizarlo: TCPDump Capture HTTP GET/POST requests – Apache, Weblogic & Websphere
  • Indicar a WordPress que haga uso de la IP contenida en el campo X-Forwarded-For: Por último, hay que modificar el fichero wp-config.php del servidor WordPress, para reemplazar el valor del campo REMOTE_ADDR, que normalmente es la IP que realiza la petición a WordPress, por la IP contenida en la cebecera X-Forwarded-For. Se realiza incrustando este fragmento de código:
    // Use X-Forwarded-For HTTP Header to Get Visitor's Real IP Address

    if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
    $http_x_headers = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] );

    $_SERVER['REMOTE_ADDR'] = $http_x_headers[0];
    }

Et voilà! A partir de este momento, nuestro WordPress pasa a mostrar de nuevo correctamente las IPs con la que se accede por parte de los usuarios del sitio a nuestro contenido.

Registro de WordPress mostrando correctamente la IP del usuario final

Registro de WordPress mostrando correctamente la IP del usuario final

VN:F [1.9.20_1166]
Rating: 10.0/10 (1 vote cast)

Etiquetas: , , ,

22 may 17 Hello World IPv6!

Hoy he publicado mi primer sitio en IPv6:

Mi primer sitio en IPv6

Mi primer sitio en IPv6

…y no sólo se trata del sitio, que ya mola de por sí, sino lo que estoy utilizando para ello: un servidor NGINX, una Asus TinkerBoard… y las IPs v6 que me da mi proveedor irlandés. Aunque los malditos me hacen CG-NAT en IPv4. :@

VN:F [1.9.20_1166]
Rating: 0.0/10 (0 votes cast)

Etiquetas: , , ,

05 feb 11 Modificaciones en el servidor: fachada nginx

Estas semanas, cuando el trabajo y la salud me lo han permitido, he estado realizando algunos cambios en el servidor. Como comenté anteriormente, el más importante ha sido el cambio de su ubicación: ha pasado de ser un servidor virtual VMWare ubicado en Córdoba a ser un servidor físico emplazado en Sevilla. Y ya que estaba de cambios, me decidí a probar un servidor web del que llevaba tiempo escuchando hablar: nginx.

Logo NGINX

nginx es un servidor web/proxy inverso ligero de alto rendimiento y un proxy para protocolos de correo electrónico (IMAP/POP3). Es software libre y de código abierto, licenciado bajo la Licencia BSD simplificada. Es multiplataforma, por lo que corre en sistemas tipo Unix (GNU/Linux, BSD, Solaris, Mac OS X, etc.) y Windows.

El sistema es empleado en una larga lista de sitios web conocidos, como: WordPress, Hulu, GitHub, Ohloh, SourceForge y TorrentReactor. Originalmente, nginx fue desarrollado para satisfacer las necesidades de varios sitios web de Rambler que recibían unas 500 millones de peticiones al día en septiembre de 2008.

De acuerdo con el estudio de Netcraft, Netcraft’s May 2010 Web Server Survey, nginx fue el tercer servidor web más usado en todos los dominios (6.55% de los sitios estudiados) y el cuarto servidor web más usado en los sitios activos (8.77% de los sitios estudiados).

Sus características básicas son las siguientes:

  • Servidor de archivos estáticos, índices y autoindexado
  • Habilitado para soportar más de 10.000 conexiones simultáneas
  • Proxy inverso con opciones de caché
  • Balance de carga
  • Tolerancia a fallos
  • Soporte de HTTP sobre SSL
  • Soporte para FastCGI con opciones de caché
  • Servidores virtuales basados en nombre y/o en dirección IP
  • Streaming de archivos FLV y MP4
  • Soporte para autenticación
  • Compresión gzip
  • Capacidad de reescritura de URLs
  • Sistema de log personalizable
  • Soporte WebDAV

La arquitectura interna de nginx le permite servir más peticiones por segundo con menos recursos que sus principales alternativas. Ésta consiste en un proceso maestro que delega el trabajo en uno o varios procesos “worker”. Cada worker gestiona múltiples peticiones de modo basado en eventos, o bien asíncrono, haciendo uso de funcionalidades especiales del kernel Linux (epoll/select/poll). Esto permite a nginx gestionar un gran número de peticiones concurrentes de una manera rápida y con muy poca sobrecarga. Por ejemplo, un servidor Apache puede ser configurado para procesar las bien una petición por proceso (pre-fork) o bien una petición por cada hilo (worker). Aunque el modo basado en hilos de Apache tiene un rendimiento mucho mejor que el basado en procesos, sigue haciendo uso de mucha más memoria y CPU que la arquitectura basada en eventos de nginx.

En mi caso concreto, mi servidor web contiene las siguientes aplicaciones:

  • Una bitácora. La que estás leyendo, que utiliza WordPress. Necesita PHP y una base de datos MySQL
  • Un sistema de almacenamiento de fotografías. Utiliza Gallery2. También necesita PHP, MySQL, y una serie de molestas reescrituras
  • Una serie de aplicaciones menores de mantenimiento y de gestión de logs. Por lo general, usan PHP, CGI, y alguna de ellas MySQL

Mi objetivo primordial era realizar un reemplazo completo del servidor Apache, motivado por las siguientes razones: el cambio del servidor me ha dejado con menos recursos hardware (en concreto, con menos RAM y con un procesador menos potente), y sobre todo, comprobar si nginx es tan bueno como lo vende.

A la hora de realizar el cambio, pude comprobar algo que es bastante importante: nginx es un servidor web de ficheros estáticos. Esto quiere decir que si estás pensando en sacar a través de él páginas web dinámicas tienes un problema. Por suerte es un problema fácilmente abordable, ya que al estar pensado desde el principio como un servidor proxy inverso, tienes la capacidad de delegar funcionalidades no soportadas en otros servidores adicionales. En mi caso, instalé en mi servidor Debian un servidor PHP externo, spawn-fcgi, que escucha peticiones por el puerto 9000.

La migración de WordPress no supuso mayor problema, una vez solucionado el tema anterior. Sin embargo, la de Gallery2 sí me ha planteado más dificultades, debido a una serie de reescrituras un tanto especiales que necesita para mantener funcionando el sistema. Tras varios días de pruebas, y viendo que no alcanzaba a migrar completamente esta aplicación, decidí darle un cambio de perspectiva: mantener el servidor Apache como un servidor web subordinado, y emplear nginx como servidor de fachada, con caché de contenido. No hay mal que por bien no venga, ya que me ha supuesto la oportunidad de realizar pruebas de esta funcionalidad, de cara a una línea de trabajo que estoy desarrollando para mi empresa.

Como consecuencia de lo anterior, decidí mover los puertos de servicio del servidor Apache al 81 (conexión http) y 444 (conexión https), que son sólo alcanzables desde la red interna de mi casa. Mediante una serie de reescrituras, las peticiones efectuadas al sistema Gallery2 son dirigidas al servidor Apache, procesadas por éste, y reenviadas por nginx al cliente, además de ser cacheadas para ganar en tiempo de respuesta. El resto de peticiones (WordPress, otras aplicaciones…) son servidas directamente por el servidor nginx. Un diagrama básico de lo expuesto hasta el momento sería el siguiente:

Diagrama de arquitectura

Diagrama de arquitectura

El resultado desde el punto de vista funcional es bastante bueno: las aplicaciones siguen siendo servidas de manera correcta, se ha ganado algo en tiempo de respuesta (por desgracia, la poca potencia del servidor y las limitaciones de la línea de datos no permiten grandes alegrías), y ha disminuido el consumo de memoria: pese a no haber eliminado el servidor Apache, se ha pasado de consumir unos 900 MB de RAM a unos 780, y con un comportamiento mucho más estable. Cada proceso nginx consume un máximo de 3 MB, mientras que cada proceso Apache ronda los 50 MB, con una gran fluctuación de memoria consumida. A esto hay que sumar los dos procesos configurados para spawn-fcgi, que también rondan los 50 MBs. La bajada en el consumo ha venido de haber podido reducir el número de procesos Apache que se mantienen en ejecución: he podido pasar de un mínimo de 10 procesos concurrentes a tan sólo 2.

En resumen: estoy bastante contento con el cambio. Estoy aprendiendo a gestionar servidores web de alto rendimiento, y creo que voy a poder sacarle bastante partido a este servidor nginx en el ámbito laboral. Esperemos que así sea.

VN:F [1.9.20_1166]
Rating: 9.0/10 (2 votes cast)

Etiquetas: , , , , ,

21 ene 11 Estoy de mudanza…

…del servidor web. ;)

Llevo una semana con una migración de mi servidor. He realizado una migración desde máquina virtual VMWare a una máquina física, y su traslado de Córdoba a Sevilla (con una herramienta de las que espero poder hablar más adelante). Y una vez trasladada, algunas modificaciones en el entorno de publicación, entre lo que destaca lo siguiente:

Logo NGINX

Estoy realizando pruebas para reemplazar el servidor web Apache por algo más ligero, como por ejemplo NGINX, o Cherokee. Por ello, durante unos días es posible que este sitio se muestre un tanto inestable… :mrgreen:

VN:F [1.9.20_1166]
Rating: 0.0/10 (0 votes cast)

Etiquetas: , , ,