msgbartop
بنو أمية
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 (1 vote 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: , , ,

20 nov 11 MTB a Fondo

El ciclismo, como sabe cualquiera que lea un poco estas páginas, es una de mis grandes pasiones. Disfruto con el ciclismo de carretera, pero tengo especial predilección por el ciclismo de montaña. Afición que, afortunadamente, comparto con una buena cantidad de amigos. Hace ya algún tiempo, en una charla con Mané, estuvimos hablando sobre la creación de un foro para nuestro grupo de amigos en el que pudiéramos charlar de las etapas, planificar salidas, y poder contar cosas en general sobre nuestra común afición.

Tiempo después, me encontré con un pequeño problema: desde hace un año registro todas las salidas que hacemos con la bici en archivos GPX, a fin de tenerlas documentadas para posteriores salidas, así como material para realizar los relatos con los que me gusta recordar las etapas. El almacenaje de esos gpx se estaba volviendo un tanto caótico (ya que no contenía referencias o datos más allá de la fecha del fichero), por lo que se me ocurrió poder utilizar algún gestor documental para almacenar las etapas de manera más ordenada, y que a la vez me sirviera de copia de seguridad de mi registro de archivos.

Fue entonces cuando se me ocurrió que podía aprovechar un gestor de contenidos con el que tengo bastante esperiencia, WordPress, para solucionar ambos problemas. Y fruto de esa idea fue como nació MTB A Fondo.

Captura de pantalla de MTB a Fondo

Captura de pantalla de MTB a Fondo

MTB a Fondo ha sido creado como una pequeña red social especializada en ciclismo; su principal función es que los aficionados al ciclismo podamos compartir noticias, ideas, experiencias y conocimiento. Es una herramienta pensada para ser usada por nuestro grupo de amigos, pero que está abierta a cualquiera que quiera participar. Originariamente fue creada como una sección de mi página principal (www.eniac2000.com), pero como me aconsejó mi buen amigo Manolo, si quería darle algo de vidilla, era más conveniente crear la red como una web aparte. Y así fue como me decidí a compar el dominio www.mtbafondo.es

En cuanto a su estructura, está formada por los siguientes elementos:

  • WordPress: Es un gestor de contenido. Aunque está principalmente enfocado a la creación de blogs, la gran cantidad de plugins que admite hace que se pueda extender su funcionalidad habitual mucho más allá, y dotar al sistema de capacidades adicionales, como en este caso.
  • BuddyPress: Es un plugin para WordPress que permite dotarlo de funcionalidades de red social (una especie de Feisbuk, para entendernos): un muro en donde puedes colgar rápidamente entradas rápidas o pequeños mensajes, una sección de usuarios ampliada, en la que se pueden establecer amigos y enviar mensajes privados, un foro integrado, una sección de grupos, donde se pueden crear agrupaciones de interés para temas comunes (y que se integra con el foro y el muro), etc…
  • Plugins adicionales: Además de este plugin, he añadido otros más a la red social, que permiten extender las funciones anteriores: un gestor de eventos, para gestionar las quedadas ciclistas, un gestor de archivos, para almacenar ficheros (caso de los GPX que citaba antes, además de imágenes), o un sistema de suscripción por correo electrónico, que permite que los artículos o novedades que se publiquen en la web sean enviados de manera automática a una dirección de correo, permitiendo escoger de qué secciones quieres recibir correos de aviso.

He hablado un poco de las principales funcionalidades que ofrece MTB a Fondo, pero existen otras dignas de destacar:

  • Suscripción RSS: MTB a Fondo dispone, como todo sitio basado en WordPress, de fuente de contenidos RSS, que permite que el contenido del sitio pueda ser seguido sin tener que acceder a la página, a traves de lectores como Google Reader o aplicaciones ajenas a navegadores, como lectores de correo o aplicaciones específicas para móvil
  • Icono de contenido RSS

    Icono de contenido RSS

  • Avisos por correo a usuarios: Cada vez que un usuario de la red cita a otro en sus comentarios (insertando una “@” delante de su nombre), el usuario citado recibe automáticamente un correo electrónico de aviso, lo que permite seguir de manera más ágil las conversaciones que se generan el el sitio.
  • Mensajes privados entre usuarios: Además de los mensajes públicos del sitio, se pueden enviar mensajes privados a usuarios, sin publicidad para el resto de la web.
  • Escribiendo un mensaje privado

    Escribiendo un mensaje privado

  • Chat integrado: Además de la parte de red social convencional, MTB a Fondo dispone de un chat integrado, visible sólo para los usuarios registrados. Este chat, al estilo de Google Talk, permite una mayor agilidad de comunicación entre los usuarios del sitio. :)
  • Aspecto general del chat integrado

    Aspecto general del chat integrado

  • Integración de sitios externos: ¿Escribes en otra página y no quieres tener que repetir contenido en este sitio? ¡Sin problemas! Ese es exactamente mi caso: escribo entradas de ciclismo en mi sitio habitual (www.eniac2000.com), y no me apetece tener que repetir lo que escribo en MTB a Fondo. Para ello he instalado un plugin (FeedWordPress) que permite hacer uso el RSS/Atom de tu sitio habitual para que el contenido de éste sea publicado de manera automática en tu usuario de MTB a Fondo.
  • Acceso optimizado para teléfonos móviles: Otra aplicación que le he instalado permite detectar automáticamente si se está accediendo a la web por un dispositivo móvil (Android, iPhone, etc…), y presenta una interfaz optimizada para acceder de manera más cómoda con estos dispositivos.
  • Captura de pantalla de MTB a Fondo en un Android

    Captura de pantalla de MTB a Fondo en un Android

  • Integración con Twitter: Otra de las vocaciones de esta red es la facilidad de compartir información. Cada una de las entradas publicadas tiene la posibilidad de ser compartida fácilmente con Twitter, y hacer un seguimiento de su actividad. Y es más, se puede sincronizar el usuario del MTB a Fondo con nuestro usuario de Twitter, de tal manera que los comentarios que se publique en MTB a Fondo puedan ser enviados automáticamente a Twitter, tan sólo añadiendo el tag #twitter delante de nuestra entrada.
  • Compartiendo información con Twitter

    Compartiendo información con Twitter

