Example #1
0
func main() {
	flag.Parse()
	timeout := time.Second * time.Duration(govpn.TimeoutDefault)
	log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
	log.Println(govpn.VersionGet())

	govpn.MTU = *mtu
	govpn.PeersInit(*peersPath)

	if *egdPath != "" {
		log.Println("Using", *egdPath, "EGD")
		govpn.EGDInit(*egdPath)
	}

	sink := make(chan Pkt)
	switch *proto {
	case "udp":
		startUDP(sink)
	case "tcp":
		startTCP(sink)
	case "all":
		startUDP(sink)
		startTCP(sink)
	default:
		log.Fatalln("Unknown protocol specified")
	}

	termSignal := make(chan os.Signal, 1)
	signal.Notify(termSignal, os.Interrupt, os.Kill)

	hsHeartbeat := time.Tick(timeout)
	go func() { <-hsHeartbeat }()

	var state *govpn.Handshake
	var peerState *PeerState
	var peer *govpn.Peer
	var exists bool
	states := make(map[string]*govpn.Handshake)
	peers := make(map[string]*PeerState)
	peerReadySink := make(chan PeerReadyEvent)
	knownPeers := govpn.KnownPeers(make(map[string]**govpn.Peer))
	var peerReady PeerReadyEvent
	var pkt Pkt
	var ethEvent EthEvent
	var peerId *govpn.PeerId
	var peerConf *govpn.PeerConf
	var handshakeProcessForce bool
	ethSink := make(chan EthEvent)

	log.Println("Max MTU on TAP interface:", govpn.TAPMaxMTU())
	if *stats != "" {
		log.Println("Stats are going to listen on", *stats)
		statsPort, err := net.Listen("tcp", *stats)
		if err != nil {
			log.Fatalln("Can not listen on stats port:", err)
		}
		go govpn.StatsProcessor(statsPort, &knownPeers)
	}
	if *proxy != "" {
		go proxyStart(sink)
	}
	log.Println("Server started")

MainCycle:
	for {
		select {
		case <-termSignal:
			break MainCycle
		case <-hsHeartbeat:
			now := time.Now()
			for addr, hs := range states {
				if hs.LastPing.Add(timeout).Before(now) {
					log.Println("Deleting handshake state", addr)
					hs.Zero()
					delete(states, addr)
				}
			}
			for addr, state := range peers {
				if state.peer.LastPing.Add(timeout).Before(now) {
					log.Println("Deleting peer", state.peer)
					delete(peers, addr)
					delete(knownPeers, addr)
					downPath := path.Join(
						govpn.PeersPath,
						state.peer.Id.String(),
						"down.sh",
					)
					go govpn.ScriptCall(downPath, state.tap.Name)
					state.terminate <- struct{}{}
					state.peer.Zero()
				}
			}
		case peerReady = <-peerReadySink:
			for addr, state := range peers {
				if state.tap.Name != peerReady.iface {
					continue
				}
				delete(peers, addr)
				delete(knownPeers, addr)
				state.terminate <- struct{}{}
				state.peer.Zero()
				break
			}
			state := NewPeerState(peerReady.peer, peerReady.iface)
			if state == nil {
				continue
			}
			peers[peerReady.peer.Addr] = state
			knownPeers[peerReady.peer.Addr] = &peerReady.peer
			states[peerReady.peer.Addr].Zero()
			delete(states, peerReady.peer.Addr)
			log.Println("Registered interface", peerReady.iface, "with peer", peer)
			go func(state *PeerState) {
				for data := range state.sink {
					ethSink <- EthEvent{
						peer:  state.peer,
						data:  data,
						ready: state.ready,
					}
				}
			}(state)
		case ethEvent = <-ethSink:
			if s, exists := peers[ethEvent.peer.Addr]; !exists || s.peer != ethEvent.peer {
				continue
			}
			ethEvent.peer.EthProcess(ethEvent.data, ethEvent.ready)
		case pkt = <-sink:
			if pkt.data == nil {
				pkt.ready <- struct{}{}
				continue
			}
			handshakeProcessForce = false
		HandshakeProcess:
			if _, exists = peers[pkt.addr]; handshakeProcessForce || !exists {
				peerId = govpn.IDsCache.Find(pkt.data)
				if peerId == nil {
					log.Println("Unknown identity from", pkt.addr)
					pkt.ready <- struct{}{}
					continue
				}
				peerConf = peerId.Conf()
				if peerConf == nil {
					log.Println("Can not get peer configuration", peerId.String())
					pkt.ready <- struct{}{}
					continue
				}
				state, exists = states[pkt.addr]
				if !exists {
					state = govpn.HandshakeNew(pkt.addr, pkt.conn, peerConf)
					states[pkt.addr] = state
				}
				peer = state.Server(pkt.data)
				if peer != nil {
					log.Println("Peer handshake finished", peer)
					if _, exists = peers[pkt.addr]; exists {
						go func() {
							peerReadySink <- PeerReadyEvent{
								peer, peers[pkt.addr].tap.Name,
							}
						}()
					} else {
						go func() {
							upPath := path.Join(govpn.PeersPath, peer.Id.String(), "up.sh")
							result, err := govpn.ScriptCall(upPath, "")
							if err != nil {
								return
							}
							sepIndex := bytes.Index(result, []byte{'\n'})
							if sepIndex < 0 {
								sepIndex = len(result)
							}
							ifaceName := string(result[:sepIndex])
							peerReadySink <- PeerReadyEvent{peer, ifaceName}
						}()
					}
				}
				if !handshakeProcessForce {
					pkt.ready <- struct{}{}
				}
				continue
			}
			peerState, exists = peers[pkt.addr]
			if !exists {
				pkt.ready <- struct{}{}
				continue
			}
			// If it fails during processing, then try to work with it
			// as with handshake packet
			if !peerState.peer.PktProcess(pkt.data, peerState.tap, pkt.ready) {
				handshakeProcessForce = true
				goto HandshakeProcess
			}
		}
	}
}
Example #2
0
func startUDP() {
	bind, err := net.ResolveUDPAddr("udp", *bindAddr)
	if err != nil {
		log.Fatalln("Can not resolve bind address:", err)
	}
	conn, err := net.ListenUDP("udp", bind)
	if err != nil {
		log.Fatalln("Can not listen on UDP:", err)
	}
	log.Println("Listening on UDP:" + *bindAddr)

	udpBufs <- make([]byte, govpn.MTU)
	go func() {
		var buf []byte
		var raddr *net.UDPAddr
		var addr string
		var n int
		var err error
		var ps *PeerState
		var hs *govpn.Handshake
		var addrPrev string
		var exists bool
		var peerId *govpn.PeerId
		var peer *govpn.Peer
		var conf *govpn.PeerConf
		for {
			buf = <-udpBufs
			n, raddr, err = conn.ReadFromUDP(buf)
			if err != nil {
				log.Println("Unexpected error when receiving", err)
				break
			}
			addr = raddr.String()

			peersLock.RLock()
			ps, exists = peers[addr]
			peersLock.RUnlock()
			if !exists {
				goto CheckHandshake
			}
			go func(ps *govpn.Peer, tap *govpn.TAP, buf []byte, n int) {
				peer.PktProcess(buf[:n], tap, true)
				udpBufs <- buf
			}(ps.peer, ps.tap, buf, n)
			continue
		CheckHandshake:
			hsLock.RLock()
			hs, exists = handshakes[addr]
			hsLock.RUnlock()
			if !exists {
				goto CheckID
			}
			peer = hs.Server(buf[:n])
			if peer == nil {
				goto Finished
			}

			log.Println("Peer handshake finished:", addr, peer.Id.String())
			hs.Zero()
			hsLock.Lock()
			delete(handshakes, addr)
			hsLock.Unlock()

			go func() {
				udpBufs <- make([]byte, govpn.MTU)
				udpBufs <- make([]byte, govpn.MTU)
			}()
			peersByIdLock.RLock()
			addrPrev, exists = peersById[*peer.Id]
			peersByIdLock.RUnlock()
			if exists {
				peersLock.Lock()
				peers[addrPrev].terminator <- struct{}{}
				ps = &PeerState{
					peer:       peer,
					tap:        peers[addrPrev].tap,
					terminator: make(chan struct{}),
				}
				go func(ps PeerState) {
					peerReady(ps)
					<-udpBufs
					<-udpBufs
				}(*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 {
				go func(addr string, peer *govpn.Peer) {
					ifaceName, err := callUp(peer.Id)
					if err != nil {
						return
					}
					tap, err := govpn.TAPListen(ifaceName)
					if err != nil {
						log.Println("Unable to create TAP:", err)
						return
					}
					ps = &PeerState{
						peer:       peer,
						tap:        tap,
						terminator: make(chan struct{}),
					}
					go func(ps PeerState) {
						peerReady(ps)
						<-udpBufs
						<-udpBufs
					}(*ps)
					peersLock.Lock()
					peersByIdLock.Lock()
					kpLock.Lock()
					peers[addr] = ps
					knownPeers[addr] = &peer
					peersById[*peer.Id] = addr
					peersLock.Unlock()
					peersByIdLock.Unlock()
					kpLock.Unlock()
					log.Println("Peer created:", peer.Id.String())
				}(addr, peer)
			}
			goto Finished
		CheckID:
			peerId = idsCache.Find(buf[:n])
			if peerId == nil {
				log.Println("Unknown identity from:", addr)
				goto Finished
			}
			conf = confs[*peerId]
			if conf == nil {
				log.Println("Unable to get peer configuration:", peerId.String())
				goto Finished
			}
			hs = govpn.NewHandshake(
				addr,
				UDPSender{conn: conn, addr: raddr},
				conf,
			)
			hs.Server(buf[:n])
			hsLock.Lock()
			handshakes[addr] = hs
			hsLock.Unlock()
		Finished:
			udpBufs <- buf
		}
	}()
}