package main import ( "bufio" "encoding/hex" "fmt" "log" "net" "os" "os/exec" "strings" "time" "github.com/songgao/packets/ethernet" "github.com/songgao/water" ) //declare IP and subnet mask here var ( self = net.ParseIP(os.Args[2]) mask = net.IPv4Mask(255, 255, 255, 0) ) //declare new interface here var ifce, _ = water.New(water.Config{ DeviceType: water.TAP, }) var RCV_B = 0 //recived in byte var TXT_B = 0 //sent in byte var RCV_T = 0 //number of packet recived var TXT_T = 0 //number of packet sended func main() { //for stat only go func() { for { //showing statistics here, every 5 seconds log.Println("Total recived: ", ByteCountSI(RCV_B), ", Total transmited: ", ByteCountSI(TXT_B)) log.Println("Total recived: ", RCV_T, ", Total transmited: ", TXT_T) time.Sleep(5 * time.Second) } }() //create socket server go func() { fmt.Println("Launching server...") //show debug message // listen on all interfaces ln, _ := net.Listen("tcp", ":8081") //create new interface // accept connection on port conn, _ := ln.Accept() //accept connections // run loop forever (or until ctrl-c) for { // will listen for message to process ending in newline (\n) message, _ := bufio.NewReader(conn).ReadString('\n') // output message received //fmt.Print("RECV<<", string(message)) RCV_B += len(string(message)) //for statistics RCV_T++ //for statistics data, err := hex.DecodeString(strings.ReplaceAll("\n", "", string(message))) //since data had \n, so replace it and convert to hex array if err != nil { //log.Println(err) } //log.Println("RECV<<", data) ifce.Write(data) //write to interface } }() //declare server // connect to server conns, _ := net.Dial("tcp", os.Args[1]+":8081") var frame ethernet.Frame //declare frame setupIfce(net.IPNet{IP: self, Mask: mask}, ifce.Name()) //setup interface info for { frame.Resize(1500) //MTU = 1500 n, err := ifce.Read([]byte(frame)) //read from ifce if err != nil { log.Fatal(err) } frame = frame[:n] //fconvert frame to usabele array //log.Println("TRSV>>", hex.EncodeToString(frame)) TXT_B += len(hex.EncodeToString(frame)) //for statistics TXT_T++ //for statistics /* log.Printf("Dst: %s\n", frame.Destination()) log.Printf("Src: %s\n", frame.Source()) log.Printf("Ethertype: % x\n", frame.Ethertype()) log.Printf("Payload: % x\n", frame.Payload()) log.Printf("HEX: % x\n", frame) */ fmt.Fprintf(conns, hex.EncodeToString(frame)+"\n") //send to server /* a := hex.EncodeToString(frame) resp, err := http.Get("http://" + os.Args[1] + "/rcv?packet=" + a) if err != nil { fmt.Println(err) } else { defer resp.Body.Close() } */ } } func setupIfce(ipNet net.IPNet, dev string) { sargs := fmt.Sprintf("interface ip set address name=REPLACE_ME source=static addr=REPLACE_ME mask=REPLACE_ME gateway=none") args := strings.Split(sargs, " ") args[4] = fmt.Sprintf("name=%s", dev) args[6] = fmt.Sprintf("addr=%s", ipNet.IP) args[7] = fmt.Sprintf("mask=%d.%d.%d.%d", ipNet.Mask[0], ipNet.Mask[1], ipNet.Mask[2], ipNet.Mask[3]) cmd := exec.Command("netsh", args...) if err := cmd.Run(); err != nil { log.Println(err) } } //https://yourbasic.org/golang/formatting-byte-size-to-human-readable-format/ func ByteCountSI(b int) string { const unit = 1000 if b < unit { return fmt.Sprintf("%d B", b) } div, exp := int(unit), 0 for n := b / unit; n >= unit; n /= unit { div *= unit exp++ } return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp]) }