Exemplo n.º 1
0
func setTunIP(iface *water.Interface, ip net.IP, subnet *net.IPNet) (err error) {
	ip = ip.To4()
	logger.Debug("%v", ip)
	if ip[3]%2 == 0 {
		return invalidAddr
	}

	peer := net.IP(make([]byte, 4))
	copy([]byte(peer), []byte(ip))
	peer[3]++
	tun_peer = peer

	sargs := fmt.Sprintf("addr add dev %s local %s peer %s", iface.Name(), ip, peer)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	logger.Info("ip %s", sargs)
	err = cmd.Run()
	if err != nil {
		return err
	}

	sargs = fmt.Sprintf("route add %s via %s dev %s", subnet, peer, iface.Name())
	args = strings.Split(sargs, " ")
	cmd = exec.Command("ip", args...)
	logger.Info("ip %s", sargs)
	err = cmd.Run()
	return err
}
Exemplo n.º 2
0
Arquivo: main.go Projeto: kanocz/lcvpn
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])

	}
}
Exemplo n.º 3
0
Arquivo: main.go Projeto: kanocz/lcvpn
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)
		}
	}

}