func rcvrThread(proto string, port int, iface *water.Interface) { conn, err := reuseport.NewReusableUDPPortConn(proto, fmt.Sprintf(":%v", port)) if nil != err { log.Fatalln("Unable to get UDP socket:", err) } buf := make([]byte, BUFFERSIZE) for { n, _, err := conn.ReadFrom(buf) if err != nil { fmt.Println("Error: ", err) continue } // ReadFromUDP can return 0 bytes on timeout if 0 == n { continue } if n%aes.BlockSize != 0 { fmt.Println("packet size ", n, " is not a multiple of the block size") continue } iv := buf[:aes.BlockSize] ciphertext := buf[aes.BlockSize:n] conf := config.Load().(VPNState) mode := cipher.NewCBCDecrypter(conf.Main.block, iv) var size int if conf.Main.hasalt { // if we have alternative key we need store orig packet for second try pcopy := make([]byte, n) copy(pcopy, buf[:n]) mode.CryptBlocks(ciphertext, ciphertext) size = int(ciphertext[0]) + (256 * int(ciphertext[1])) if (n-aes.BlockSize-2)-size > 16 || (n-aes.BlockSize-2)-size < 0 || 4 != ((ciphertext)[2]>>4) { // don't looks like anything is ok, trying second key copy(buf[:n], pcopy) cipher.NewCBCDecrypter(conf.Main.altblock, iv).CryptBlocks(ciphertext, ciphertext) size = int(ciphertext[0]) + (256 * int(ciphertext[1])) if (n-aes.BlockSize-2)-size > 16 || (n-aes.BlockSize-2)-size < 0 || 4 != ((ciphertext)[2]>>4) { fmt.Println("Invalid size field or IPv4 id in decrypted message", size, (n - aes.BlockSize - 2)) continue } } } else { mode.CryptBlocks(ciphertext, ciphertext) size = int(ciphertext[0]) + (256 * int(ciphertext[1])) if (n-aes.BlockSize-2)-size > 16 || (n-aes.BlockSize-2)-size < 0 { fmt.Println("Invalid size field in decrypted message", size, (n - aes.BlockSize - 2)) continue } if 4 != ((ciphertext)[2] >> 4) { fmt.Println("Non IPv4 packet after decryption, possible corupted packet") continue } } iface.Write(ciphertext[2 : 2+size]) } }