"ip tuntap add mode tap"을 사용하여 생성된 인터페이스 이름을 얻는 방법

"ip tuntap add mode tap"을 사용하여 생성된 인터페이스 이름을 얻는 방법

sudo를 사용하여 Tap을 만든 다음 여기에 사용자 공간 프로그램(ssh)을 연결하고 싶습니다.

여러 사용자가 인터페이스 이름을 사용하기 때문에 인터페이스 이름을 하드코딩하고 싶지 않으므로 인터페이스 이름이 동적으로 생성되기를 원합니다.

그래서 저는 다음과 같이 수도꼭지를 만듭니다.

sudo ip tuntap add mode tap user $USER

ssh에 전달하는 데 사용할 수 있도록 생성된 인터페이스의 이름을 반환하는 ip 명령을 얻으려면 어떻게 해야 합니까?

답변1

tuntap장치의 Linux 프로그래밍 인터페이스는 여기에 문서화되어 있습니다(샘플 코드 포함).tuntap.rst. 인터페이스 이름을 요청한 다음 초기 호출에 전달된 구조를 사용하여 검색할 수 있습니다 ioctl(fd, TUNSETIFF, ...). ip tuntap이름이 표시되지 않으므로 이 명령만으로는 유익하지 않습니다 .

이를 수행하는 방법에는 두 가지가 있습니다.

도서관 래퍼

libc 래퍼를 추가할 수 있습니다.ioctl()이 특정 대상의 경우 런타임에 사용할 수 있습니다LD_PRELOAD이렇게 하면 원래 도구를 수정할 필요가 없습니다. 이는 해당 목적에 대한 래퍼이며 ioctl()다음으로 인쇄됩니다.표준 출력방금 생성된 인터페이스의 이름입니다. OP의 ip tuntap예를 고려하면 3번만 사용됩니다 ioctl().수도꼭지ioctl()모든 용도에 항상 동일한 수의 매개변수가 있는 것은 아니지만 매우 안전한 인터페이스입니다 (여기에서는 매개변수를 3개로 가정합니다).

wraptuntap.c:

#define _GNU_SOURCE
#include <dlfcn.h>

#include <linux/if.h>
#include <linux/if_tun.h>

#define ioctl ioctl_diverted
#include <sys/ioctl.h>
#undef ioctl

#include <stdio.h>

int ioctl(int fd, unsigned long request, void *p) {
        int ret;

        int (*orig_ioctl)(int, unsigned long, void *)=dlsym(RTLD_NEXT,"ioctl");
        if ((ret=orig_ioctl(fd, request, p)) != -1 )
                if (request == TUNSETIFF)
                        printf("%s\n",((struct ifreq *)p)->ifr_name);
        return ret;
}

논평:

  • <sys/ioctl.h>올바르게 정의 해야 TUNSETIFF하지만 동시에 그렇게 할 수 없습니다 ioctl(). 그렇지 않으면 래퍼 정의가 충돌하게 됩니다. 초기 정의는 다음으로 전송됩니다.이 SO Q/A 방법.
  • ifr_name보장됨커널 4.13부터 null이 종료되었습니다.그렇지 않으면...글쎄, 그것은 허술한 포장지입니다.

예를 들어 다음과 같이 컴파일합니다.

gcc -shared -fPIC -o /tmp/wraptuntap.so wraptuntap.c -ldl

그런 다음 다음과 같이 사용하십시오.

# LD_PRELOAD=/tmp/wraptuntap.so ip tuntap add mode tap user 1000
tap0
# LD_PRELOAD=/tmp/wraptuntap.so ip tuntap add mode tap user 1000
tap1
# LD_PRELOAD=/tmp/wraptuntap.so ip tuntap add mode tap user 1000 name foo%d
foo0
# LD_PRELOAD=/tmp/wraptuntap.so ip tuntap add mode tap user 1000 name foo%d
foo1

또는 더 유용하게:

# mytun=$(LD_PRELOAD=/tmp/wraptuntap.so ip tuntap add mode tap user 1000 name foo%d)
# ip link show dev "$mytun"
11: foo2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether ae:99:4a:2b:1f:6b brd ff:ff:ff:ff:ff:ff

이러한 인터페이스를 만드는 것은 그리 어렵지 않으므로 프로덕션 용도로 사용하려면 전용 도구를 만들거나 해당 인터페이스의 이름을 표시할 수 있는 다른 도구를 사용하는 것이 좋습니다.

장로tunctl(만수도꼭지상호 작용):

UML 유틸리티와 함께 ​​제공되는 이전(따라서 일반적으로 사용되지 않음) tunctl도구는 사용된 인터페이스 이름이 포함된 문장을 표시하지만 패턴만 생성합니다.수도꼭지(레이어 2) 인터페이스(OP가 찾고 있는 것) 대신투엔(레이어 3) 인터페이스.

예:

# tunctl -u 1000 -t foo%d
Set 'foo3' persistent and owned by uid 1000
# tunctl -u 1000 -t foo%d | sed -E "s/^Set '([^']+)' .*\$/\1/"
foo4
# ip -d link show dev foo4 # this is a "type tap" interface
13: foo4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether c2:05:de:78:16:a3 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 65521 
    tun type tap pi off vnet_hdr off persist on user 1000 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 

관련 정보