El servidor y el cliente de Wireguard pueden hacer ping entre sí, pero los clientes de Wireguard no pueden hacer ping entre sí

Aug 18 2020

Estoy configurando una configuración de Wireguard donde tengo las siguientes entidades:

  1. Instancia de VM remota en hosts como google cloud o amazon aws. Este es un cliente remoto para mi servidor wireguard. Vamos a llamar a estogcp_client

  2. Un servidor wireguard en una máquina alojada en mi LAN. Llamemos a esto srvlan.

  • El reenvío de IPv4 está habilitado en este dispositivo mediante sysctl.
  • Hay un Ubiquiti Edgerouter 4 entre la WAN y mi LAN. He habilitado el reenvío de puertos y NAT de horquilla en este dispositivo. También configuré un DNS dinámico en este enrutador.
  1. Uno o más clientes en mi LAN, que deberían poder conectarse al cliente remoto como si fuera una máquina en mi LAN. Como estoy enfrentando el problema con mi primer cliente, llamémoslo client1.

En mi configuración, puedo hacer ping entre srvlany en gcp_clientambos sentidos, y entre client1y srvlantambién. Sin embargo. los pings de gcp_clienta client1(y viceversa) fallan.

Basándome en leer los resultados de tcpdump -i wg0 -n icmp, hice las siguientes observaciones:

  1. Hace ping desde client1para gcp_clientllegar srvlanpero no se reenvía al enrutador.
  2. Hace ping desde gcp_clientpara client1llegar a mi enrutador, que los reenvía a srvlan. Sin embargo, los paquetes no se reenvían srvlana client1.

Lo único que puedo concluir de esto es que las reglas de reenvío srvlanson de alguna manera defectuosas. Estoy usando nftablespara administrar este dispositivo.

Esta es mi configuración de protección de cables; Se han cambiado las direcciones IP y el número de puerto.

# wg0.conf for gcp_client
[Interface]
Address = 10.0.1.2/24
ListenPort = 50000
PrivateKey = gcp_client_privkey

[Peer]
PublicKey = srvlan_pubkey
AllowedIPs = 10.0.1.0/24
Endpoint = srvlan_ddns:50000

# wg0.conf for srvlan
[Interface]
Address = 10.0.1.1/24
ListenPort = 50000
PrivateKey = srvlan_privkey

[Peer]
PublicKey = gcp_client_pubkey
AllowedIPs = 10.0.1.2/32
Endpoint = gcp_client_domainname:50000
PersistentKeepalive = 25

[Peer]
PublicKey = client1_pubkey
AllowedIPs = 10.0.1.3/32
Endpoint = client1_lanhostname:50000
PersistentKeepalive = 25 # I realise this one is unnecessary, but I had added it while testing just in case the problem got fixed.

# wg0.conf for client1
[Interface]
Address = 10.0.1.3/24
ListenPort = 50000
PrivateKey = client1_privkey

[Peer]
PublicKey = srvlan_pubkey
AllowedIPs = 10.0.1.0/24
Endpoint = srvlan_lanhostname:50000

Este es mi firewall encendido srvlan.

# nft list ruleset
table inet firewall {
        chain inbound {
                type filter hook input priority filter; policy drop;
                ct state established,related accept
                ct state invalid drop
                iif "lo" accept
                ip protocol icmp accept
                ip6 nexthdr ipv6-icmp accept
                ip protocol igmp accept
                tcp dport 22 accept
                iifname "eno1" tcp dport { 80, 443 } ct state new accept
                iifname "eno1" udp dport 50000 ct state new accept
                iifname "wg0" udp dport 53 ct state new accept
                iifname "wg0" tcp dport { 80, 443 } ct state new accept
                iifname "wg0" udp dport 50000 ct state new accept
        }

        chain forward {
                type filter hook forward priority filter; policy drop;
                ct state established,related accept
                ct state invalid drop
                iifname "wg0" oifname "eno1" ct state new accept
        }

        chain outbound {
                type filter hook output priority filter; policy accept;
                ct state invalid drop
        }
}
table ip router {
        chain prerouting {
                type nat hook prerouting priority filter; policy accept;
        }

        chain postrouting {
                type nat hook postrouting priority srcnat; policy accept;
                oifname "eno1" ip saddr 10.0.1.0/24 masquerade
        }
}

Respuestas

A.B Aug 26 2020 at 00:35

Cuando srvlan reenvía tráfico de túnel WireGuard, lo recibe de wg0 y lo enruta a ... wg0 nuevamente: dos veces la misma interfaz.

Por lo tanto, debe agregar esta entrada a la cadena de avance del firewall inet de nftables :

                iifname "wg0" oifname "wg0" accept

Otros problemas, en la cadena entrante :


                ip protocol icmp accept
                ip6 nexthdr ipv6-icmp accept
                ip protocol igmp accept

Si bien el protocolo funciona para IPv4, nexthdr en el protocolo IPv6 no garantiza que el siguiente encabezado sea ICMPv6: puede haber varios encabezados de extensión entre el encabezado fijo y el encabezado del protocolo de capa superior. Si tales encabezados de extensión aparecen en algunos paquetes, entonces nexthdr ipv6-icmpya no coincidirán. Utilice la sintaxis correcta para IPv4 e IPv6:

                meta nfproto ipv4 meta l4proto icmp accept
                meta nfproto ipv6 meta l4proto ipv6-icmp accept
                meta nfproto ipv4 meta l4proto igmp accept

Dependiendo de la versión de nftables , se mostrará de nuevo en una forma más simplificada.


                iifname "wg0" udp dport 50000 ct state new accept

El puerto 50000 no aparece dentro de la interfaz WireGuard (a menos que desee tunelizar WireGuard dentro de WireGuard), sino afuera (para lo cual ya existe una regla). No debería ser necesario.


Recuerde a medida que agrega más clientes / pares de WireGuard (como lo hizo correctamente), que no puede haber superposiciones en las entradas de IPs permitidas de srvlan ya que determinan el enrutamiento criptográfico que ocurre en WireGuard para seleccionar el par adecuado, después del enrutamiento estándar. Además, si gcp_client se conecta a través de srvlan a servidores que no usan túneles WireGuard, entonces su dirección LAN también debe agregarse tanto a los IP permitidos como a la tabla de enrutamiento de gcp_client . AllowIPs se utiliza tanto para aceptar un paquete según su origen (y determinar qué par y tal vez actualizar su punto final en caso de itinerancia), como para determinar a qué par enviar un paquete según su destino.