¿Cómo puedo decirle a ssh que se conecte usando la dirección IPv6 no temporal?

¿Cómo puedo decirle a ssh que se conecte usando la dirección IPv6 no temporal?

Las interfaces IPv6 (al menos con IP enrutables) generalmente tienen una dirección IP temporal, que cambia con frecuencia y normalmente se usa para conexiones salientes para brindar más privacidad.

¿Cómo puedo decirle a ssh que no use esta dirección, sino que se vincule a la no temporal para un intento de conexión saliente determinado?

Sé que puedo usar la -bopción para vincularme a una dirección IP específica, pero eso significa que primero tendría que buscar la dirección IP de la interfaz saliente.

Respuesta1

En Linux, ssh necesitaría llamar a setsockopt(IPV6_ADDR_PREFERENCES) para solicitar un tipo de dirección específico. (Esto no se menciona en los documentos de Linux setsockopt, pero el código está presente en el kernel y parece coincidir con la especificación RFC 5014).

Dado que OpenSSH no tiene ninguna opción de configuración que le permita especificar preferencias de dirección, tendría que ser un truco comoÉste(sólo con otro enchufe). Puede intentar pedirles a los desarrolladores de OpenSSH que agreguen dicha opción, pero generalmente no quieren agregar ninguna característica del sistema operativo que OpenBSD no admita.

Probablemente sea más fácil escribir un script para obtener la dirección correcta -b; por ejemplo, si estás en Linux puedes usar ip | jq:

addr=$(ip -json -6 addr ls dev eno1 scope global \
      | jq -r ".[].addr_info[]|select(.local)|select(.temporary|not)|.local")

ssh -b $addr ...

Alternativamente, desactive completamente las direcciones temporales (Extensiones de privacidad).

Pero si quieres probar suerte con LD_PRELOAD, puedes probar esto (no lo he probado en absoluto; es muy posible que se active demasiado tarde para tener algún efecto):

/* gcc -shared -o ipv6pref.so ipv6pref.c */
/* LD_PRELOAD="$HOME/ipv6pref.so" ssh whatever */

#define _GNU_SOURCE
#include <dlfcn.h>
#include <err.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>

int setsockopt(int fd, int level, int name, const void *value, socklen_t len)
{
    static int (*real_setsockopt)(int, int, int, const void *, socklen_t);
    uint32_t flags = IPV6_PREFER_SRC_PUBLIC;
    int r;

    if (!real_setsockopt)
        real_setsockopt = dlsym(RTLD_NEXT, "setsockopt");
    
    if ((level == SOL_IP && name == IP_TOS) ||
        (level == SOL_IPV6 && name == IPV6_TCLASS))
    {
        /* This is probably the TCP socket that will be used for SSH. */
        r = real_setsockopt(fd, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &flags, sizeof flags);
        if (r != 0)
            warn("Could not set address preference");
    }

    return real_setsockopt(fd, level, name, value, len);
}

información relacionada