Otros Mundos

Otra de las cosas que he procurado proporcionar con MTB a Fondo es una facilidad para seguir la actividad del sitio. Esto no se limita al seguimiento mediante RSS que comentaba antes, sino que he integrado la publicación de la actividad de la página en Facebook y en Twitter:

  • Facebook: Para lograr la integración con Facebook, he creado una página (MTB a Fondo en Facebook) en la que se publican automáticamente las nuevas entradas de MTB a Fondo. Por desgracia, la sincronización no es bidireccional, por lo que, si bien es posible publicar cosas en la versión de FaceBook, estas publicaciones no aparecerán en MTB a Fondo. Pero espero mejorar esto. :) La sincronización se realiza mediante la aplicación de Facebook NetworkedBlogs.
  • MTB a Fondo en Facebook

    MTB a Fondo en Facebook

  • Twitter: ¡Tambien estamos en Twitter. Además de lo comentado anteriormente con respecto a Twitter, la propia MTB a Fondo tiene su correspondiente Twitter (MTB a Fondo en Twitter), donde igualmente se publican las novedades del sitio, y facilita seguir las novedades que acontezcan mediante esta popular aplicación.
MTB a Fondo en Twitter

MTB a Fondo en Twitter

Creo que con esto he desgranado lo más importante de la página, en lo que se refiere a los aspectos técnicos. Pero una web social no es nada sin sus usuarios. Por ello, animo a cualquiera que quiera participar en el sitio a que se registre, participe, disfrute con la página, y que la haga suya. ¡Adelante! :D

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

Etiquetas: , , , , , , ,

17 sep 10 Corregido error que impedía publicar comentarios

Gracias a Ángel (¡gracias nen!) he visto que desde que actualicé el plugin que despliega el captcha para usuarios no autenticados (es decir, todo el mundo menos yo) no se podían escribir comentarios. Todo era un tema de permisos de escritura en el servidor, que ya ha quedado corregido. ^_^

Estaba ya a punto de empezar a cantar aquello de estoy solo, no me quieren… :mrgreen:

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

Etiquetas: , , , ,

25 ago 10 Corrección de error en mostrado panorámicas con WordPress y Gallery2

El sistema que utilizo para publicar este sitio web es el siguiente: se utiliza como base el gestor de contenidos WordPress, complementado con algunas soluciones periféricas. La principal de ellas es la integración con el sistema de gestión de galerías fotográficas Gallery2, que se realiza mediante un plugin diseñado al efecto: WPG2.

