You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
7.6 KiB
Markdown

---
title: "Ansible: Escenario router-nat"
date: 2022-10-18T13:49:56+02:00
draft: false
tags: ["ansible","vagrant"]
---
Creación del siguiente escenario con un cliente y un router-nat utilizando **vagrant** y **ansible**
![escenario](escenario.png)
## Vagrant
Según el esquema de red que tenemos que replicar, vamos a crear una **red muy aislada** entre las dos máquinas. También, el router tendrá un **bridge** que será su puerta de enlace predeterminada. En el caso del cliente, esta configuración se hará más adelante. El `Vagrantfile` queda de la siguiente manera:
{{< highlight ruby "linenos=table">}}
config.vm.define :router do |router|
router.vm.box = "debian/bullseye64"
router.vm.hostname = "router"
router.vm.synced_folder ".", "/vagrant", disabled: true
router.vm.network :public_network,
:dev => "br0",
:mode => "bridge",
:type => "bridge",
use_dhcp_assigned_default_route: true
router.vm.network :private_network,
:libvirt__network_name => "red-muy-aislada",
:libvirt__dhcp_enabled => false,
:ip => "192.168.0.1",
:libvirt__forward_mode => "veryisolated"
end
config.vm.define :cliente do |cliente|
cliente.vm.box = "debian/bullseye64"
cliente.vm.hostname = "cliente"
cliente.vm.synced_folder ".", "/vagrant", disabled: true
cliente.vm.network :private_network,
:libvirt__network_name => "red-muy-aislada",
:libvirt__dhcp_enabled => false,
:ip => "192.168.0.2",
:libvirt__forward_mode => "veryisolated"
end
end
{{< / highlight >}}
Creamos las máquinas virtuales:
```bash
vagrant up
```
## Ansible
Ahora nos movemos al directorio donde se va a encontrar el **playbook** (`ansible/`). empezamos por el fichero `hosts`;
### hosts
El fichero `hosts` contiene la información de las máquinas en las que vamos a realizar el despliegue, pero antes de crearlo necesitamos conseguir las direcciones IPs que tienen asignadas en la interfaz **eth0** (la de Vagrant). Para ello usamos el siguiente comando:
{{< highlight bash "hl_lines=2" >}}
$ vagrant ssh cliente -c "hostname -I | cut -d' ' -f1" 2>/dev/null
192.168.121.77
{{< / highlight >}}
{{< highlight bash "hl_lines=6" >}}
$ vagrant ssh router -c "hostname -I | cut -d' ' -f1" 2>/dev/null
==> router: You assigned a static IP ending in ".1" to this machine.
==> router: This is very often used by the router and can cause the
==> router: network to not work properly. If the network doesn't work
==> router: properly, try changing this IP.
192.168.121.146
{{< / highlight >}}
Nos aparece una alerta ya que el router tiene una dirección IP acabada en ".1", Lo ignoramos ya que la máquina es el **router de la red**. Con la salida de ambos comandos tenemos las IPs de las máquinas y, añadiendo además las **rutas de las claves privadas**, podemos crear el fichero:
{{< highlight yaml "linenos=table,hl_lines=6 10" >}}
all:
children:
maquinas:
hosts:
cliente:
ansible_ssh_host: 192.168.121.77
ansible_ssh_user: vagrant
ansible_ssh_private_key_file: ../.vagrant/machines/cliente/libvirt/private_key
router:
ansible_ssh_host: 192.168.121.146
ansible_ssh_user: vagrant
ansible_ssh_private_key_file: ../.vagrant/machines/router/libvirt/private_key
{{< / highlight >}}
Ahora podemos crear las máquinas con `vagrant up`:
![vagrant](vagrant.png)
### site.yaml
Tras eso creamos el fichero que contiene la información de asignación de roles, que deben ser de la siguiente manera:
* **common**: Estas tareas se deben ejecutar en todos los nodos: actualizar los paquetes y añadir tu clave pública a la máquinas para poder acceder a ellas con ssh. ¿Existe algún módulo de ansible que te permita copiar claves públicas?.
* **router**: Todas las tareas necesarias para configurar router cómo router-nat y que salga a internet por eth1. Las configuraciones deben ser permanentes. ¿Existe algún módulo de ansible que te permita ejecutar sysctl?.
* **cliente**: Todas las tareas necesarias para que las máquinas conectadas a la red privada salgan a internet por eth1.
* **web**: Las tareas necesarias para instalar y configurar un servidor web con una página estática en la máquina cliente.
{{< highlight yaml "linenos=table" >}}
- hosts: all
become: true
roles:
- role: common
- hosts: router
become: true
roles:
- role: router
- hosts: cliente
become: true
roles:
- role: web
- role: cliente
{{< / highlight >}}
### Roles
Para realizar el despliegue indicado tenemos que crear los roles. Las tareas de los roles, están contenidas en una estructura de carpetas dentro de la carpeta rol, siendo de la siguiente manera:
```bash
rolejemplo
├── defaults
├── files
├── handlers
├── library
├── tasks
├── templates
└── vars
```
conteniendo las tareas que realizará. Empezaremos por **common**:
#### Common
Este rol es bastante sencillo ya que solo cuenta con un fichero `tasks/main.yaml` que contiene la instrucción para comprobar que el sistema está actualizado:
{{< highlight yaml "linenos=table" >}}
- name: Comprueba que el sistema esta actualizado
apt: update_cache=yes upgrade=yes
- name: Introduce la clave publica desde un fichero
authorized_key:
user: vagrant
state: present
key: "{{ lookup('file', '/home/roberto/.ssh/id_rsa.pub') }}"
{{< / highlight >}}
#### Router
Todas las tareas necesarias para configurar router cómo router-nat y que salga a internet por eth1. Las configuraciones deben ser permanentes. El contenido de `tasks/main.yaml` es el siguiente:
{{< highlight yaml "linenos=table" >}}
- name: Cambia el bit de forward a 1
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: '1'
sysctl_set: yes
state: present
reload: yes
- name: Configuracion de DNAT
iptables:
chain: PREROUTING
in_interface: eth1
destination_port: 80
jump: DNAT
protocol: tcp
table: nat
to_destination: 10.0.0.2:80
become: yes
- name: Configuracion de SNAT
iptables:
chain: POSTROUTING
destination: 10.0.0.0/8
jump: MASQUERADE
out_interface: eth1
table: nat
become: yes
{{< / highlight >}}
#### Web
Las tareas necesarias para instalar y configurar un servidor web con una página estática en la máquina cliente. El contenido de `tasks/main.yaml` es el siguiente:
{{< highlight yaml "linenos=table" >}}
- name: "ensure apache2 is installed"
apt:
pkg: apache2
- name: copy template index
template:
src: index.j2
dest: /var/www/html/index.html
owner: www-data
group: www-data
mode: 0644
- name: "Copiar fichero al servidor remoto"
copy:
src: fichero.html
dest: /var/www/html/fichero.html
owner: www-data
group: www-data
mode: '0644'
- name: "Copiar fichero de configuración y reiniciar el servicio"
copy:
src: etc/apache2/ports.conf
dest: /etc/apache2/ports.conf
owner: root
group: root
mode: '0644'
notify: restart apache2
{{< / highlight >}}
En esta tarea si que se utilizan otros ficheros, pero al no tener una configuración crucial, no vamos a modificarlos. Su contenido se encuentra en github.
#### Cliente
Todas las tareas necesarias para que las máquinas conectadas a la red privada salgan a internet por eth1. El contenido de `tasks/main.yaml` es el siguiente:
{{< highlight yaml "linenos=table" >}}
- name: cambiar la ruta por defecto
shell: ip route delete default && ip route add default via 10.0.0.1 && echo "post-up route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.0.0.0 dev eth1" >> /etc/network/interfaces
{{< / highlight >}}
---
Finalmente, podemos ejecutar el playbook con `ansible-playbook site.yaml`:
![ansible](ansible.png)