如何告訴 ssh 使用非臨時 IPv6 位址進行連線?

如何告訴 ssh 使用非臨時 IPv6 位址進行連線?

IPv6 介面(至少具有可路由的 IP)通常有一個臨時 IP 位址,該位址經常更改,通常用於出站連接,以提供更多隱私。

我該如何告訴 ssh 不要使用此位址,而是針對給定的出站連線嘗試綁定到非臨時位址?

我知道我可以使用該-b選項綁定到特定的 IP 位址,但這意味著我必須先查找出站介面的 IP 位址。

答案1

在 Linux 上,ssh 需要呼叫 setsockopt(IPV6_ADDR_PREFERENCES) 來請求特定的位址類型。 (Linux setsockopt 文件中沒有提到這一點,但程式碼存在於核心中,並且似乎符合 RFC 5014 規範。)

由於 OpenSSH 沒有任何設定選項可以讓您指定位址首選項,因此它必須是像這樣的 hack這個(僅適用於不同的 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);
}

相關內容