/*
* @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])
}
}
评论已关闭