Cómo Hacer Túneles SSH

Una de las funcionalidades extraordinarias que posee openssh es la de encapsular el tráfico inseguro a puertos TCP. A continuación vemos algunos ejemplos útiles de cuándo y cómo utilizarlos.

Túneles

unsplash-logo Aaron Burden

Algunas suposiciones:

  • openssh-server.example.com: Es el host que posee el servicio ssh y el servicio sin cifrar
  • otrohost.example.com: Es un host que posee un servidor web sin TLS pero que carece de ssh.
  • 192.0.2.1/24: Es la dirección IP del cliente ssh.
  • filtrado.example.com: Es un host que tiene el puerto del servicio al que queremos acceder pero se encuentra filtrado para el exterior.
  • casa.example.com: Es un host remoto respecto a un servidor ssh accesible desde la red de filtrado.example.com. Este host está en un lugar en el cual podemos trabajar cómodamente 😊 por fuera de la infraestructura de filtrado.example.com.

Caso 1: Redireccionado desde un puerto local a un puerto remoto para segurizar un servicio sin cifrar

Queremos segurizar el acceso a un servidor web sin TLS.

ssh -N -f -L 10001:localhost:80 openssh-server.example.com

  • 80: Es el puerto que tiene el servicio sin cifrar
  • localhost: Es la dirección en el host servicio-remoto.example.com que escucha en el puerto 80.
  • 10001: Es el puerto local al cual tendremos que conectarnos para obtener el servicio web.
  • -N No ejecuta comandos en el lado remoto.
  • -f El proceso va al segundo plazo antes de la ejecución de comandos.

El url que habrá que poner en el navegador es http://localhost:10001

Caso 2: Redireccionado desde un puerto local a un puerto remoto permitiendo el acceso al túnel usuarios de la misma red local para Segurizar un servicio sin cifrar

Queremos permitir que otros hosts de la red puedan acceder nuestro servicio encapsulado.

ssh -g -N -f -L 10001:localhost:80 openssh-server.example.com

  • -g Permite acceder a otros hosts de la red 192.0.2.0/24 acceder a el url http://192.0.2.1:10001/

Caso 3: Redireccionado desde un puerto local a un puerto remoto usando otro servidor ssh para acceder a un servicio sin TLS ni ssh

ssh -N -f -L 10001:otrohost.example.com:80 openssh-server.example.com

  • Aquí la url será http://localhost:10001

Caso 4: Crear un túnel en dirección inversa para acceder a un puerto SSH filtrado (utilización de un túnel remoto)

En este caso, queremos acceder al puerto SSH de filtrado.example.com, que no es accesible desde internet. Utilizamos casa.example.com con acceso SSH temporal para redirigir el puerto SSH de filtrado.example.com.

El comando debe ejecutarse en filtrado.example.com:

ssh  -N -f -R 9000:localhost:22 casa.example.com
  • 22: Es el puerto SSH de filtrado.example.com.
  • 9000: Es el puerto redirigido en casa.example.com.

Para conectarse al puerto SSH de filtrado.example.com desde casa.example.com:

ssh -p 9000 localhost

Caso 5: Redireccionamiento remoto para permitir acceso compartido a un puerto filtrado

En este caso, queremos redirigir el puerto SSH de un servidor filtrado (filtrado.example.com) hacia un servidor intermedio (casa.example.com) y permitir que otros hosts que están en la misma red local puedan acceder al túnel.

Comando para configurar el túnel:

ssh  -N -f -R 0.0.0.0:9000:localhost:22 casa.example.com
  • 0.0.0.0:9000: Permite que el puerto redirigido esté accesible en todas las interfaces de red de casa.example.com.
  • localhost:22: Redirige el tráfico al puerto SSH de filtrado.example.com.

Para conectarse al túnel desde cualquier host con acceso a casa.example.com:

ssh -p 9000 casa.example.com
Requisito en casa.example.com

Habilitar GatewayPorts en /etc/ssh/sshd_config:

GatewayPorts clientspecified

Con esta configuración si el cliente no especifica explícitamente 0.0.0.0 al crear el túnel, los puertos siguen siendo locales por defecto.

Reinicia el servicio SSH:

sudo systemctl restart sshd
Notas de Seguridad

Si el servidor casa.example.com tiene una IP pública, usar firewalls para limitar el acceso al puerto 9000 y restringirlo solo a las máquinas necesarias. Para mayor seguridad, se puede especificar una interfaz específica en lugar de 0.0.0.0.

Troubleshooting

En todas las casos usar la opción -v para obtener realizar debugging. Recordar que dicha opcioń se puede usar múltiples veces para aumentar el detalle.

Como instalar Zabbix 7.x usando contenedores podman

Namespaces en Linux

Zabbix es una potente herramienta de monitoreo. Recientemente salió la versión 7.0 la cual incorporó funcionalidades importantes, como son los items de browser que usan webdrivers. A continuación veremos como implementar Zabbix 7.x usando podman.

La guía siguiente supone que:

  • Ya generaste o adquiriste los certificados ssl.
  • Tenés los conocimientos fundamentales sobre Linux (usamos RHEL8).
  • Poseés conocimientos básicos de troubleshooting en contenedores y entendiendo que este "HowTo" es un punto al que deberás adaptar a tu entorno y necesidades. No es consultoría 😀.

