TUN/TAPのメモ
2023-06-17
TUN/TAPについて勉強したのでそれのメモ
tun/tapは仮想的なnetworkスタックでEthernet framesやip packetsをプログラムから扱うことができる。
dockerを使う場合はrunする場合に--privileged
をつけないと動かない。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
int main() {
char dev_name[IFNAMSIZ] = "test_device";
struct ifreq ifr;
int fd;
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
perror("Opening /dev/net/tun");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
perror("ioctl(TUNSETIFF)");
exit(1);
}
printf("Successfully allocated interface %s\n", dev_name);
char buffer[BUFSIZ];
while (1) {
int nread = read(fd, buffer, BUFSIZ);
if (nread < 0) {
perror("reading from interface");
close(fd);
exit(1);
}
printf("Read %d bytes from interface %s \n", nread, buffer);
for (int i = 0; i < nread; i++) {
printf("%02X ", (unsigned char)buffer[i]);
}
printf("\n");
}
}
上記のプログラムを実行するとネットワークインタフェースができている。
$ ip link show | grep test_device
4: test_device: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
状態がdownなので、コマンドでネットワークインターフェースを起こす。
$ ip link set test_device up
これで使えるようになった。pingでこのデバイスにパケットを送るためにルーティングテーブルを設定する。
$ ip addr add 10.0.0.1/24 dev test_device
これで10.0.0.2とかにpingするとさっきのプログラムの出力にきたEthernetのframeが流れる。多分ARPのリクエスト。だけど、10.0.0.1に送るとカーネルが処理をしてしまうので、ネットマスクの範囲のルーティングされるアドレスに送る必要がある。
参考になった記事: https://backreference.org/2010/03/26/tuntap-interface-tutorial/index.html