/*
 * @Author: dean 1028968939@qq.com
 * @Date: 2024-07-13 12:05:39
 * @LastEditors: dean 1028968939@qq.com
 * @LastEditTime: 2024-07-13 13:01:16
 * @FilePath: \Workspace\GoWorkSpace\Demo\main.go
 * @Description: tun虚拟机网卡demo
 */
package main

import (
    "bufio"
    "fmt"
    "os"
    "os/exec"
    "syscall"
    "unsafe"
)

// 定义 ifreq 结构体
type Ifreq struct {
    Name  [syscall.IFNAMSIZ]byte // 接口名称
    Flags uintptr                // 标志位
}

func createTunDevice(tunName string) (*os.File, error) {
    // 打开 /dev/net/tun 设备
    fd, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
    if err != nil {
        return nil, err
    }

    // 准备 ifreq 结构体
    var ifr Ifreq
    copy(ifr.Name[:], []byte(tunName))
    ifr.Flags = syscall.IFF_TUN | syscall.IFF_NO_PI // 创建一个 Tun 设备

    // 使用 ioctl 设置 Tun 设备
    if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd.Fd()), syscall.TUNSETIFF, uintptr(unsafe.Pointer(&ifr))); errno != 0 {
        fd.Close()
        return nil, fmt.Errorf("ioctl TUNSETIFF failed: %w", errno)
    }

    return fd, nil
}

func execCommand(command string) {
    cmd := exec.Command("/usr/bin/bash", "-c", command)
    _, err := cmd.CombinedOutput()
    if err != nil {
        fmt.Printf("命令执行失败: %s, %s\n", command, err)
        return
    }
}

func main() {
    tunDeviceName := "tun0"
    // execCommand(fmt.Sprintf("ip tuntap del dev  %s mode tun", tunDeviceName))
    // execCommand(fmt.Sprintf("ip tuntap add dev  %s mode tun", tunDeviceName))
    // execCommand(fmt.Sprintf("ip addr flush dev  %s", tunDeviceName))
    fd, err := createTunDevice(tunDeviceName)
    if err != nil {
        fmt.Printf("Failed to create tun device: %v\n", err)
        return
    }
    defer fd.Close()

    // 配置IP,并打开网卡(否则ping无反应)
    // ping 同网段其他网卡地址,ping本机的IP是收不到的,流量不经过网卡
    execCommand(fmt.Sprintf("ip addr add 192.168.1.100/24 dev %s", tunDeviceName))
    execCommand(fmt.Sprintf("ip link set %s up", tunDeviceName))

    reader := bufio.NewReader(fd)
    for {
        data := make([]byte, 4096)
        n, err := reader.Read(data)
        if err != nil {
            fmt.Printf("Error reading from tun device: %v\n", err)
            break
        }

        fmt.Println(data[0:n])
    }

}

标签: none

评论已关闭