2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2015 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 // Simple secure free software virtual private network daemon client.
34 remoteAddr = flag.String("remote", "", "Remote server address")
35 ifaceName = flag.String("iface", "tap0", "TAP network interface")
36 IDRaw = flag.String("id", "", "Client identification")
37 keyPath = flag.String("key", "", "Path to passphrase file")
38 upPath = flag.String("up", "", "Path to up-script")
39 downPath = flag.String("down", "", "Path to down-script")
40 stats = flag.String("stats", "", "Enable stats retrieving on host:port")
41 mtu = flag.Int("mtu", 1452, "MTU for outgoing packets")
42 nonceDiff = flag.Int("noncediff", 1, "Allow nonce difference")
43 timeoutP = flag.Int("timeout", 60, "Timeout seconds")
44 noisy = flag.Bool("noise", false, "Enable noise appending")
45 cpr = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate")
46 egdPath = flag.String("egd", "", "Optional path to EGD socket")
53 log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
57 id, err := govpn.IDDecode(*IDRaw)
63 log.Println("Using", *egdPath, "EGD")
64 govpn.EGDInit(*egdPath)
67 pub, priv := govpn.NewVerifier(id, govpn.StringFromFile(*keyPath))
68 conf := &govpn.PeerConf{
70 Timeout: time.Second * time.Duration(timeout),
71 Noncediff: *nonceDiff,
77 govpn.PeersInitDummy(id, conf)
79 bind, err := net.ResolveUDPAddr("udp", "0.0.0.0:0")
81 log.Fatalln("Can not resolve address:", err)
83 conn, err := net.ListenUDP("udp", bind)
85 log.Fatalln("Can not listen on UDP:", err)
87 remote, err := net.ResolveUDPAddr("udp", *remoteAddr)
89 log.Fatalln("Can not resolve remote address:", err)
92 tap, ethSink, ethReady, _, err := govpn.TAPListen(
94 time.Second*time.Duration(timeout),
98 log.Fatalln("Can not listen on TAP interface:", err)
100 udpSink, udpBuf, udpReady := govpn.ConnListen(conn)
106 var udpPkt govpn.UDPPkt
107 var udpPktData []byte
108 knownPeers := govpn.KnownPeers(map[string]**govpn.Peer{remote.String(): &peer})
110 log.Println(govpn.VersionGet())
111 log.Println("Max MTU on TAP interface:", govpn.TAPMaxMTU())
113 log.Println("Stats are going to listen on", *stats)
114 statsPort, err := net.Listen("tcp", *stats)
116 log.Fatalln("Can not listen on stats port:", err)
118 go govpn.StatsProcessor(statsPort, &knownPeers)
121 termSignal := make(chan os.Signal, 1)
122 signal.Notify(termSignal, os.Interrupt, os.Kill)
124 log.Println("Starting handshake")
125 handshake := govpn.HandshakeStart(conf, conn, remote)
129 if peer != nil && (peer.BytesIn+peer.BytesOut) > govpn.MaxBytesPerKey {
132 handshake = govpn.HandshakeStart(conf, conn, remote)
133 log.Println("Rehandshaking")
138 case ethPkt = <-ethSink:
141 ethReady <- struct{}{}
145 peer.EthProcess(ethPkt, conn, ethReady)
146 case udpPkt = <-udpSink:
148 if timeouts >= timeout {
151 if udpPkt.Addr == nil {
152 udpReady <- struct{}{}
156 udpPktData = udpBuf[:udpPkt.Size]
158 if udpPkt.Addr.String() != remote.String() {
159 udpReady <- struct{}{}
160 log.Println("Unknown handshake message")
163 if govpn.IDsCache.Find(udpPktData) == nil {
164 log.Println("Invalid identity in handshake packet")
165 udpReady <- struct{}{}
168 if p := handshake.Client(conn, udpPktData); p != nil {
169 log.Println("Handshake completed")
171 go govpn.ScriptCall(*upPath, *ifaceName)
178 udpReady <- struct{}{}
182 udpReady <- struct{}{}
185 if peer.UDPProcess(udpPktData, tap, udpReady) {
190 govpn.ScriptCall(*downPath, *ifaceName)