Mi ISP me proporciona solo una dirección IPv4.
Después de configurar una conexión con el servidor OpenVPN de mi universidad, obtengo una dirección IPv6. Con una dirección IPv6 de ejemplo www6.fit.vutbr.cz
Puedo:
Pero no puedo:
es decir, el navegador web no resuelve una dirección dns ipv6.
Si agrego la siguiente asignación a /etc/hosts
2001:67c:1220:809::93e5:916 www6.fit.vutbr.cz
el navegador web finalmente funciona.
Creo que tiene algo que ver con scutil --dns mostrando:
DNS configuration
resolver #1
search domain[0] : lan
nameserver[0] : 192.168.1.1
nameserver[1] : 8.8.8.8
nameserver[2] : 8.8.4.4
flags : Request A records
reach : 0x00020002 (Reachable,Directly Reachable Address)
Creo que debería ver Solicitar registros AAAA. ¿Por qué host, traceroute6 y ping6 resuelven el DNS, pero los navegadores web no? ¿Alguna sugerencia? Gracias
Fue una gran molestia resolverlo, así que escribí una pequeña guía con la esperanza de que otros la encontraran útil:
El solucionador de nombres de dominio de macOS solo devolverá direcciones IPv6 (de registros AAAA) cuando crea que tiene una dirección IPv6 enrutable válida. Para las interfaces físicas como Ethernet o Wi-Fi, es suficiente establecer o que se le asigne una dirección IPv6, pero para los túneles (como los que usan utun
interfaces) hay algunos pasos extra molestos que deben tomarse para convencer al sistema de que sí, en efecto. tiene una dirección IPv6 y sí, le gustaría recuperar las direcciones IPv6 para las búsquedas de DNS.
Lo uso wg-quick
para establecer un túnel WireGuard entre mi computadora portátil y un servidor virtual Linode. WireGuard utiliza un utun
dispositivo de túnel de espacio de usuario para realizar la conexión. Así es como se configura ese dispositivo:
utun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1420
inet 10.75.131.2 --> 10.75.131.2 netmask 0xffffff00
inet6 fe80::a65e:60ff:fee1:b1bf%utun1 prefixlen 64 scopeid 0xc
inet6 2600:3c03::de:d002 prefixlen 116
nd6 options=201<PERFORMNUD,DAD>
Y aquí hay algunas líneas relevantes de mi tabla de enrutamiento:
Internet:
Destination Gateway Flags Refs Use Netif Expire
0/1 utun1 USc 0 0 utun1
default 10.20.4.4 UGSc 0 0 en3
10.20.4/24 link#14 UCS 3 0 en3 !
10.75.131.2 10.75.131.2 UH 0 0 utun1
50.116.51.30 10.20.4.4 UGHS 7 2629464 en3
128.0/1 utun1 USc 5 0 utun1
Internet6:
Destination Gateway Flags Netif Expire
::/1 utun1 USc utun1
2600:3c03::de:d000/116 fe80::a65e:60ff:fee1:b1bf%utun1 Uc utun1
8000::/1 utun1 USc utun1
10.20.4/24
es mi red ethernet local.10.20.4.5
es la dirección IP LAN de mi computadora portátil.10.20.4.4
es la dirección IP de LAN de mi puerta de enlace.10.75.131.2
es la dirección IPv4 de mi extremo del túnel punto a punto de WireGuard.2600:3c03::de:d002
es la dirección IPv6 de mi extremo del túnel punto a punto de WireGuard.50.116.51.30
es la dirección pública de mi servidor Linode.Esto debería ser suficiente para tener conectividad IPv6, ¿verdad? Bueno, la resolución de nombres funciona cuando host
habla directamente con mi servidor de nombres:
sam@shiny ~> host ipv6.whatismyv6.com
ipv6.whatismyv6.com has IPv6 address 2607:f0d0:3802:84::128
Hacer ping por dirección IPv6 funciona:
sam@shiny ~> ping6 -c1 2607:f0d0:3802:84::128
PING6(56=40+8+8 bytes) 2600:3c03::de:d002 --> 2607:f0d0:3802:84::128
16 bytes from 2607:f0d0:3802:84::128, icmp_seq=0 hlim=55 time=80.991 ms
--- 2607:f0d0:3802:84::128 ping6 statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 80.991/80.991/80.991/0.000 ms
Y las conexiones HTTP por dirección IPv6 funcionan:
sam@shiny ~> curl -s 'http://[2607:f0d0:3802:84::128]' -H 'Host: ipv6.whatismyv6.com' | html2text | head -3
This page shows your IPv6 and/or IPv4 address
You are connecting with an IPv6 Address of:
2600:3c03::de:d002
Sin embargo, las conexiones HTTP por nombre de host solo IPv6 no funcionan:
sam@shiny ~> curl 'http://ipv6.whatismyv6.com'
curl: (6) Could not resolve host: ipv6.whatismyv6.com
El resultado es el mismo en wget
aplicaciones GUI como Firefox: la conexión mediante una dirección IPv6 literal funciona bien, pero la conexión mediante un nombre de host que solo tiene un registro AAAA (y ningún registro A) asociado no funciona.
Curiosamente, ping6
puede realizar una búsqueda de DNS y recuperar una dirección IPv6:
sam@shiny ~ [6]> ping6 -c1 ipv6.whatismyv6.com
PING6(56=40+8+8 bytes) 2600:3c03::de:d002 --> 2607:f0d0:3802:84::128
16 bytes from 2607:f0d0:3802:84::128, icmp_seq=0 hlim=55 time=49.513 ms
--- ipv6.whatismyv6.com ping6 statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 49.513/49.513/49.513/0.000 ms
¿ Por qué puede ping6
hacer esto cuando nada más puede? Resulta que cuando lo ping6
llama getaddrinfo
sobrescribe las banderas predeterminadas. Uno de los indicadores predeterminados es AI_ADDRCONFIG
, que le dice al resolutor que solo devuelva direcciones en familias de direcciones para las que el sistema tiene una dirección IP. (Es decir, no devuelva direcciones IPv6 a menos que el sistema tenga una dirección IPv6 (no de enlace local).) La mayoría de los otros programas agregan a las banderas predeterminadas en lugar de aplastarlas, lo que supongo que es sensato.
Si lo ejecuta, scutil --dns
le dirá cómo está configurado el resolver. Aquí está la salida en mi sistema (menos un montón de cosas de mdns que no importan):
DNS configuration
resolver #1
search domain[0] : home.munkynet.org
nameserver[0] : 10.20.4.4
if_index : 14 (en3)
flags : Request A records
reach : 0x00020002 (Reachable,Directly Reachable Address)
DNS configuration (for scoped queries)
resolver #1
search domain[0] : home.munkynet.org
nameserver[0] : 10.20.4.4
if_index : 14 (en3)
flags : Scoped, Request A records
reach : 0x00020002 (Reachable,Directly Reachable Address)
Tenga en cuenta que en flags
, dice Request A records
pero no Request AAAA records
. Por lo tanto, nos corresponde a nosotros tratar de convencer al resolutor de macOS de que, de hecho, tenemos una dirección IPv6 válida, aunque esté en una interfaz de túnel.
La forma "correcta" de que esto suceda es que cualquier programa configure el túnel para usar la SystemConfiguration
API extraña y en gran parte indocumentada para registrar el "servicio" de la red y sus propiedades IPv6. La aplicación Viscosity hace esto. Tunnelblick no lo hace, el OpenVPN Client oficial no lo hace, y wg-quick
seguro que tampoco.
scutil
chapuceroPodemos crear las mismas estructuras de "servicio" de SystemConfiguration manualmente usando el scutil
comando:
Primero creamos la parte IPv4 del servicio:
sam@shiny ~> sudo scutil
> d.init
> d.add Addresses * 10.75.131.2
> d.add DestAddresses * 10.75.131.2
> d.add InterfaceName utun1
> set State:/Network/Service/my_ipv6_tunnel_service/IPv4
> set Setup:/Network/Service/my_ipv6_tunnel_service/IPv4
Y luego creamos la parte IPv6:
> d.init
> d.add Addresses * fe80::a65e:60ff:fee1:b1bf 2600:3c03::de:d002
> d.add DestAddresses * ::ffff:ffff:ffff:ffff:0:0 ::
> d.add Flags * 0 0
> d.add InterfaceName utun1
> d.add PrefixLength * 64 116
> set State:/Network/Service/my_ipv6_tunnel_service/IPv6
> set Setup:/Network/Service/my_ipv6_tunnel_service/IPv6
> quit
Una vez hecho esto, la salida de scutil --dns
(de nuevo módulo mdns cosas) cambia:
DNS configuration
resolver #1
search domain[0] : home.munkynet.org
nameserver[0] : 10.20.4.4
if_index : 14 (en3)
flags : Request A records, Request AAAA records
reach : 0x00020002 (Reachable,Directly Reachable Address)
DNS configuration (for scoped queries)
resolver #1
search domain[0] : home.munkynet.org
nameserver[0] : 10.20.4.4
if_index : 14 (en3)
flags : Scoped, Request A records
reach : 0x00020002 (Reachable,Directly Reachable Address)
Ahora lo vemos Request AAAA records
en las banderas! No estoy realmente seguro de qué son las "consultas de alcance" o por qué la configuración de DNS para ellas no cambió, pero parece que las cosas funcionan ahora, así que sea lo que sea:
sam@shiny ~> curl -s 'http://ipv6.whatismyv6.com' | html2text | head -3
This page shows your IPv6 and/or IPv4 address
You are connecting with an IPv6 Address of:
2600:3c03::de:d002
Al desconectarse del túnel, todo lo que tiene que hacer es eliminar las claves de configuración del sistema que agregó:
sam@shiny ~> sudo scutil
> remove State:/Network/Service/my_ipv6_tunnel_service/IPv4
> remove Setup:/Network/Service/my_ipv6_tunnel_service/IPv4
> remove State:/Network/Service/my_ipv6_tunnel_service/IPv6
> remove Setup:/Network/Service/my_ipv6_tunnel_service/IPv6
> quit
Un par de cosas a tener en cuenta:
my_ipv6_tunnel_service
es totalmente arbitrario..ovpn
perfil de Mullvad, debe crear las teclas Setup:
y . State:
No verifiqué esto porque soy perezoso.DestAddresses
viene el IPv6. Los copié de Viscosity porque parecían funcionar allí. ::ffff:ffff:ffff:ffff:0:0
para la dirección local de enlace y ::
para el públicoDestAddresses
significa o para qué se usa.Escribí un script de python que obtiene direcciones y longitudes de prefijos de ifconfig
la salida. Requiere Python 3.6 o posterior, así que asegúrese de tenerlo en su camino. Se llama wg-updown
y llama a su servicio SystemConfiguration wg-updown-utun#
, pero en realidad no es específico de WireGuard. Puede llamarlo como un script de subida/bajada previa para cualquier túnel VPN antiguo o ejecutarlo manualmente. Llámalo así:
# After tunnel comes up
wg-updown up IFACE
# Before tunnel goes down
wg-updown down IFACE
reemplácelo IFACE
con el nombre de la interfaz que está utilizando su túnel/cliente VPN, por ejemplo utun1
, . Imprimirá los comandos que está enviando scutil
para que pueda ver lo que está haciendo en detalle.
#!/usr/bin/env python3
import re
import subprocess
import sys
def service_name_for_interface(interface):
return 'wg-updown-' + interface
v4pat = re.compile(r'^\s*inet\s+(\S+)\s+-->\s+(\S+)\s+netmask\s+\S+')
v6pat = re.compile(r'^\s*inet6\s+(\S+?)(?:%\S+)?\s+prefixlen\s+(\S+)')
def get_tunnel_info(interface):
ipv4s = dict(Addresses=[], DestAddresses=[])
ipv6s = dict(Addresses=[], DestAddresses=[], Flags=[], PrefixLength=[])
ifconfig = subprocess.run(["ifconfig", interface], capture_output=True,
check=True, text=True)
for line in ifconfig.stdout.splitlines():
v6match = v6pat.match(line)
if v6match:
ipv6s['Addresses'].append(v6match[1])
# This is cribbed from Viscosity and probably wrong.
if v6match[1].startswith('fe80'):
ipv6s['DestAddresses'].append('::ffff:ffff:ffff:ffff:0:0')
else:
ipv6s['DestAddresses'].append('::')
ipv6s['Flags'].append('0')
ipv6s['PrefixLength'].append(v6match[2])
continue
v4match = v4pat.match(line)
if v4match:
ipv4s['Addresses'].append(v4match[1])
ipv4s['DestAddresses'].append(v4match[2])
continue
return (ipv4s, ipv6s)
def run_scutil(commands):
print(commands)
subprocess.run(['scutil'], input=commands, check=True, text=True)
def up(interface):
service_name = service_name_for_interface(interface)
(ipv4s, ipv6s) = get_tunnel_info(interface)
run_scutil('\n'.join([
f"d.init",
f"d.add Addresses * {' '.join(ipv4s['Addresses'])}",
f"d.add DestAddresses * {' '.join(ipv4s['DestAddresses'])}",
f"d.add InterfaceName {interface}",
f"set State:/Network/Service/{service_name}/IPv4",
f"set Setup:/Network/Service/{service_name}/IPv4",
f"d.init",
f"d.add Addresses * {' '.join(ipv6s['Addresses'])}",
f"d.add DestAddresses * {' '.join(ipv6s['DestAddresses'])}",
f"d.add Flags * {' '.join(ipv6s['Flags'])}",
f"d.add InterfaceName {interface}",
f"d.add PrefixLength * {' '.join(ipv6s['PrefixLength'])}",
f"set State:/Network/Service/{service_name}/IPv6",
f"set Setup:/Network/Service/{service_name}/IPv6",
]))
def down(interface):
service_name = service_name_for_interface(interface)
run_scutil('\n'.join([
f"remove State:/Network/Service/{service_name}/IPv4",
f"remove Setup:/Network/Service/{service_name}/IPv4",
f"remove State:/Network/Service/{service_name}/IPv6",
f"remove Setup:/Network/Service/{service_name}/IPv6",
]))
def main():
operation = sys.argv[1]
interface = sys.argv[2]
if operation == 'up':
up(interface)
elif operation == 'down':
down(interface)
else:
raise NotImplementedError()
if __name__ == "__main__":
main()
Al menos una interfaz de red debe incluir un servidor DNS con dirección IPv6.
Eso establece el indicador AAAA y luego Mac OS resolverá las direcciones IPv6.
El problema parece surgir porque IPv6 está deshabilitado en la interfaz Ethernet (al menos así fue conmigo).
Estoy accediendo a Internet IPv6 a través de tunnelbroker.net. Acabo de agregar mis direcciones local y de puerta de enlace de Tunnelbroker en la página Preferencias del sistema - Red en la página de red.
Una solución más limpia sería ajustar las banderas para Solicitar registros AAAA, pero no tengo idea de cómo hacerlo.
OndrejG