我正在尝试本教程来创建和使用tun
界面。就我而言,我想在 docker 容器中使用它。我的主机和 docker 容器都是支持 mknod 的 Linux。我正在尝试在容器内获取 tun 接口以从主机读取数据包,但不使用--network=host
.
基于docker run doc,我/dev/net/tun
使用--device
. 然后添加功能NET_ADMIN
(也尝试添加MKNOD
,NET_RAW
但似乎没有帮助)。然后使用下面的示例 tun 阅读器;这是上面教程中的示例;添加代码以创建界面;试图读取数据包。
它可以从容器内从 10.0.0.2 上 ping 读取数据包。但无法从主机上的 ping 读取。使用--network=host
标志 to docker run
,tunx
接口在主机上创建,因此 ping 工作。
我的问题是,是否可以在不使用主机网络的情况下使其工作?我需要任何明确iptables
的规则来转发容器和主机之间的流量吗?
tun_alloc
功能来自本教程
码头工人命令
docker run -it --device=/dev/net/tun:/dev/net/tun -cap-add=NET_ADMIN <image>
阅读器代码
int main(void) {
const char *ifname = "tunx";
const char *ifaddr = "10.0.0.1/24";
char tun_name[IFNAMSIZ];
char buffer[2096];
int tun_fd = -1;
char cmd[1024] = "";
int err = -1;
strcpy(tun_name, ifname);
tun_fd = tun_alloc(tun_name, IFF_TUN); /* tun interface */
if (tun_fd < 0) {
fprintf(stderr, "failed to alloc_tun. tun_fd: %d\n", tun_fd);
exit(1);
}
printf("tun_fd: %d\n", tun_fd);
printf("ip commands \n");
snprintf(cmd, sizeof(cmd), "/bin/ip addr add dev %s %s", ifname, ifaddr);
err = system(cmd);
fprintf(stdout, "Running: %s, err: %d\n", cmd, err);
if (err < 0) {
fprintf(stderr, "failed system. Cmd:%s, err: %d (%s)\n", cmd, err, strerror(errno));
exit(1);
}
snprintf(cmd, sizeof(cmd), "/bin/ip link set %s up", ifname);
err = system(cmd);
fprintf(stdout, "Running: %s, err: %d\n", cmd, err);
if (err < 0) {
fprintf(stderr, "failed system. Cmd:%s, err: %d (%s)\n", cmd, err, strerror(errno));
exit(1);
}
while (1) {
/* Note that "buffer" should be at least the MTU size of the interface, eg 1500 bytes */
int nread = read(tun_fd,buffer,sizeof(buffer));
if(nread < 0) {
perror("Reading from interface");
close(tun_fd);
exit(1);
}
/* Do whatever with the data */
printf("Read %d bytes from device %s\n", nread, tun_name);
}
return 0;
}