VPN de malla con WireGuard en OpenBSD
Por el 16 de Agosto de 2023
Con una VPN de malla todos los nodos pueden conectarse directamente entre ellos.
Crearé la red privada 10.0.0.0/8 con la siguiente topología:
- Nodo foo 10.0.0.1 detrás de un NAT con IP dinámica.
- Nodo bar 10.0.0.2 con IP pública 203.0.113.24
- Nodo wu 10.0.0.3 con IP pública 198.51.100.76
Configuración del nodo foo
Este es mi ordenador local desde el cual empezaré la configuración. Lo primero que necesito es, en caso de no tenerla, generar una clave privada WireGuard y obtener la parte pública.
foo# install -m 0700 -o root -g wheel -d /etc/wireguard
foo# openssl rand -base64 32 > /etc/wireguard/$(hostname).key
foo# chmod og-r /etc/wireguard/$(hostname).key
Nótese que no paso ningún parámetro a wgpeer ya que aún no tengo creada la clave en los demás nodos. El objetivo es arrancar la interfaz wg0 para obtener la clave pública de forma que pueda configurar el resto de nodos para más tarde completar esta configuración con este dato.
Uso la opción wgpka 25 ya que estoy detrás de un NAT. Para mayor seguridad recomiendo usar también una clave compartida wgpsk.
wgkey `cat /etc/wireguard/$(hostname).key`
wgpeer wgendpoint 203.0.113.24 51820 wgaip 10.0.0.2/32 wgpka 25
wgpeer wgendpoint 198.51.100.76 51820 wgaip 10.0.0.3/32 wgpka 25
inet 10.0.0.1/8
up
Ejecuto el comando sh /etc/netstart wg0
y, aunque dará un error al no tener la clave pública del otro punto, ya puedo obtener la clave pública:
foo# sh /etc/netstart wg0
foo# ifconfig wg0 | grep wgpubkey
wgpubkey <clave-publica-foo>
Configuración del nodo bar
Al igual que antes, creo el directorio y genero la clave:
bar# install -m 0700 -o root -g wheel -d /etc/wireguard
bar# openssl rand -base64 32 > /etc/wireguard/$(hostname).key
bar# chmod og-r /etc/wireguard/$(hostname).key
Con la clave pública de foo obtenida anteriormente creo la configuración WireGuard en bar:
wgkey `cat /etc/wireguard/$(hostname).key` wgport 51820
wgpeer <clave-publica-foo> wgaip 10.0.0.1/32
wgpeer wgendpoint 198.51.100.75 51820 wgaip 10.0.0.3/32
inet 10.0.0.2/8
up
Arranco la interfaz del túnel y obtengo la clave pública:
bar# sh /etc/netstart wg0
bar# ifconfig wg0 | grep wgpubkey
wgpubkey <clave-publica-bar>
Configuración del nodo wu
Genero la llave WireGuard de la misma forma:
wu# install -m 0700 -o root -g wheel -d /etc/wireguard
wu# openssl rand -base64 32 > /etc/wireguard/$(hostname).key
wu# chmod og-r /etc/wireguard/$(hostname).key
Configuro la interfaz WireGuard usando las claves públicas de bar y de wu obtenidas anteriormente. Al tener las claves esta será la configuración final para este host:
wgkey `cat /etc/wireguard/$(hostname).key` wgport 51820
wgpeer <clave-publica-foo> wgaip 10.0.0.1/32
wgpeer <clave-publica-bar> wgendpoint 203.0.113.24 51820 wgaip 10.0.0.2/32
inet 10.0.0.3/8
up
Arranco la interfaz del túnel y obtengo la clave pública:
wu# sh /etc/netstart wg0
wu# ifconfig wg0 | grep wgpubkey
wgpubkey <clave-publica-wu>
Completando la configuración de los nodos foo y bar
Ahora que tengo las claves públicas de todos los nodos puedo insertarlas en los archivos /etc/hostname.wg0:
hostname.wg0 de foo
wgkey `cat /etc/wireguard/$(hostname).key`
wgpeer <clave-publica-bar> wgendpoint 203.0.113.24 51820 wgaip 10.0.0.2/32 wgpka 25
wgpeer <clave-publica-wu> wgendpoint 198.51.100.76 51820 wgaip 10.0.0.3/32 wgpka 25
inet 10.0.0.1/8
up
hostname.wg0 de bar
wgkey `cat /etc/wireguard/$(hostname).key` wgport 51820
wgpeer <clave-publica-foo> wgaip 10.0.0.1/32
wgpeer <clave-publica-bar> wgendpoint 198.51.100.75 51820 wgaip 10.0.0.3/32
inet 10.0.0.2/8
up
Reciniciando la interfaz wg0 en todos los nodos habrá conectividad entre los mismos a través de la VPN:
foo# sh /etc/netstart wg0
bar# sh /etc/netstart wg0
wu# sh /etc/netstart wg0
Zonas DNS para la red VPN
Una vez conectada la red es posible delegar el subdominio vpn.example.com a uno o varios servidores DNS internos de la red. Este sería el aspecto de las zonas, incluyendo el DNS reverso para la zona 10.0.0.0/8:
vpn.example.com.
$TTL 3600
$ORIGIN vpn.example.com.
@ IN SOA foo.vpn.example.com. hostmaster.example.com. (
2023081800 ; serial
14400 ; refresh
7200 ; retry
1209600 ; expire
3600 ) ; negative
NS foo.vpn.example.com.
NS bar.vpn.example.com.
foo IN A 10.0.0.1
bar IN A 10.0.0.2
10.in-addr.arpa.
$TTL 3600
10.in-addr.arpa. IN SOA foo.vpn.example.com. hostmaster.example.com. (
202308210 ; serial
14400 ; refresh
7200 ; retry
1209600 ; expire
3600 ) ; negative
1.0.0 IN PTR foo.vpn.example.com.
2.0.0 IN PTR bar.vpn.example.com.
example.com.
En el dominio principal hay que insertar los registros NS y los registros A de los nameservers de la nueva zona. Además, si el dominio está firmado con DNSSEC insertaré el registro DS de la zona vpn.example.com en la zona example.com:
; VPN
vpn.example.com. IN DS [...] ; DS de vpn.example.com.
vpn.example.com. IN NS foo.vpn.example.com.
vpn.example.com. IN NS bar.vpn.example.com.
foo.vpn.example.com. IN A 10.0.0.1
bar.vpn.example.com. IN A 10.0.0.2