임시가 아닌 IPv6 주소를 사용하여 연결하도록 ssh에 어떻게 알릴 수 있습니까?

임시가 아닌 IPv6 주소를 사용하여 연결하도록 ssh에 어떻게 알릴 수 있습니까?

IPv6 인터페이스(적어도 라우팅 가능한 IP 포함)에는 일반적으로 임시 IP 주소가 있으며, 이는 자주 변경되며 일반적으로 더 많은 개인 정보 보호를 제공하기 위해 아웃바운드 연결에 사용됩니다.

ssh에게 이 주소를 사용하지 않고 대신 특정 아웃바운드 연결 시도에 대해 임시가 아닌 주소에 바인딩하도록 지시하려면 어떻게 해야 합니까?

특정 IP 주소에 바인딩하는 옵션을 사용할 수 있다는 것을 알고 있지만 -b이는 먼저 아웃바운드 인터페이스의 IP 주소를 조회해야 함을 의미합니다.

답변1

Linux에서 ssh는 특정 주소 유형을 요청하려면 setockopt(IPV6_ADDR_PREFERENCES)를 호출해야 합니다. (이것은 Linux setockopt 문서에는 언급되지 않았지만 코드는 커널에 존재하며 RFC 5014 사양과 일치하는 것 같습니다.)

OpenSSH에는 주소 기본 설정을 지정할 수 있는 구성 옵션이 없으므로 다음과 같은 해킹이어야 합니다.이 하나(다른 소켓을 사용하는 경우에만). OpenSSH 개발자에게 이러한 옵션을 추가하도록 요청할 수 있지만 일반적으로 OpenBSD가 지원하지 않는 OS 기능을 추가하는 것을 원하지 않습니다.

에 대한 올바른 주소를 얻기 위해 무언가를 스크립트하는 것이 더 쉬울 것입니다 -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);
}

관련 정보