func (p *PacketSprayer) SetIPLayer(iplayer layers.IPv4) error { p.ip = iplayer p.ipBuf = gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } err := p.ip.SerializeTo(p.ipBuf, opts) if err != nil { return err } p.ipHeader, err = ipv4.ParseHeader(p.ipBuf.Bytes()) if err != nil { return err } return nil }
func (i *TCPStreamInjector) SetIPLayer(iplayer layers.IPv4) error { i.ip = iplayer i.ipBuf = gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } err := i.ip.SerializeTo(i.ipBuf, opts) if err != nil { return err } i.ipHeader, err = ipv4.ParseHeader(i.ipBuf.Bytes()) if err != nil { return err } return nil }
//sendPacket generates & sends a packet of arbitrary size to a specific destination. //The size specified should be larger then 40bytes. func sendPacket(sourceIP string, destinationIP string, size int, message string, appID int, chanID int, icmpType layers.ICMPv4TypeCode) []byte { var payloadSize int if size < 28 { //Unable to create smaller packets. payloadSize = 0 } else { payloadSize = size - 28 } //Convert IP to 4bit representation srcIP := net.ParseIP(sourceIP).To4() dstIP := net.ParseIP(destinationIP).To4() //IP Layer ip := layers.IPv4{ SrcIP: srcIP, DstIP: dstIP, Version: 4, TTL: 64, Protocol: layers.IPProtocolICMPv4, } icmp := layers.ICMPv4{ TypeCode: icmpType, } opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ipHeaderBuf := gopacket.NewSerializeBuffer() err := ip.SerializeTo(ipHeaderBuf, opts) if err != nil { panic(err) } //Set "Don't Fragment"-Flag in Header ipHeader, err := ipv4.ParseHeader(ipHeaderBuf.Bytes()) ipHeader.Flags |= ipv4.DontFragment if err != nil { panic(err) } payloadBuf := gopacket.NewSerializeBuffer() //Influence the payload size payload := gopacket.Payload(generatePayload(payloadSize, ","+strconv.Itoa(appID)+","+strconv.Itoa(chanID)+","+message+",")) err = gopacket.SerializeLayers(payloadBuf, opts, &icmp, payload) if err != nil { panic(err) } //Send packet var packetConn net.PacketConn var rawConn *ipv4.RawConn packetConn, err = net.ListenPacket("ip4:icmp", srcIP.String()) if err != nil { panic(err) } rawConn, err = ipv4.NewRawConn(packetConn) if err != nil { panic(err) } err = rawConn.WriteTo(ipHeader, payloadBuf.Bytes(), nil) return append(ipHeaderBuf.Bytes(), payloadBuf.Bytes()...) }
func sndrThread(conn *net.UDPConn, iface *water.Interface) { // first time fill with random numbers ivbuf := make([]byte, aes.BlockSize) if _, err := io.ReadFull(rand.Reader, ivbuf); err != nil { log.Fatalln("Unable to get rand data:", err) } var packet IPPacket = make([]byte, BUFFERSIZE) for { plen, err := iface.Read(packet[2 : MTU+2]) if err != nil { break } if 4 != packet.IPver() { header, _ := ipv4.ParseHeader(packet[2:]) log.Printf("Non IPv4 packet [%+v]\n", header) continue } // each time get pointer to (probably) new config c := config.Load().(VPNState) dst := packet.Dst() wanted := false addr, ok := c.remotes[dst] if ok { wanted = true } if dst == c.Main.bcastIP || packet.IsMulticast() { wanted = true } // very ugly and useful only for a limited numbers of routes! if !wanted { ip := packet.DstV4() for n, s := range c.routes { if n.Contains(ip) { addr = s ok = true wanted = true break } } } if wanted { // store orig packet len packet[0] = byte(plen % 256) packet[1] = byte(plen / 256) // encrypt clen := plen + 2 if clen%aes.BlockSize != 0 { clen += aes.BlockSize - (clen % aes.BlockSize) } if clen > len(packet) { log.Println("clen > len(package)", clen, len(packet)) continue } ciphertext := make([]byte, aes.BlockSize+clen) iv := ciphertext[:aes.BlockSize] copy(iv, ivbuf) mode := cipher.NewCBCEncrypter(c.Main.block, iv) mode.CryptBlocks(ciphertext[aes.BlockSize:], packet[:clen]) // save new iv copy(ivbuf, ciphertext[clen-aes.BlockSize:]) if ok { n, err := conn.WriteToUDP(ciphertext, addr) if nil != err { log.Println("Error sending package:", err) } if n != len(ciphertext) { log.Println("Only ", n, " bytes of ", len(ciphertext), " sent") } } else { // multicast or broadcast for _, addr := range c.remotes { n, err := conn.WriteToUDP(ciphertext, addr) if nil != err { log.Println("Error sending package:", err) } if n != len(ciphertext) { log.Println("Only ", n, " bytes of ", len(ciphertext), " sent") } } } } else { fmt.Println("Unknown dst", dst) } } }