1

我正在尝试本教程来创建和使用tun界面。就我而言,我想在 docker 容器中使用它。我的主机和 docker 容器都是支持 mknod 的 Linux。我正在尝试在容器内获取 tun 接口以从主机读取数据包,但不使用--network=host.

基于docker run doc,我/dev/net/tun使用--device. 然后添加功能NET_ADMIN(也尝试添加MKNODNET_RAW但似乎没有帮助)。然后使用下面的示例 tun 阅读器;这是上面教程中的示例;添加代码以创建界面;试图读取数据包。

它可以从容器内从 10.0.0.2 上 ping 读取数据包。但无法从主机上的 ping 读取。使用--network=host标志 to docker runtunx接口在主机上创建,因此 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;
}
4

0 回答 0