Esempio n. 1
0
func handleTCP(conn *net.TCPConn, timeouted, rehandshaking, termination chan struct{}) {
	hs := govpn.HandshakeStart(*remoteAddr, conn, conf)
	buf := make([]byte, govpn.MTU)
	var n int
	var err error
	var prev int
	var peer *govpn.Peer
	var terminator chan struct{}
HandshakeCycle:
	for {
		select {
		case <-termination:
			break HandshakeCycle
		default:
		}
		if prev == govpn.MTU {
			log.Println("Timeouted waiting for the packet")
			timeouted <- struct{}{}
			break HandshakeCycle
		}

		conn.SetReadDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
		n, err = conn.Read(buf[prev:])
		if err != nil {
			log.Println("Connection timeouted")
			timeouted <- struct{}{}
			break HandshakeCycle
		}

		prev += n
		peerId := idsCache.Find(buf[:prev])
		if peerId == nil {
			continue
		}
		peer = hs.Client(buf[:prev])
		prev = 0
		if peer == nil {
			continue
		}
		log.Println("Handshake completed")
		knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{*remoteAddr: &peer})
		if firstUpCall {
			go govpn.ScriptCall(*upPath, *ifaceName)
			firstUpCall = false
		}
		hs.Zero()
		terminator = make(chan struct{})
		go func() {
			heartbeat := time.NewTicker(peer.Timeout)
			var data []byte
		Processor:
			for {
				select {
				case <-heartbeat.C:
					peer.EthProcess(nil)
				case <-terminator:
					break Processor
				case data = <-tap.Sink:
					peer.EthProcess(data)
				}
			}
			heartbeat.Stop()
			peer.Zero()
		}()
		break HandshakeCycle
	}
	if hs != nil {
		hs.Zero()
	}
	if peer == nil {
		return
	}

	nonceExpectation := make([]byte, govpn.NonceSize)
	peer.NonceExpectation(nonceExpectation)
	prev = 0
	var i int
TransportCycle:
	for {
		select {
		case <-termination:
			break TransportCycle
		default:
		}
		if prev == govpn.MTU {
			log.Println("Timeouted waiting for the packet")
			timeouted <- struct{}{}
			break TransportCycle
		}
		conn.SetReadDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
		n, err = conn.Read(buf[prev:])
		if err != nil {
			log.Println("Connection timeouted")
			timeouted <- struct{}{}
			break TransportCycle
		}
		prev += n
	CheckMore:
		if prev < govpn.MinPktLength {
			continue
		}
		i = bytes.Index(buf[:prev], nonceExpectation)
		if i == -1 {
			continue
		}
		if !peer.PktProcess(buf[:i+govpn.NonceSize], tap, false) {
			log.Println("Unauthenticated packet, dropping connection")
			timeouted <- struct{}{}
			break TransportCycle
		}
		if atomic.LoadInt64(&peer.BytesIn)+atomic.LoadInt64(&peer.BytesOut) > govpn.MaxBytesPerKey {
			log.Println("Need rehandshake")
			rehandshaking <- struct{}{}
			break TransportCycle
		}
		peer.NonceExpectation(nonceExpectation)
		copy(buf, buf[i+govpn.NonceSize:prev])
		prev = prev - i - govpn.NonceSize
		goto CheckMore
	}
	if terminator != nil {
		terminator <- struct{}{}
	}
	peer.Zero()
	conn.Close()
}
Esempio n. 2
0
func handleTCP(conn net.Conn) {
	addr := conn.RemoteAddr().String()
	buf := make([]byte, govpn.MTU)
	var n int
	var err error
	var prev int
	var hs *govpn.Handshake
	var ps *PeerState
	var peer *govpn.Peer
	var tap *govpn.TAP
	var conf *govpn.PeerConf
	for {
		if prev == govpn.MTU {
			break
		}
		conn.SetReadDeadline(time.Now().Add(time.Duration(govpn.TimeoutDefault) * time.Second))
		n, err = conn.Read(buf[prev:])
		if err != nil {
			// Either EOFed or timeouted
			break
		}
		prev += n
		peerId := idsCache.Find(buf[:prev])
		if peerId == nil {
			continue
		}
		if hs == nil {
			conf = confs[*peerId]
			if conf == nil {
				log.Println("Can not get peer configuration:", peerId.String())
				break
			}
			hs = govpn.NewHandshake(addr, conn, conf)
		}
		peer = hs.Server(buf[:prev])
		prev = 0
		if peer == nil {
			continue
		}
		hs.Zero()
		log.Println("Peer handshake finished:", addr, peer.Id.String())
		peersByIdLock.RLock()
		addrPrev, exists := peersById[*peer.Id]
		peersByIdLock.RUnlock()
		if exists {
			peersLock.Lock()
			peers[addrPrev].terminator <- struct{}{}
			tap = peers[addrPrev].tap
			ps = &PeerState{
				peer:       peer,
				tap:        tap,
				terminator: make(chan struct{}),
			}
			go peerReady(*ps)
			peersByIdLock.Lock()
			kpLock.Lock()
			delete(peers, addrPrev)
			delete(knownPeers, addrPrev)
			peers[addr] = ps
			knownPeers[addr] = &peer
			peersById[*peer.Id] = addr
			peersLock.Unlock()
			peersByIdLock.Unlock()
			kpLock.Unlock()
			log.Println("Rehandshake processed:", peer.Id.String())
		} else {
			ifaceName, err := callUp(peer.Id)
			if err != nil {
				break
			}
			tap, err = govpn.TAPListen(ifaceName)
			if err != nil {
				log.Println("Unable to create TAP:", err)
				break
			}
			ps = &PeerState{
				peer:       peer,
				tap:        tap,
				terminator: make(chan struct{}, 1),
			}
			go peerReady(*ps)
			peersLock.Lock()
			peersByIdLock.Lock()
			kpLock.Lock()
			peers[addr] = ps
			peersById[*peer.Id] = addr
			knownPeers[addr] = &peer
			peersLock.Unlock()
			peersByIdLock.Unlock()
			kpLock.Unlock()
			log.Println("Peer created:", peer.Id.String())
		}
		break
	}
	if hs != nil {
		hs.Zero()
	}
	if peer == nil {
		return
	}

	nonceExpectation := make([]byte, govpn.NonceSize)
	peer.NonceExpectation(nonceExpectation)
	prev = 0
	var i int
	for {
		if prev == govpn.MTU {
			break
		}
		conn.SetReadDeadline(time.Now().Add(conf.Timeout))
		n, err = conn.Read(buf[prev:])
		if err != nil {
			// Either EOFed or timeouted
			break
		}
		prev += n
	CheckMore:
		if prev < govpn.MinPktLength {
			continue
		}
		i = bytes.Index(buf[:prev], nonceExpectation)
		if i == -1 {
			continue
		}
		if !peer.PktProcess(buf[:i+govpn.NonceSize], tap, false) {
			log.Println(
				"Unauthenticated packet, dropping connection",
				addr, peer.Id.String(),
			)
			break
		}
		peer.NonceExpectation(nonceExpectation)
		copy(buf, buf[i+govpn.NonceSize:prev])
		prev = prev - i - govpn.NonceSize
		goto CheckMore
	}
	peer.Zero()
}