1. Crear el Pod con Puertos Correctos

Primero, crear el pod con el puerto 443 en el host mapeado al puerto 8443 en el contenedor de NGINX. También asignar el puerto 10051 para Zabbix Server.

podman pod create --name zabbix -p 443:8443 -p 10051:10051

2. Desplegar el Contenedor MySQL

Iniciar el contenedor mysql-server dentro del pod, configurando las variables de entorno necesarias para la base de datos de Zabbix:

mkdir mysql && podman run -d --name mysql-server --pod=zabbix \
    -v ./mysql:/var/lib/mysql:Z \
    -e MYSQL_DATABASE="zabbix" \
    -e MYSQL_USER="zabbix" \
    -e MYSQL_PASSWORD="zabbix_pwd" \
    -e MYSQL_ROOT_PASSWORD="root_pwd" \
    docker.io/library/mysql:8.0

3. Configurar log_bin_trust_function_creators en MySQL

Para evitar problemas con permisos de creación de funciones, habilita esta configuración en el servidor MySQL:

Darle tiempo a que MySQL esté listo:

until podman exec mysql-server mysqladmin ping -u root -p'root_pwd' --silent; do
    echo "Esperando a que MySQL esté listo..."
    sleep 5
done

Ejecutar la configuración:

podman exec -i mysql-server mysql -u root -p'root_pwd' -e "SET GLOBAL log_bin_trust_function_creators = 1;"

4. Desplegar el Contenedor Zabbix Server

Iniciar el contenedor zabbix-server-mysql en el pod, conectándolo a MySQL y asegurándote de que se conecte al Java Gateway:

podman run -d --name zabbix-server-mysql --pod=zabbix \
    -e DB_SERVER_HOST="127.0.0.1" \
    -e MYSQL_USER="zabbix" \
    -e MYSQL_PASSWORD="zabbix_pwd" \
    -e MYSQL_DATABASE="zabbix" \
    -e ZBX_JAVAGATEWAY="127.0.0.1" \
    docker.io/zabbix/zabbix-server-mysql:alpine-latest

5. Verificar la Creación de Tablas en la Base de Datos

Confirmar que zabbix-server-mysql crea correctamente las tablas en la base de datos:

podman exec -i mysql-server mysql -u root -p'root_pwd' -e "USE zabbix; SHOW TABLES;"

6. Desplegar el Contenedor Zabbix Java Gateway

Iniciar el contenedor zabbix-java-gateway, asegurándote de que esté en el pod zabbix:

podman run -d --name zabbix-java-gateway --pod=zabbix docker.io/zabbix/zabbix-java-gateway:alpine-latest

7. Desplegar el Contenedor NGINX con Certificados SSL y Configuración

Ejecutar el contenedor de Zabbix Web NGINX MySQL (zabbix-web-mysql-ssl), montando los certificados y el archivo de configuración zabbix-ssl.conf correctamente:

El archivo de configuración zabbix-web-mysql-ssl puede ser algo así:

server {
    listen 8443 ssl;
    server_name _;

    ssl_certificate /etc/ssl/nginx/fullchain.pem;
    ssl_certificate_key /etc/ssl/nginx/privkey.pem;

    root /usr/share/zabbix;

    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/tmp/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /usr/share/zabbix$fastcgi_script_name;
    }

    error_log /tmp/zabbix_ssl_error.log;
    access_log /tmp/zabbix_ssl_access.log;
}
podman run -d --name zabbix-web-mysql-ssl --pod=zabbix \
    -v ./certs/fullchain.pem:/etc/ssl/nginx/fullchain.pem:ro \
    -v ./certs/privkey.pem:/etc/ssl/nginx/privkey.pem:ro \
    -v ./zabbix-ssl.conf:/etc/nginx/http.d/zabbix-ssl.conf:ro \
    -e ZBX_SERVER_HOST="127.0.0.1" \
    -e DB_SERVER_HOST="127.0.0.1" \
    -e MYSQL_DATABASE="zabbix" \
    -e MYSQL_USER="zabbix" \
    -e MYSQL_PASSWORD="zabbix_pwd" \
    docker.io/zabbix/zabbix-web-nginx-mysql:alpine-latest

8. Verificación Final

Hacer una solicitud a la interfaz de Zabbix para confirmar que todo esté funcionando y que la configuración SSL esté activa:

curl -v  https://sebelk.lab

Deberías ver una respuesta HTTP 200 desde NGINX, indicando que Zabbix está activo y funcionando con SSL.

9. Instalación del agente

podman run -d --name zabbix-agent --pod=zabbix \
    -e ZBX_SERVER_HOST="127.0.0.1" \
    -e ZBX_SERVER_PORT="10051" \
    -e ZBX_HOSTNAME="ZabbixServerAgent" \
    docker.io/zabbix/zabbix-agent2:alpine-latest

10. Deshabilitar variable en MySQL

La variable que habilitamos antes no es imprescindible, de modo que se puede desactivar:

podman exec -i mysql-server mysql -u\
     root -p'root_pwd'\
    -e "SET GLOBAL log_bin_trust_function_creators = 0;"

Todo listo

¡Listo! Trabajo terminado 😉

Zabbix Implementado usando podman

¿Qué te pareció la guía? Podés usar la sección de Comentarios.