Как мне указать ssh подключаться, используя не временный адрес IPv6?

Как мне указать ssh подключаться, используя не временный адрес IPv6?

Интерфейсы IPv6 (по крайней мере с маршрутизируемыми IP-адресами) обычно имеют временный IP-адрес, который часто меняется и обычно используется для исходящих соединений с целью обеспечения большей конфиденциальности.

Как мне указать ssh не использовать этот адрес, а вместо этого привязаться к невременному для данной попытки исходящего соединения?

Я знаю, что могу использовать -bопцию привязки к определенному IP-адресу, но это означает, что мне сначала придется искать IP-адрес исходящего интерфейса.

решение1

В Linux ssh должен вызвать setsockopt(IPV6_ADDR_PREFERENCES), чтобы запросить определенный тип адреса. (Это не упоминается в документации Linux setsockopt, но код присутствует в ядре и, по-видимому, соответствует спецификации RFC 5014.)

Поскольку OpenSSH не имеет никаких параметров конфигурации, которые позволили бы вам указать предпочтения адреса, придется прибегнуть к хаку вродеВот этот(только с другим sockopt). Вы можете попробовать попросить разработчиков OpenSSH добавить такую ​​опцию, но они, как правило, не хотят добавлять какие-либо функции ОС, которые OpenBSD также не поддерживает.

Вероятно, проще написать скрипт для получения правильного адреса -b; например, если вы работаете в Linux, вы можете использовать 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 ...

Либо полностью отключите временные адреса (расширения конфиденциальности).

Но если вы хотите попытать счастья с LD_PRELOAD, вы можете протестировать это (я вообще не тестировал; вполне может быть, что это сработает слишком поздно, чтобы оказать какой-либо эффект):

/* 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);
}

Связанный контент