songgao/water

how to read all packet from the tun/tap device

youerning opened this issue · 3 comments

how to read all packet from the tun/tap device

i want to analyze the packet from tap/tun device, but only BROADCAST packet is recieved from the tun/tap device when i use iface.read method.

code as below.

package main

import (
	// "encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	// "strings"

	// "fastvpn/common"
	"github.com/songgao/water"
	"golang.org/x/net/ipv4"
)

const (
	BUFFERSIZE = 1500
	MTU        = "1500"
)

func checkFatalErr(err error, msg string) {
	if err != nil {
		log.Println(msg)
		log.Fatal(err)
	}
}

func runIP(args ...string) {
	cmd := exec.Command("/sbin/ip", args...)
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout

	err := cmd.Run()

	if err != nil {
		log.Fatal("Error runing /sbin/ip:", err)
	}
}

func main() {
	config := water.Config{
		DeviceType: water.TAP,
	}

	iface, err := water.New(config)
	checkFatalErr(err, "Unable to allocate TUN interface: ")
	log.Println("Interface allocated: ", iface.Name())

	runIP("link", "set", "dev", iface.Name(), "mtu", MTU)
	runIP("addr", "add", "192.168.1.85/24", "dev", iface.Name())
	runIP("link", "set", "dev", iface.Name(), "up")

	packet := make([]byte, BUFFERSIZE)

	for {
               // read packaet
		plen, err := iface.Read(packet)
		fmt.Println("readed")
		if err != nil {
			fmt.Println("erro read")
			fmt.Println(err)
		}

		header, _ := ipv4.ParseHeader(packet[:plen])
		dstIP := header.Dst.String()
		srcIP := header.Src.String()
		fmt.Println(dstIP)
		fmt.Println(srcIP)
	}
}

only the broadcast packet is recieved when a excute the command, as below.
ping -c1 -b 192.168.1.255

my question is how can i read all packet from the tap device,everything send to the tap,like ping 192.168.1.85

Tks.

It seems your TAP device has the IP 192.168.1.85. Sending packets to that IP won't work in your test because the kernel knows it's an address locally, and would bypass the TUN/TAP driver entirely and just deliver it to the network stack. Did you try e.g. ping -c1 -b 192.168.1.80?

yes,you are rigth,the method i test packet capture is wrong,i should ping 192.168.1.84(any ip in the subnet range except 85.).if i ping 192.168.1.84,the iface.read method is work well, could be recieve packet beacuse the kernel will pass the packet to the tap device according to the route table.

thanks very much.
it's nice golang lib for develop some tool use tun/tap device.