/dev/tunX
デバイスファイルがありません。代わりに、 を開き、を「指す」/dev/net/tun
ように構成します。基本的な手順を示すために、コマンド ライン ツールを使用して TUN インターフェイスを作成し、その TUN デバイスから読み取る C コードを示します。したがって、コマンド ライン経由で tun インターフェイスを作成するには、次のようにします。ioctl()
tun0
ip tun tap
ip addr show # my eth0 inet address is 10.0.2.15/24 as Im running on a VirtualBox vm with Ubuntu 18.04 guest
sudo ip tuntap add mode tun dev tun0
sudo ip addr add 10.0.3.0/24 dev tun0 # give it an address (that does not conflict with existing IP)
sudo ip link set dev tun0 up # bring the if up
ip route get 10.0.3.50 # check that packets to 10.0.3.x are going through tun0
# 10.0.3.50 dev tun0 src 10.0.3.0 uid 1000
ping 10.0.3.50 # leave this running in another shell to be able to see the effect of the next example, nobody is responding to the ping
tun0
が作成され、宛先 IP アドレス 10.0.3.x へのすべてのパケットが にルーティングされますtun0
。
/dev/net/tun
ユーザー空間プログラムからこのインターフェイスにパケットを読み書きするには、ioctl()
. tun0
インターフェイスに到着するパケットを読み取り、サイズを出力する例を次に示します。
#include <fcntl.h> /* O_RDWR */
#include <string.h> /* memset(), memcpy() */
#include <stdio.h> /* perror(), printf(), fprintf() */
#include <stdlib.h> /* exit(), malloc(), free() */
#include <sys/ioctl.h> /* ioctl() */
#include <unistd.h> /* read(), close() */
/* includes for struct ifreq, etc */
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
int tun_open(char *devname)
{
struct ifreq ifr;
int fd, err;
if ( (fd = open("/dev/net/tun", O_RDWR)) == -1 ) {
perror("open /dev/net/tun");exit(1);
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN;
strncpy(ifr.ifr_name, devname, IFNAMSIZ); // devname = "tun0" or "tun1", etc
/* ioctl will use ifr.if_name as the name of TUN
* interface to open: "tun0", etc. */
if ( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1 ) {
perror("ioctl TUNSETIFF");close(fd);exit(1);
}
/* After the ioctl call the fd is "connected" to tun device specified
* by devname ("tun0", "tun1", etc)*/
return fd;
}
int main(int argc, char *argv[])
{
int fd, nbytes;
char buf[1600];
fd = tun_open("tun0"); /* devname = ifr.if_name = "tun0" */
printf("Device tun0 opened\n");
while(1) {
nbytes = read(fd, buf, sizeof(buf));
printf("Read %d bytes from tun0\n", nbytes);
}
return 0;
}
ping 10.0.3.1
またはping 10.0.3.40
を実行している場合は、Read 88 bytes from tun0
定期的に表示されます。
nc -u 10.0.3.3 2222
テキスト + Enter を入力して netcat UDP を使用してテストすることもできます。
何も表示されない場合は、tun0 に割り当てられた ID アドレス / IP 範囲が到達可能 / ルーティング可能 / アドレス可能でない可能性が最も高いです。Linux カーネルが 10.0.3.4 へのパケットを tun0 デバイスに送信する必要があることを認識していることをip route get 10.0.3.4
示すショーを確認してください。10.0.3.4 dev tun0
削除するにtun0
は
sudo ip link set dev tun0 down
sudo ip tuntap del mode tun dev tun0