Admin Libre - Administración de sistemas y redes

Conectividad IPv6 con una subred /56 y un túnel WireGuard
Por Francisco Gaitán el 22 de Septiembre de 2023

A partir de una conexión IPv4, un router y un servidor OpenBSD al que va enrutada una subred IPv6 /56 voy a conseguir conectividad IPv6 en la red de casa sin necesidad de NAT66.

Estos artículos me han sido muy útiles para hacerlo funcionar:

Tengo enrutada la red 2001:db8:83ac:100::/56 y estos hosts:

  • cerbero es el router firewall con OpenBSD
  • fugu es el servidor al que está enrutada la subred IPv6 /56
  • talos es un ordenador que va conectado a cerbero por eth1

Con esta calculadora dividiré esta red en las 256 /64 de las cuales cogeré la última para el túnel, asignando estas IPs:

  • 2001:db8:83ac:1ff::1/64 es la IP del lado de fugu del túnel WireGuard.
  • 2001:db8:83ac:1ff::2/64 es la IP del lado de cerbero del túnel WireGuard.

La subred /56 se puede dividir en 16 /60 (cada una con 16 /64), de la cual cogeré la primera:

  • 2001:db8:83ac:100::/60 es la subred lan_ipv6 que voy a anunciar en eth1 donde va conectado talos o un switch al que van conectados varios hosts.

La IP asignada a la interfaz eth1 de cerbero es 2001:db8:83ac:100::1/64.

Pasos necesarios

  1. Crear un túnel WireGuard con el que doy conectividad IPv6 al router
  2. Dar los permisos adecuados en el cortafuegos de cada host
  3. Anunciar una subred /64 desde el router para la red casera

Configuración del túnel WireGuard

La parte de crear el túnel está explicada en el artículo VPN Road Warrior con WireGuard en OpenBSD. Se puede hacer más seguro añadiendo una clave precompartida wgpsk, aunque aquí no lo incluiré por simplicar.

cerbero

Configuro el túnel y hago del otro extremo (fugu) la ruta por defecto:

wgkey `cat /etc/wireguard/$(hostname).key`
wgpeer <fugu-wg-pubkey> wgendpoint <fugu-public-ip4> 51820 wgaip ::/0 wgpka 25 
inet6 2001:db8:83ac:1ff::2 
up
!route add -inet6 default 2001:db8:83ac:1ff::1
description "IPv6 tunnel"

fugu

Especifico los rangos de IPs permitidos para el tráfico del túnel con wgaip. Añado una ruta a la lan_ipv6 con la IP del lado de fugu en el túnel WireGuard:

wgkey `cat /etc/wireguard/$(hostname).key` wgport 51820
wgpeer <cerbero-wg-pubkey> wgaip 2001:db8:83ac:1ff::2/64 wgaip 2001:db8:83ac:100::1/64
inet6 2001:db8:83ac:1ff::1/64
!route add -net 2001:db8:83ac:100::/60 2001:db8:83ac:1ff::1
up
description "IPv6 tunnel"

Reenvío de IPv6 para el enrutado

Activo el reenvío de paquetes IPv6 en fugu y en cerbero:

fugu# echo "net.inet6.ip6.forwarding=1" >> /etc/sysctl.conf
cerbero# echo "net.inet6.ip6.forwarding=1" >> /etc/sysctl.conf
fugu# sysctl net.inet6.ip6.forwarding=1 
net.inet6.ip6.forwarding: 1 -> 1
cerbero# sysctl net.inet6.ip6.forwarding=1 
net.inet6.ip6.forwarding: 1 -> 1

Configuración de Packet Filter

Parto de una configuración con denegación por defecto. En lugar de dar las configuraciones completas indicaré solamente las líneas necesarias para esta configuración.

Recomiendo revisar todo y probar que no haya conexiones indebidas usando tcpdump(8) y pflog(4). Una vez aplicada la configuración compruebo que es fugu quien bloquea toda conexión externa hacia cerbero y hacia la red local IPv6, de forma que estos no vean los paquetes salvo que yo lo permita expresamente. También compruebo que permitiendo acceso a la red interna de un determinado host en fugu es cerbero quien bloquea la conexión, cuyo firewall es otra barrera que protege a la red interna.

