---
weight: 4
title: "Apuntes de WireGuard"
date: 2021-04-18T22:20:51+0200
draft: false
summary: "Apuntes de WireGuard"
categories:
  - notes
tags:
  - wireguard
  - debian
  - alpine
---

Apuntes sobre WireGuard. Una herramienta para implementar redes VPN

<!--more-->

{{< admonition type=warning title="Work in progress" open=true >}}
Estos apuntes no están completos, (ni de lejos)
{{< /admonition >}}


# WireGuard

{{< admonition type=abstract title="Referencias" open=false >}}


- [WireGuard: Conceptual Overview](https://www.wireguard.com/#conceptual-overview)
- [WireGuard on Ubuntu](https://www.xmodulo.com/wireguard-vpn-server-ubuntu.html)
- [Set up WireGuard on Alpine Linux](https://www.cyberciti.biz/faq/how-to-set-up-wireguard-vpn-server-on-alpine-linux/)
- [Firewall rules for WireGuard](https://www.cyberciti.biz/faq/how-to-set-up-wireguard-firewall-rules-in-linux/)
- [Debian 10 set up WireGuard VPN server](https://www.cyberciti.biz/faq/debian-10-set-up-wireguard-vpn-server/)
- [Setting up a private mesh VPN with WireGuard](https://www.scaleway.com/en/docs/wireguard-mesh-network/)
- [Wireguard network managers](https://kaspars.net/blog/wireguard-managers)
    - [wg-gen-web](https://github.com/vx3r/wg-gen-web)

{{< /admonition >}}

<!--

AQUI TENEMOS INSTRUCCIONES PARA NETWORKMANAGER <https://www.xmodulo.com/wireguard-vpn-network-manager-gui.html>
- [Referencia Alpine Awall](https://www.cyberciti.biz/faq/how-to-set-up-a-firewall-with-awall-on-alpine-linux/)

-->


Las implementaciones tradicionales de VPN (_**V**irtual **P**rivate **N**etwork_) más utilizadas en la industria (como _IPsec_ por ejemplo) se implementan dentro del kernel; insertando una capa extra, que se encarga del cifrado y el encapsulado, entre la pila IP y el interfaz de red.

Esto se hace así por que se quiere que sea un proceso tan rápido como sea posible que no penalice la eficiencia de las comunicaciones. A cambio es necesario implementar por separado el _plano de tráfico_ (la capa que hemos mencionado dentro del kernel) y _el plano de control_ que se crea en el espacio de usuario. Esta arquitectura hace que tanto la implementación (el software) como la gestión de estas soluciones sean complejas.

En las implementaciones de VPN en el espacio de usuario, como por ejemplo _OpenVPN_, todo el proceso de cifrado lo hace un demonio en el espacio de usuario. Con esta arquitectura inevitablemente se penaliza el rendimiento, por qué los paquetes tienen que pasar del espacio kernel al espacio de usuario y viceversa varias veces. Aunque esto no impide que sean soluciones muy populares debido a su facilidad de uso.

_WireGuard_ es una alternativa relativamente reciente a _OpenVPN_ que puede ser muy interesante. Por un lado se implementa como un módulo del Kernel, y por otro mantiene la gestión y configuración a un nivel muy asequible por qué usa ficheros  de configuración **muy sencillos** y se basa en la metáfora de _interfaz de red_, que se gestiona como cualquier otro interfaz del sistema con las herramientas estándar como `ip` o `ifconfig`.

_WireGuard_ cifra y encapsula paquetes IP sobre UDP. Básicamente hay que añadir un interface _WireGuard_, configurarlo con tu clave privada y la clave pública de los pares (_peers_) con los que se va a comunicar y ya puedes enviar paquetes a través de ese túnel. En realidad es mucho más parecido a _SSH_ o _Mosh_ que a _OpenVPN_.

Como hemos dicho, al usar _WireGuard_ se añadirán uno (o varios) interfaces de red de tipo _WireGuard_ (wg0, wg1, ....) a tu máquina. Estos interfaces de red se pueden configurar normalmente con las herramientas del sistema, igual que un `eth0` o `wlan0`. Los aspectos específicos del _WireGuard Interface_ se configuran con la herramienta `wg`. Los interfaces _WireGuard_ se comportan como un túnel cifrado.

_WireGuard_ asocia las direcciones IP de los túneles con los extremos remotos y sus claves públicas.

Cuando el interfaz envía un paquete a un _peer_ hace lo siguiente:

1. Veamos, este paquete es para `192.168.30.8`. ¿Qué _peer_ es este? Vale, es para el _peer_ `pepito`. Si no soy capaz de determinar a que _peer_ esta dirigido descartaré el paquete (_drop_) **¡OJO!** WireGuard determina el _peer_ a partir de la IP destino
2. Cifra el paquete con la clave pública del _peer_ `pepito`
3. ¿Qué extremo remoto corresponde a este _peer_? Vale, es el puerto UDP 53133 en 216.58.211.110
4. Procedo a enviar los bytes cifrados al extremo remoto via UDP

En el extremo remoto, el _peer_ `pepito`que recibe el paquete:

1. Me ha llegado un paquete del puerto `7361` de `98.139.183.24`. Voy a descifrarlo.
2. Descifro y además compruebo que se garantiza la autenticidad para el peer `manolito`. Ya que estamos actualizo mi tabla de direcciones: Apunto que el destino más reciente para `manolito` es el `98.139.183.24:7361/UDP`
3. El paquete descifrado viene de `192.168.43.89` si el _peer_ `manolito` está autorizado a enviar paquetes con esa IP origen lo aceptamos, de lo contrario lo descartamos (_drop_)

El concepto fundamental en el que se base _WireGuard_ es el ___Cryptokey Routing___, consiste en almacenar una lista de claves públicas junto con la lista de direcciones IP origen que permitimos, ambas asociadas al _peer_ al que corresponde esa clave.

Así:
- Cada interfaz de red tiene una clave privada
- Cada interfaz de red tiene una lista de _peers_
- Cada _peer_ tiene una clave pública
- Para cada _peer_ se especifican las direcciones IP origen autorizadas

Un _servidor_ de _WireGuard_ podría tener una configuración como esta (no está completa es una configuración simplificada):

```toml
[Interface]
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24

[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16

[Peer]
PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
AllowedIPs = 10.10.10.230/32
```

Un _cliente_ puede tener una configuración más simple (no está completa):

```toml
[Interface]
PrivateKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE=
ListenPort = 21841

[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 192.95.5.69:51820
AllowedIPs = 0.0.0.0/0
```

Tanto el _"servidor"_ como el _"cliente"_ tienen un interfaz de red (al menos) con su clave privada asociada. Pero no te lies con los términos servidor y cliente, nada impide que configures varios interfaces de tu VPN como servidores.

El _servidor_ tiene también una lista de _peer_; cada uno con su lista `AllowedIPs`: la lista de direcciones IP origen que están autorizadas para ese _peer_

La configuración mínima para un cliente solo necesita tener como _peer_ al servidor. Se almacena una dirección ___inicial___ del servidor.

Deliberadamente no se mantienen direcciones estáticas para los _peer_, los _peer_ se identifican al descifrar un paquete recibido. Y se mantiene una tabla de direcciones más recientes para cada _peer_ que se actualiza con cada mensaje recibido. De esta forma los _peer_ podrían hacer _roaming_ por distintas redes.

Cuando el servidor recibe un paquete comprueba, una vez descifrado, que el _peer_ puede enviar paquetes con ese origen, en caso que no sea así lo descarta.

Cuando el servidor quiere enviar un paquete comprueba las redes asociadas a cada _peer_ para decidir a quien enviarlo, y lo envía a la dirección IP más reciente que tenga registrada para ese _peer_.

En el cliente (con la configuración de ejemplo) se aceptan paquetes de cualquier origen si provienen del _servidor_. También se envian todos los paquetes, sea cual sea la dirección de destino hacia el _servidor_. Como hemos dicho, los paquetes se envían a la dirección registrada más recientemente para el servidor, si el cliente ya ha recibido algún paquete, o a la dirección inicial especificada en la configuración si aún no ha recibido nada desde el _servidor_.

## Instalación de _WireGuard_


### Instalación de WireGuard en Debian Server 10

Añadimos `backports` a nuestros orígenes de software e instalamos _WireGuard_.

```bash
echo 'deb http://ftp.debian.org/debian buster-backports main' | sudo tee /etc/apt/sources.list.d/buster-backports.list
apt update
apt install wireguard
```

_WireGuard_ se ejecuta como un **módulo del kernel**

Genemos las claves en `/etc/wireguard`

```bash
umask 077
wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey
```

Editamos el fichero `sudo nano /etc/wireguard/wg0.conf` con el contenido:

```toml
[Interface]
Address = 10.0.0.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
```

El fichero de configuración no tiene por que ser accesible para nadie (`chmod 600 /etc/wireguard/wg0.conf`), al fin y al cabo contiene la clave privada.

Este fichero de configuración correspondería a un "servidor" de VPN clásico para dar acceso a internet a los "clientes" de la VPN via NAT.

Los campos del fichero de configuración:


**Address**

: La dirección IP **privada** (una dirección interna de la VPN) asignada al interfaz. Asignamos IP y máscara en un solo comando.

**SaveConfig**

: Si vale `true`la configuración del interfaz se salva en el fichero de configuración cada vez que hacemos un shutdown del interfaz

**ListenPort**

: El puerto UDP que escucha nuestro interfaz, los _peer_ (clientes) tienen que dirigirse a ese puerto

**PrivateKey**

: La clave de cifrado para este interfaz

**PostUp**

: Un comando o un script que se tiene que ejecutar **antes** de levantar el interfaz. En este ejemplo estamos habilitando _IP masquerading_. Esto permitirá que el tráfico salga del servidor dando a los clientes de la VPN acceso a internet (habría que sustituir `ens3` por el verdadero nombre del interfaz público del servidor)

**PostDown**

: Un comando o script que se tiene que ejecutar **antes** de bajar el interface. En nuestro ejemplo se borran la configuración de _IP masquerading_ de las IPtables. Es imprescindible sustituir `ens3` por el puerto real del servidor.


Podemos arrancar ya el interfaz `wg0` con el comando `wg-quick up wg0` (en mi caso necesité reiniciar el servidor previamente, supongo que para completar la instalación del módulo wireguard en el kernel)

```bash
root@vmi504132:~# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.0.0.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
root@vmi504132:~# wg show wg0
interface: wg0
  public key: rgbUE5KCfrUWT/7Vhh7NTdosCyP9LGx7M5vnJU9EAxw=
  private key: (hidden)
  listening port: 51820
root@vmi504132:~# ip addr show wg0
24: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 10.0.0.1/24 scope global wg0
       valid_lft forever preferred_lft forever
```

Hasta aquí hemos configurado nuestro nuevo interfaz `wg0` pero necesitamos completar un par de cosas más antes de terminar:

#### Abrir el cortafuegos para WireGuard

Tenemos que permitir tráfico entrante UDP en el puerto `51820`, en mi caso estoy usando UFW en el servidor:

```bash
ufw allow 51820/udp
ufw enable
ufw status numbered
ufw status verbose
```

#### Habilitar _ip forwarding_

Editamos el fichero `/etc/sysctl.conf` y descomentamos la linea:

`net.ipv4.ip_forward=1`

Recargamos el fichero ejecutando `sysctl -p /etc/sysctl.conf`

Evidentemente si queremos usar IPV6 tenemos que descomentar la linea correspondiente.

#### Configurar el arranque automático del interfaz cuando arranca el servidor

Para dejar configurado el arranque automático del interfaz `wg0`:

```bash
wg-quick down wg0              # Paramos el interfaz que hemos levantado manualmente

systemctl enable wg-quick@wg0  # Dejamos el servicio habilitado
systemctl status wg-quick@wg0  # Comprobamos el status del servicio


# systemctl start wg-quick@wg0 # Comandos para arrancar o parar el servicio
# systemctl stop wg-quick@wg0  # manualmente
```


### Creación de una máquina virtual en Proxmox con Alpine Linux y WireGuard

Creamos la máquina virtual igual que creamos la de Docker

1. Creamos la máquina virtual, basada en la ISO de _Alpine Linux_, asignamos un disco duro de 16Gb
2. Ejecutamos `alpine-setup` asignamos IP estática y el tipo de instalación `sys`
2. Instalamos `qemu-guest-agent` y configuramos adecuadamente
3. Instalamos `sudo` y habilitamos el grupo `wheel` (editando `/etc/sudoers`)
3. Añadimos usuario `wgadmin` (ya de paso lo metemos en `wheel`)
4. Instalamos UFW
5. Instalamos el WireGuard

    ```bash
    apk add sudo
    addgroup wgadmin
    adduser -G wgadmin wgadmin
    adduser wgadmin wheel
    apk add ufw
    ufw default deny incoming
    ufw default allow outgoing
    ufw allow ssh
    ufw enable
    apk add wireguard-tools
    ```

Ya tenemos todo listo para proceder con la configuración de _WireGuard_

```bash
cd /etc/wireguard
umask 077; wg genkey | tee privatekey | wg pubkey > publickey
```

Creamos el fichero de configuración `wg0.conf`

```toml
[Interface]
Address = 10.0.0.2/24
ListenPort = 51820
PrivateKey = 2IHAoIOz+tWxRZ4oRlI1xHiD5FADVBTKOePnLSZNSkw=


[Peer]
PublicKey = d7TRyBXIX0I3sC/tPOqrIpNAGwEt2bW43QXKK4cEeGw=
AllowedIPs = 0.0.0.0/0
Endpoint = 207.180.207.206:51820
PersistentKeepalive = 20
```

Habilitamos el _IP Forwarding_:

Por comando: `sysctl net.ipv4.ip_forward=1`

O si lo queremos permanente añadimos la linea `net.ipv4.ip_forward=1` en el fichero `/etc/sysctl.conf`

También tenemos que abrir el cortafuegos `ufw allow 51820/udp`

Ya podemos levantar el interfaz con `wg-quick up wg0`

Para que la cosa funcione tenemos que habilitar la redirección del puerto 51820/udp en nuestro router de internet para que apunte a la máquina virtual que hemos creado.

Llegamos por ping a la maquina siriowg pero no más allá (faltan rutas de vuelta hacia el servidor)

<!--

### Escenario: Salida a internet via VPN para el servidor HASS

Configuración de VPN server (el "servidor central")

```toml
[Interface]
Address = 10.200.200.1/24
PrivateKey = <vps_privatekey>
ListenPort = 37466

# Do not forget to change eth0 to the interface that is connected to the Internet!
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables - tnat -A POSTROUTING - oeth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables - tnat -D POSTROUTING - oeth0 -j MASQUERADE

# This is the peer inside the local subnet we want to have access to.
# For that to happen, you need to add your local subnet to the AllowedIPs
# option just like I did below.
[Peer]
PublicKey = <pi_publickey>
AllowedIPs = 10.200.200.2/32, 192.168.1.0/24

# A client...
[Peer]
PublicKey = <client_publickey>
AllowedIPs = 10.200.200.3/32

# An additional client...
[Peer]
PublicKey = <some other public key>
AllowedIPs = 10.200.200.4/32
```

Configuración en el cliente

```toml
[Interface]
Address = 10.200.200.2/24
PrivateKey = <pi_privatekey>
DNS = 1.1.1.1                 # you can also use your own DNS server

[Peer]
PublicKey = <vps_publickey>
Endpoint = <vps_public_ip>:37466     # do not forget to put your VPS IP here
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25      # keep connections alive across NAT
```
CONFIGURACION DE ADDON WIREGUARD EN MODO (PSEUDO)CLIENTE

Instalamos el addon de Wireguard en Hassio.

Tras la instalación, en el host del Hassio aparecerá un nuevo directorio para el addon que estará inicialmente vacío:

/mnt/data/supervisor/addons/data/a0d7b954_wireguard

También podemos comprobar que en el directorio de claves ssl para los addons, no hay ningún dato todavía del wireguard:

/mnt/data/supervisor/ssl

Si arrancamos el addon con los datos de configuración por defecto, vemos que aparece un fichero "options.json" que contiene la configuración por defecto.

/mnt/data/supervisor/addons/data/a0d7b954_wireguard/options.json

También podemos ver que tras arrancar el addon, aparece un directorio para wireguard en el directorio de claves ssl:

/mnt/data/supervisor/ssl/wireguard

En este directorio de claves tendremos un fichero "private_key" que contendrá la clave privada del addon, así como una carpeta llamada "hassio". Esta carpeta corresponde a la configuración del cliente de Wireguard que se crea en la configuración por defecto. Si modificamos esa configuración y declaramos varios clientes de Wireguard, nos aparecerán varias carpetas cada una con el nombre que le hayamos puesto.

client.conf
Fichero con la configuración del cliente de la configuración por defecto. Este fichero, si quisiésemos usar el addon como servidor (que es lo que se hace habitualmente) nos lo deberíamos llevar al PC que quisiésemos usar para conectarnos remotamente a nuestro Hassio. Contiene tanto la clave privada del cliente como la clave pública de nuestro Hassio, así como otros parámetros de la configuración por defecto. OJO: La carpeta hassio es una carpeta para el cliente de Wireguard, no para nuestra instancia de Hassio.

private_key
Fichero con la clave privada del cliente Wireguard. Es la misma que aparece en el fichero client.conf, así que no aporta nada nuevo.

qrcode.png
Este fichero contiene una imagen de un código QR que codifica el contenido del fichero client.conf. Si nos llevamos este fichero a un PC y lo visualizamos, podremos cargar la configuración desde la aplicación para móviles de Wireguard de forma fácil y sencilla.


Bueno, pues hasta aquí la descripción sobre dónde se almacena la configuración del addon de Wireguard en Hassio. En cada arranque del addon, un script se encarga de procesar estos ficheros e incorporarlos a la configuración interna de Wireguard dentro del contenedor.

Podríamos entrar en el contenedor y modificar la configuración de Wireguard a nuestro gusto, pero esa configuración se perdería tras un reinicio.

Podríamos modificar a mano los ficheros de configuración en el host de Hassio, pero si usásemos alguna opción de configuración no contemplada por el script que traduce e incorpora el json al contenedor, tampoco serviría de nada.

Pero, por fortuna, hay algunas opciones que sí se permiten en el fichero json y que por lo tanto son reconocidas por el addon, que nos permiten hacer que el nuestra instancia de Hassio sea la que intente establecer las conexiones hacia los clientes.

A partir de este punto vamos a explicar la configuración necesaria para que nuestro addon de Wireguard se comporte como un cliente e inicie la conexión hacia otro servidor Wireguard que tengamos accesible públicamente, por ejemplo en un VPS.

Vamos a cargar la siguiente configuración:

*****************************************************************
server:
  host: 10.10.10.10
  addresses:
    - 10.22.10.2
  private_key: <ponga aqui la clave privada del peer que corresponde al Hass, sin comillas ni ná>
  dns: []
peers:
  - name: hassvpn (aquí podemos poner el nombre que queramos)
    public_key: <ponga aqui la clave pública del Wireguard del VPS, sin comillas ni ná>
    endpoint: 'x.x.x.x:yyyy' #Esta es la IP del VPS y el puerto por donde está escuchando el Wireguard
    addresses:
      - 10.22.10.1
    allowed_ips:
      - 10.22.10.0/24
    client_allowed_ips: []
log_level: info
*****************************************************************

Pero antes de cargarla en el addon, aclaremos algunas cosas:

Se supone que ya tenemos un Wireguard configurado en nuestro VPS, y queremos que nuestro Hassio se conecte a él. Por lo tanto, ya hemos generado en nuestro VPS las claves públicas y privadas de todos los miembros de la VPN. Lo que vamos a hacer es que el addon de Wireguard en nuestro Hassio adopte esas claves en lugar de utilizar las que ha generado él al iniciarse.

Por lo tanto, lo que estamos haciendo es algo así como montar una VPN donde hay dos servidores: por un lado el que hemos montado en nuestro VPS, y por otro lado el addon de nuestro Hassio, que está pensado para actuar también como servidor.

Es necesario aclarar que en la filosofía de diseño que se ha seguido en Wireguard no existen realmente ni servidores ni clientes, sino que todos se comportan como peers al mismo nivel. Lo que diferencia a un servidor de un cliente es que el servidor no intenta iniciar la comunicación con ningún cliente, sino que se mantiene a la escucha. La razón lógica es que los clientes pueden tener cualquier IP porque su ubicación es la que puede cambiar, mientras que el servidor es la máquina que tiene una dirección invariable y conocida por todos los demás, y por lo tanto es a quien intentarán conectarse.

La otra pequeña diferencia que hay entre un servidor y un cliente en Wireguard, es que en el servidor se configura un NAT por defecto para que los clientes de la VPN puedan salir al exterior (este es el cometido general de una VPN). Pero a nivel de establecimiento de los túneles, todos los miembros de la VPN se comportan igual: cada uno tiene su clave privada y conoce la clave pública de su interlocutor.


Ahora una breve explicación de los campos:

- server.host: Es la dirección INTERNA de nuestro Hassio, es decir, la IP que usamos para acceder a él cuando estamos en nuestra red doméstica.

- server.addresses: Será la dirección IP que asignemos para el interfaz del túnel de la VPN. En este ejemplo, yo tengo un servidor Wireguard funcionando con la 10.22.10.1, así que le asigno la 10.22.10.2 a mi Hassio, la 10.22.10.3 a mi móvil, y así con cada uno de los clientes vaya a tener la VPN.

- server.private_key: Esta es una de las claves de cliente (peer) que se han generado en el Wireguard de nuestro VPS. OJO!!! No es la clave privada del servidor Wireguard del VPS, sino que es la clave privada de uno de los peer que se ha generado. De todos los peer que hayamos generado en el VPS, debemos elegir uno para que sea utilizado por nuestro Hassio.

- server.dns: Aquí podemos indicarle el DNS que queremos que se utilice en la VPN. Si no indicamos nada, el addon usará el servicio de DNS por defecto del Hassio.

- peers.name: Es el nombre del cliente con el que se conectará nuestro Hassio. Es decir, es el nombre que tendrá nuestro VPS a ojos del Hassio. En el ejemplo le hemos llamado hassvpn.

- peers.name.public_key: Es la clave pública del cliente con el que se conectará nuestro Hassio. Es decir, es la clave pública de nuestro servidor Wireguard del VPS.

- peers.name.endpoint: Es la IP:puerto (pública, se entiende), o bien la URL:puerto, del cliente con el que se conectará nuestro Hassio. Es decir, es la IP/URL de nuestro VPS con el puerto donde esté escuchando el Wireguard de nuestro VPS.

- peers.name.addresses: Es la dirección IP del interfaz del túnel en el Wireguard de nuestro VPS. Como ya hemos dicho antes, lo habíamos configurado para que usase la 10.22.10.1, así que aquí pondremos esa misma.

- peers.name.allowed_ips: Es una enumeración de direcciones IP's a las que queremos llegar por el túnel, o de las que permitiremos que nos lleguen paquetes por él. Esta línea se comporta como una especia de enrutamiento y filtro de entrada. A la hora de transmitir paquetes, nuestro Hass solo enviará por el túnel los que vayan dirigidos a las subredes que anotemos aquí. A la hora de recibir paquetes, nuestro Hass solo hará caso a los tengan procedencia de alguna de las subredes que anotemos aquí. En nuestro ejemplo, nosotros solamente admitiremos paquetes que provengan de algún miembro de la VPN, por lo que tan solo anotaremos la subred que hemos elone que ya tenemos un Wireguard configurado en nuestro VPS, y queremos que nuestro Hassio se conecte a él. Por lo tanto, ya hemos generado en nuestro VPS las claves públicas y privadas de todos los miembros de la VPN. Lo que vamos a hacer es que el addon de Wireguard en nuestro Hassio adopte esas claves en lugar de utilizar las que ha generado él al iniciarse.

Por lo tanto, lo que estamos haciendo es algo así como montar una VPN donde hay dos servidores: por un lado el que hemos montado en nuestro VPS, y por otro lado el addon de nuestro Hassio, que está pensado para actuar también como servidor.

Es necesario aclarar que en la filosofía de diseño que se ha seguido en Wireguard no existen realmente ni servidores ni clientes, sino que todos se comportan como peers al mismo nivel. Lo que diferencia a un servidor de un cliente es que el servidor no intenta iniciar la comunicación con ningún cliente, sino que se mantiene a la escucha. La razón lógica es que los clientes pueden tener cualquier IP porque su ubicación es la que puede cambiar, mientras que el servidor es la máquina que tiene una dirección invariable y conocida por todos los demás, y por lo tanto es a quien intentarán conectarse.

La otra pequeña diferencia que hay entre un servidor y un cliente en Wireguard, es que en el servidor se configura un NAT por defecto para que los clientes de la VPN puedan salir al exterior (este es el cometido general de una VPN). Pero a nivel de establecimiento de los túneles, todos los miembros de la VPN se comportan igual: cada uno tiene su clave privada y conoce la clave pública de su interlocutor.


Ahora una breve explicación de los campos:

- server.host: Es la dirección INTERNA de nuestro Hassio, es decir, la IP que usamos para acceder a él cuando estamos en nuestra red doméstica.

- server.addresses: Será la dirección IP que asignemos para el interfaz del túnel de la VPN. En este ejemplo, yo tengo un servidor Wireguard funcionando con la 10.22.10.1, así que le asigno la 10.22.10.2 a mi Hassio, la 10.22.10.3 a mi móvil, y así con cada uno de los clientes vaya a tener la VPN.

- server.private_key: Esta es una de las claves de cliente (peer) que se han generado en el Wireguard de nuestro VPS. OJO!!! No es la clave privada del servidor Wireguard del VPS, sino que es la clave privada de uno de los peer que se ha generado. De todos los peer que hayamos generado en el VPS, debemos elegir uno para que sea utilizado por nuestro Hassio.

- server.dns: Aquí podemos indicarle el DNS que queremos que se utilice en la VPN. Si no indicamos nada, el addon usará el servicio de DNS por defecto del Hassio.

- peers.name: Es el nombre del cliente con el que se conectará nuestro Hassio. Es decir, es el nombre que tendrá nuestro VPS a ojos del Hassio. En el ejemplo le hemos llamado hassvpn.

- peers.name.public_key: Es la clave pública del cliente con el que se conectará nuestro Hassio. Es decir, es la clave pública de nuestro servidor Wireguard del VPS.

- peers.name.endpoint: Es la IP:puerto (pública, se entiende), o bien la URL:puerto, del cliente con el que se conectará nuestro Hassio. Es decir, es la IP/URL de nuestro VPS con el puerto donde esté escuchando el Wireguard de nuestro VPS.

- peers.name.addresses: Es la dirección IP del interfaz del túnel en el Wireguard de nuestro VPS. Como ya hemos dicho antes, lo habíamos configurado para que usase la 10.22.10.1, así que aquí pondremos esa misma.

- peers.name.allowed_ips: Es una enumeración de direcciones IP's a las que queremos llegar por el túnel, o de las que permitiremos que nos lleguen paquetes por él. Esta línea se comporta como una especia de enrutamiento y filtro de entrada. A la hora de transmitir paquetes, nuestro Hass solo enviará por el túnel los que vayan dirigidos a las subredes que anotemos aquí. A la hora de recibir paquetes, nuestro Hass solo hará caso a los tengan procedencia de alguna de las subredes que anotemos aquí. En nuestro ejemplo, nosotros solamente admitiremos paquetes que provengan de algún miembro de la VPN, por lo que tan solo anotaremos la subred que hemos elegido para asignar IP's a los interfaces de los túneles, la 10.22.10.0/24.

- peers.name.client_allowed_ips: Este campo es similar al anterior, pero aplicaría a la hora de generar los ficheros de configuración de los clientes del addon. Es decir, lo que pongamos en este campo sería lo que aparecería en el "allowed_ips" del fichero de configuración del cliente. NO AFECTA AL FUNCIONAMIENTO DEL ADDON YA QUE SOLO SE USA PARA GENERAR FICHEROS DE CONFIGURACION PARA OTRAS MAQUINAS. Como nosotros no vamos a usar estos ficheros porque ya tenemos nuestro Wireguard configurado en el VPS, no vamos a poner nada aquí.

- log_level: Aquí podemos indicar varios niveles de logging, con más o menos detalle. El valor habitual es "info". Si ponemos "trace" tendremos más información de depuración. Los valores posibles están indicados en la documentación del addon que podemos consultar directamente desde el Supervisor de nuestro Hassio.


Explicado todo esto, y si personalizamos la configuración que hemos puesto anteriormente, podemos cargarla directamente en nuestro addon a través del interfaz del Supervisor. Al guardar la nueva configuración, nos preguntará si queremos reiniciar el addon, a lo que deberemos responder que sí. Si todo ha ido bien, nuestro Hassio ya debería estar conectándose a nuestro VPS.

Si después de reiniciar el addon comprobamos el contenido de los directorios que hemos comentado antes, podremos comprobar varias cosas:

- El fichero options.json del directorio /mnt/data/supervisor/addons/data/a0d7b954_wireguard contendrá nuestra configuración personalizada.
- El fichero private_key del directorio /mnt/data/supervisor/ssl/wireguard todavía contiene la clave privada que generó el addon la primera vez que lo iniciamos. No nos debe preocupar, porque prevalece lo que hayamos indicado en el fichero de configuración.
- En el directorio /mnt/data/supervisor/ssl/wireguard se habrá creado una carpeta con el mismo nombre que le hemos dado a nuestro cliente (en nuestro ejemplo, hassvpn). En esta carpeta habrá dos ficheros, uno llamado client.conf y otro qrcode.png. Estos ficheros serían los que tendríamos que llevarnos al cliente (ojo, al cliente del Hassio, es decir, el VPS) si las claves y la configuración la hubiésemos hecho desde el Hassio. Como en nuestro caso todas las claves se generaron en el VPS, no tenemos que hacer nada con estos ficheros. También debemos fijarnos en la ausencia de private_key en el directorio hassvpn. Esto se debe a que como hemos indicado una clave pública en la configuración, el addon no genera ninguna clave privada para el cliente porque interpreta que para ese cliente ya tenemos las claves generadas (además de que es imposible calcular la clave privada a partir de la clave pública).

El último paso, y yo creo que recomendable, es ocultar un poco la clave privada de la configuración del addon en el Hassio. Para ello, podemos eliminar directamente la línea correspondiente de la configuración del addon siempre que editemos el fichero private_key del directorio /mnt/data/supervisor/ssl/wireguard y la pongamos ahí, sustituyendo a la que había generado el addon de forma automática.

-->
