/

Enrutar Trafico Ssh a Contenedores Lxc Con Haproxy

Created 2020-02-22 Modifyed 2020-02-22
961 Words

Cuando tenemos contenedores lxc en un servidor, estos suelen estar en una red diferente a la red donde esta huestro host anfitrión. En estas ocasiones, lxc crea un nat, y no podemos acceder directamente a estos contenedores desde fuera.

En este artículo vamos a poner un haproxy en el host anfitrion (de aquí en adelante server0), que se va a encargar de redirigir el trafico ssh que le entre a server0 por un determinado puerto, al puerto donde este escuchando el servicio ssh del contenedor lxc.

enrutar-trafico-ssh-a-contenedores-lxc-con-haproxy-1

Lo primero que necesitamos es lxc y lxd en server0, así que vamos a comprobar si lo tenemos instalado con lxc version

athos@server0:~$ lxc version
2.0.11

Vemos que lo tenemos instalado, pero vamos a instalar la versión 3, para esto lo haremos así:

sudo apt install -t xenial-backports lxd lxd-client -y

athos@server0:~$ lxc version
If this is your first time running LXD on this machine, you should also run: lxd init
To start your first container, try: lxc launch ubuntu:18.04

Client version: 3.0.3
Server version: 3.0.3

Se nos advierte de que es la primera vez que ejecutamos LXD y que deberíamos ejecutar lxd init. Lo hacemos y dejamos todas las opciones por defecto.

athos@server0:~$ lxd init
Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]: 
Name of the new storage pool [default=default]: 
Name of the storage backend to use (btrfs, dir, lvm) [default=btrfs]: 
Create a new BTRFS pool? (yes/no) [default=yes]: 
Would you like to use an existing block device? (yes/no) [default=no]: 
Size in GB of the new loop device (1GB minimum) [default=15GB]: 
Would you like to connect to a MAAS server? (yes/no) [default=no]: 
Would you like to create a new local network bridge? (yes/no) [default=yes]: 
What should the new bridge be called? [default=lxdbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
Would you like LXD to be available over the network? (yes/no) [default=no]: 
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: 

Una vez hecho esto, vamos a levantar tres contenedores como se ve en la imagen superior.

lxc launch ubuntu:16.04 lxc0

lxc launch ubuntu:16.04 lxc1

lxc launch ubuntu:16.04 lxc2

athos@server0:~$ lxc list
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| NAME |  STATE  |         IPV4          |                     IPV6                      |    TYPE    | SNAPSHOTS |
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| lxc0 | RUNNING | 10.108.131.2 (eth0)   | fd42:f96f:612f:6693:216:3eff:fe9c:a58a (eth0) | PERSISTENT | 0         |
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| lxc1 | RUNNING | 10.108.131.206 (eth0) | fd42:f96f:612f:6693:216:3eff:fe8c:516 (eth0)  | PERSISTENT | 0         |
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| lxc2 | RUNNING | 10.108.131.167 (eth0) | fd42:f96f:612f:6693:216:3eff:feec:fa39 (eth0) | PERSISTENT | 0         |
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+

Deberemos meter una clave publica en el authorized_keys de cada uno de los contenedores para poder acceder desde el cliente.

Y también instalaremos haproxy

sudo apt install haproxy -y

Bien, una vez instalado, deberemos configurar el archivo /etc/haproxy/haproxy.cfg. De la configuración que viene por defecto, en la parte defaults he cambiado el modo de http a tcp. Luego ha añadido dos bloques para cada uno de nuestros contenedores, el frontend y el backend.

En el bloque frontend estamos definiendo desde que ips aceptamos trafico y por que número de puerto, y el backend al que lo redireccionaremos.

En este enlace hay una buena documentación de las opciones y directivas que tenemos para configurar el archivo haproxy.cfg

En el bloque backend estamos diciendo el tipo de balanceo que haremos y a que contenedor lxc vamos a redireccionar el tráfico.

global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin
        stats timeout 30s
        user haproxy
        group haproxy
        daemon

        # Default SSL material locations
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private

        # Default ciphers to use on SSL-enabled listening sockets.
        # For more information, see ciphers(1SSL). This list is from:
        #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
        ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
        ssl-default-bind-options no-sslv3

defaults
        log     global
        mode    tcp
        #mode   http
        option  tcplog
        #option httplog
        option  dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http

frontend lxc0
    bind 0.0.0.0:2220
    default_backend lxc0

backend lxc0
    balance roundrobin
    server lxc0 10.108.131.2:22 check

frontend lxc1
    bind 0.0.0.0:2221
    default_backend lxc1

backend lxc1
    balance roundrobin
    server lxc1 10.108.131.206:22 check

frontend lxc2
    bind 0.0.0.0:2222
    default_backend lxc2

backend lxc2
    balance roundrobin
    server lxc2 10.108.131.167:22 check

Si ahora nos intentamos conectar al server0 por el puerto 2220,2221 o 2222 nos redireccionará al contenedor lxc correspondiente.

athos@athos-Z97P-D3:~$ ssh -p 2220 root@192.168.1.121
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


0 packages can be updated.
0 updates are security updates.

New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


Last login: Sat Feb 22 13:57:26 2020 from 10.108.131.1
root@lxc0:~# 

athos@athos-Z97P-D3:~$ ssh -p 2221 root@192.168.1.121
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


0 packages can be updated.
0 updates are security updates.

New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


Last login: Sat Feb 22 13:57:13 2020 from 10.108.131.1
root@lxc1:~# 

athos@athos-Z97P-D3:~$ ssh -p 2222 root@192.168.1.121
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


0 packages can be updated.
0 updates are security updates.

New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


Last login: Sat Feb 22 14:00:38 2020 from 10.108.131.1
root@lxc2:~# 

Y esto es todo lo necesario. El post parece un poco largo para lo que hemos hecho.

El resumen es que instalamos haproxy, cambiamos el modo, y ponemos los bloques frontend y backend para cada contenedor.