fugu

Permito el tráfico IPv6 TCP, UDP y los ICMPv6 correspondientes. Bloqueo las conexiones hacia cerbero (tanto a la IP de su interfaz eth1 como a su IP del túnel), hacia la IP del túnel de fugu y hacia la subred lan_ipv6. En vez de variables usaré tablas por consistencia con mi configuración:

table <cerbero> { 2001:db8:83ac:100::1, 2001:db8:83ac:1ff::2 }
table <fugu_wg0> { 2001:db8:83ac:1ff::1 }
table <lan_ipv6> { 2001:db8:83ac:100::/60 }
pass out inet6
# RFC 4890 Section 4.3
pass inet6 proto icmp6 all icmp6-type { 1 2 3 4 128 129 133 134 135 136 137 }
block in quick log inet6 from any to { <cerbero>, <fugu_wg0>, <lan_ipv6> }

Muy importante: Si no usas la opción quick en la línea block, la última regla es la que aplica, por lo que si después pones una línea para aceptar conexiones tales como abrir un determinado puerto esta prevalecerá sobre la línea block y cerbero quedará expuesto.

Nótese que he usado la opción log, lo que permitirá comprobar las reglas del cortafuegos usando tcpdump sobre la interfaz pflog0:

$ tcpdump -e -i pflog0

cerbero

Permito las conexiones salientes IPv6, algunos paquetes ICMP6 (ver RFC 4890) y acepto el tráfico de eth1 donde va conectado talos o un switch al que van conectados los dispositivos de la red lan_ipv6, a la cual no se podrá exceder desde el exterior ya que fugu lo bloqueará como configuré anteriormente.

Como medida extra de seguridad también bloqueo cualquier conexión a la red lan_ipv6 desde cualquier host (incluído fugu) a la red IPv6 anunciada, excepto entre los hosts de la propia red:

table <lan_ipv6> { 2001:db8:83ac:100::/60 }
pass out inet6
# RFC 4890 Section 4.3
pass inet6 proto icmp6 all icmp6-type { 1 2 3 4 128 129 133 134 135 136 137 }
pass in on $eth1 inet6
block in log from any to <lan_ipv6>
pass in from <lan_ipv6> to <lan_ipv6>

Me aseguro que después de este block no hay ninguna regla que contradiga a ésta ya que es la última la que aplica.

talos

Permito el tráfico saliente IPv6 y los ICMPv6 correspondientes.

pass out inet6
# RFC 4890 Section 4.3
pass inet6 proto icmp6 all icmp6-type { 1 2 3 4 128 129 133 134 135 136 }

Anunciando la subred con rad

Configuraré rad(8) en cerbero, que anunciará la subred en la interfaz eth1 (donde va conectado talos) especificando también la IP del servidor DNS:

cerbero# cat /etc/rad.conf
interface eth1 {
  prefix 2001:db8:83ac:100::/60
}

dns {
  nameserver {
    2001:db8:83ac:100::1
  }
}
cerbero# rcctl enable rad
cerbero# rcctl start rad

Para obtener mensajes de depuración se puede ejecutar rad sin demonizar:

cerbero# rad -dvvv

Interfaces de red

Estos son los archivos hostname.if(5), cuyo nombre dependerá de su interfaz de red. No incluyo a fugu ya que la configuración de IPv6 se realiza en la interfaz WireGuard como indiqué antes.

eth1 de cerbero

inet6 2001:db8:83ac:100::1
up

talos

inet6 autoconf

Como dar preferencia a inet6 frente a inet4

Usaré el parámetro family del archivo resolv.conf(5) de forma el sistema operativo usará IPv6 de forma preferente:

talos$ echo "family inet6 inet4" >> /etc/resolv.conf

Destacado

Contacto

Si has encontrado algún error o quieres comentarme algo mándame un correo a webmaster@adminlibre.org