En alguna ocasión, es posible que necesitemos que el tráfico que recibe una máquina en un determinado puerto, sea redirigido a otra máquina diferente.
Por poner un ejemplo, pillamos un servidor en cualquier proveedor. El proveedor nos da una ip pública a través de la cual podemos acceder a dicho server.
Pero dentro del servidor, queremos montar un sistema de contenedores con lxc. En el ejemplo de la foto, se puede ver, que el servidor contratado tiene la ip 82.85.85.82 (más adelante crearemos un contenedor llamado host para simularlo) y dentro de el, hemos creado tres contenedores, y cada uno de ellos tendrá un servicio diferente. En uno pondremos un apache, en otro un nginx, y en otro un servidor dns.
Bien, nuestro objetivo, es que el trafico que reciba nuestro host por el puerto 80, se redirija al contenedor con el servicio apache (lxc0), el tráfico recibido en el host por el puerto 8080, lo enrutaremos al lxc que contiene el nginx (lxc1), y el tráfico recibido por el host en el puerto 53 udp sea redirigido al contenedor que tiene el servicio dns (lxc2).
athos@athos-Z97P-D3:~$ lxc launch ubuntu:16.04 lxc0
Creating lxc0
Starting lxc0
athos@athos-Z97P-D3:~$ lxc launch ubuntu:16.04 lxc1
Creating lxc1
Starting lxc1
athos@athos-Z97P-D3:~$ lxc launch ubuntu:16.04 lxc2
Creating lxc2
Starting lxc2
athos@athos-Z97P-D3:~$ lxc list | grep lxc
| lxc0 | RUNNING | 10.163.200.199 (eth0) | fd42:def5:a1ff:ca5:216:3eff:fe5e:3885 (eth0) | PERSISTENT | 0 |
| lxc1 | RUNNING | 10.163.200.79 (eth0) | fd42:def5:a1ff:ca5:216:3eff:fe22:c9ca (eth0) | PERSISTENT | 0 |
| lxc2 | RUNNING | 10.163.200.134 (eth0) | fd42:def5:a1ff:ca5:216:3eff:fe95:68dc (eth0) | PERSISTENT | 0 |
athos@athos-Z97P-D3:~$
Bueno, ahí se pueden ver las ips internas que tendrá cada uno de nuestros contenedores (no coinciden con la imagen de arriba)
Instalamos los servicios en cada uno de los contenedores y podemos comprobar que cada contenedor nos da la respuesta esperada.
lxc0:
lxc1:
lxc2:
athos@athos-Z97P-D3:~/Documents/athosnetwork.es/front$ dig example.com @10.163.200.134
; <<>> DiG 9.10.3-P4-Ubuntu <<>> example.com @10.163.200.134
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35944
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 3600 IN A 127.0.0.2
;; Query time: 6 msec
;; SERVER: 10.163.200.134#53(10.163.200.134)
;; WHEN: Mon Mar 02 22:18:11 CET 2020
;; MSG SIZE rcvd: 67
Ahora voy a crear otro contenedor llamado host, que simulará nuestro host (valga la redundancia).
| host | RUNNING | 10.163.200.252 (eth0) | fd42:def5:a1ff:ca5:216:3eff:fed0:c0a (eth0) | PERSISTENT | 0 |
Hacemos las llamadas a este contenedor para ver su respuesta y como podemos ver, de momento si accedemos a esa ip no nos responde nada
Y si le consultamos la dns anteriormente tampoco
athos@athos-Z97P-D3:~/Documents/athosnetwork.es/front$ dig example.com @10.163.200.252
; <<>> DiG 9.10.3-P4-Ubuntu <<>> example.com @10.163.200.252
;; global options: +cmd
;; connection timed out; no servers could be reached
Ahora, vamos a hacer, que al acceder al host puerto 80 redirija el tráfico al contenedor lxc0
root@host:~# iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.163.200.199:80
root@host:~# iptables -t nat -A POSTROUTING -j MASQUERADE
root@host:~# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:http to:10.163.200.199:80
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- anywhere anywhere
Y ahora vemos que si nos redirecciona al contenedor que tiene el apache (lxc0)
Bien, el segundo paso, es hacer que cuando accedamos al puerto 8080 del host, nos redireccione al nginx(lxc1)
root@host:~# iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.163.200.79:80
root@host:~# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:http to:10.163.200.199:80
DNAT tcp -- anywhere anywhere tcp dpt:http-alt to:10.163.200.79:80
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- anywhere anywhere
MASQUERADE all -- anywhere anywhere
Y otra vez vemos que redirige bien
El tercer paso es hacer lo mismo con el puerto udp 53, tiene que redirigir al contenedor lxc2
root@host:~# iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to-destination 10.163.200.134
root@host:~# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:http to:10.163.200.199:80
DNAT tcp -- anywhere anywhere tcp dpt:http-alt to:10.163.200.79:80
DNAT udp -- anywhere anywhere udp dpt:domain to:10.163.200.134
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- anywhere anywhere
MASQUERADE all -- anywhere anywhere
Y la prueba es correcta
athos@athos-Z97P-D3:~$ dig example.com @10.163.200.252
; <<>> DiG 9.10.3-P4-Ubuntu <<>> example.com @10.163.200.252
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3046
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 3600 IN A 127.0.0.2
;; Query time: 2 msec
;; SERVER: 10.163.200.252#53(10.163.200.252)
;; WHEN: Mon Mar 02 22:30:28 CET 2020
;; MSG SIZE rcvd: 67
Resumiendo, con estas dos sencillas reglas podemos enrutar tráfico entre varias maquinas
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.163.200.103:80
iptables -t nat -A POSTROUTING -j MASQUERADE