func main() { flag.Parse() timeout := time.Second * time.Duration(govpn.TimeoutDefault) log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile) log.Println(govpn.VersionGet()) confInit() knownPeers = govpn.KnownPeers(make(map[string]**govpn.Peer)) if *egdPath != "" { log.Println("Using", *egdPath, "EGD") govpn.EGDInit(*egdPath) } switch *proto { case "udp": startUDP() case "tcp": startTCP() case "all": startUDP() startTCP() 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 }() 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() } log.Println("Server started") var needsDeletion bool MainCycle: for { select { case <-termSignal: break MainCycle case <-hsHeartbeat: now := time.Now() hsLock.Lock() for addr, hs := range handshakes { if hs.LastPing.Add(timeout).Before(now) { log.Println("Deleting handshake state", addr) hs.Zero() delete(handshakes, addr) } } peersLock.Lock() peersByIdLock.Lock() kpLock.Lock() for addr, ps := range peers { ps.peer.BusyR.Lock() needsDeletion = ps.peer.LastPing.Add(timeout).Before(now) ps.peer.BusyR.Unlock() if needsDeletion { log.Println("Deleting peer", ps.peer) delete(peers, addr) delete(knownPeers, addr) delete(peersById, *ps.peer.Id) go govpn.ScriptCall( confs[*ps.peer.Id].Down, ps.tap.Name, ) ps.terminator <- struct{}{} } } hsLock.Unlock() peersLock.Unlock() peersByIdLock.Unlock() kpLock.Unlock() } } }
func main() { flag.Parse() timeout = *timeoutP var err error log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile) if *mtu > govpn.MTUMax { log.Fatalln("Maximum allowable MTU is", govpn.MTUMax) } if *egdPath != "" { log.Println("Using", *egdPath, "EGD") govpn.EGDInit(*egdPath) } if *verifierRaw == "" { log.Fatalln("No verifier specified") } verifier, err := govpn.VerifierFromString(*verifierRaw) if err != nil { log.Fatalln(err) } key, err := govpn.KeyRead(*keyPath) if err != nil { log.Fatalln("Unable to read the key", err) } priv := verifier.PasswordApply(key) if *encless { if *proto != "tcp" { log.Fatalln("Currently encryptionless mode works only with TCP") } *noisy = true } conf = &govpn.PeerConf{ Id: verifier.Id, Iface: *ifaceName, MTU: *mtu, Timeout: time.Second * time.Duration(timeout), TimeSync: *timeSync, Noise: *noisy, CPR: *cpr, Encless: *encless, Verifier: verifier, DSAPriv: priv, } idsCache = govpn.NewCipherCache() confs := map[govpn.PeerId]*govpn.PeerConf{*verifier.Id: conf} idsCache.Update(&confs) log.Println(govpn.VersionGet()) tap, err = govpn.TAPListen(*ifaceName, *mtu) if err != nil { log.Fatalln("Can not listen on TAP interface:", err) } 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) } termSignal := make(chan os.Signal, 1) signal.Notify(termSignal, os.Interrupt, os.Kill) MainCycle: for { timeouted := make(chan struct{}) rehandshaking := make(chan struct{}) termination := make(chan struct{}) if *proxyAddr != "" { *proto = "tcp" } switch *proto { case "udp": go startUDP(timeouted, rehandshaking, termination) case "tcp": if *proxyAddr != "" { go proxyTCP(timeouted, rehandshaking, termination) } else { go startTCP(timeouted, rehandshaking, termination) } default: log.Fatalln("Unknown protocol specified") } select { case <-termSignal: log.Fatalln("Finishing") termination <- struct{}{} break MainCycle case <-timeouted: break MainCycle case <-rehandshaking: } close(timeouted) close(rehandshaking) close(termination) } govpn.ScriptCall(*downPath, *ifaceName) }
func handleTCP(conn *net.TCPConn, timeouted, rehandshaking, termination chan struct{}) { hs := govpn.HandshakeStart(*remoteAddr, conn, conf) buf := make([]byte, 2*(govpn.EnclessEnlargeSize+*mtu)+*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 == len(buf) { 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 == len(buf) { 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.LoadUint64(&peer.BytesIn)+atomic.LoadUint64(&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() }