No todas las fotografías que publico son gestionadas mediante Gallery2. Para fotografías sueltas utilizo el propio sistema de WordPress, pero cuando inserto referencias a una serie fotográfica (correspondiente a algún viaje o evento concreto) sí que suelo utilizar Gallery2. El sistema es bastante simple: una vez subidas las fotografías a Gallery2 y catalogadas por éste, desde WordPress sólo es necesario hacer referencia al identificador de la imagen mediante la etiqueta <wpg2id> para insertar la imagen en la entrada. Con esta referencia, el artículo muestra una versión reducida de la imagen, y un enlace a la imagen original dentro de la estructura de la galería de imágenes, adaptada para su visualización en WordPress,

Por lo general, el sistema funciona bastante bien. Sin embargo, desde hacía tiempo había observado un problema con las imágenes panorámicas, en las que existe una gran diferencia entre el ancho y el alto de la imagen: cuando insertaba una imagen mediante el sistema explicado anteriormente, en el caso de las fotografías panorámicas no se mostraba la miniatura de la imagen, sino la imagen completa, pero escalada al tamaño de la miniatura definida. Los problemas que esto provoca, especialmente en tiempo de carga, eran significativos, ya que algunas de las panorámicas pueden alcanzar tamaños de más de 10000×2000 píxels, y pesos superiores a los 10 MB, mientras que las miniaturas asociadas tienen unas dimensiones máximas de 400 píxels en su lado más grande, y pesos inferiores a los 30 KB.

Tras un tiempo de investigación, he conseguido dar con una solución al problema, en los foros de Gallery: <wpg2> tags use always full-size versions En una de las entradas, uno de los usuarios informa de que el problema se debe al método en el que el sistema estudia si ha de escoger mostrar una miniatura o la versión completa de la imagen, aunque escalada. Para determinar esto el sistema compara el ancho y el alto de la imagen. Esta comparación, si bien resulta adecuada para la mayoría de las imágenes, produce problemas en aquellas con importantes diferencias entre ancho y alto, como es el caso de las panorámicas. Ante ello, el usuario propone hacer uso sólo del ancho. Para ello, es necesario realizar modificaciones en el archivo ImageBlockHelper.class, ubicada en el directorio /modules/imageblock/classes de Gallery2 (en mi caso, al usar el paquete Debian, su ruta completa es /usr/share/gallery2/modules/imageblock/classes). En concreto, es necesario realizar unas modificaciones a partir de la línea 424 del archivo:

/* Get the list of resizes */
$resizes = array();
list ($ret, $ok) = GalleryCoreApi::hasItemPermission(
$derivativeParentId, 'core.viewResizes', $userId);
if ($ret) {
return array($ret, null);
}
if ($ok) {
list ($ret, $resizes) =
GalleryCoreApi::fetchResizesByItemIds(array($derivativeParentId));
if ($ret) {
return array($ret, null);
}
$resizes = isset($resizes[$derivativeParentId]) ? $resizes[$derivativeParentId]
: array();
}
if (isset($thumbnail)) {
$resizes[] = $thumbnail;
}
foreach ($resizes as $imageObject) {
/*Primera modificacion*/
/*                  $rawDifferential = ($imageObject->getHeight() - $maxSize)
+ ($imageObject->getWidth() - $maxSize);*/
$rawDifferential = ($imageObject->getWidth() - $maxSize);

if ($biggerOnly && $rawDifferential < 0) {
continue;
}
$resizeDifferential = abs($rawDifferential);
/*Segunda modificacion*/
/*                  $resizeSize = $imageObject->getHeight() * $imageObject->getWidth();*/
$resizeSize = $imageObject->getWidth();

/*
* If this differential is smaller than the last, update the image target and
* the comparison value.
* If two differentials are equidistant, use the larger based on image size.
*/
if ($resizeDifferential < $imageDifferential
|| $resizeDifferential == $imageDifferential
&& $resizeSize > $imageSize) {
$image = $imageObject;
$imageDifferential = $resizeDifferential;
$imageSize = $resizeSize;
}
}
}

Una vez hecho esto, en WordPress se empezarán a mostrar correctamente las miniaturas de las imágenes en vez de las versiones escaladas de las imágenes completas, en el caso de las panorámicas.

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

Etiquetas: , , , ,