2 govpn -- simple secure 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 virtual private network daemon
37 "golang.org/x/crypto/poly1305"
38 "golang.org/x/crypto/salsa20"
39 "golang.org/x/crypto/xtea"
43 remoteAddr = flag.String("remote", "", "Remote server address")
44 bindAddr = flag.String("bind", "", "Bind to address")
45 ifaceName = flag.String("iface", "tap0", "TAP network interface")
46 keyPath = flag.String("key", "", "Path to authentication key file")
47 upPath = flag.String("up", "", "Path to up-script")
48 downPath = flag.String("down", "", "Path to down-script")
49 mtu = flag.Int("mtu", 1500, "MTU")
50 nonceDiff = flag.Int("noncediff", 1, "Allow nonce difference")
51 timeoutP = flag.Int("timeout", 60, "Timeout seconds")
52 verboseP = flag.Bool("v", false, "Increase verbosity")
58 // S20BS is Salsa20's internal blocksize in bytes
61 HeartBeatMark = "\x00\x00\x00HEARTBEAT"
62 // Maximal amount of bytes transfered with single key (4 GiB)
63 MaxBytesPerKey = 4294967296
73 key *[KeySize]byte // encryption key
74 nonceOur uint64 // nonce for our messages
75 nonceRecv uint64 // latest received nonce from remote peer
76 nonceCipher *xtea.Cipher // nonce cipher
84 func ScriptCall(path *string) {
88 cmd := exec.Command(*path, *ifaceName)
91 if err := cmd.Run(); err != nil {
92 fmt.Println(time.Now(), "script error: ", err.Error(), string(out.Bytes()))
100 noncediff := uint64(*nonceDiff)
102 log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
105 keyData, err := ioutil.ReadFile(*keyPath)
107 panic("Unable to read keyfile: " + err.Error())
109 if len(keyData) < 64 {
110 panic("Key must be 64 hex characters long")
112 keyDecoded, err := hex.DecodeString(string(keyData[0:64]))
114 panic("Unable to decode the key: " + err.Error())
116 key := new([KeySize]byte)
117 copy(key[:], keyDecoded)
121 // Interface listening
122 maxIfacePktSize := *mtu - poly1305.TagSize - NonceSize
123 log.Println("Max MTU", maxIfacePktSize, "on interface", *ifaceName)
124 iface := NewTAP(*ifaceName)
125 ethBuf := make([]byte, maxIfacePktSize)
126 ethSink := make(chan int)
127 ethSinkReady := make(chan bool)
133 n, err = iface.Read(ethBuf)
142 // Network address parsing
143 if (len(*bindAddr) > 1 && len(*remoteAddr) > 1) ||
144 (len(*bindAddr) == 0 && len(*remoteAddr) == 0) {
145 panic("Either -bind or -remote must be specified only")
147 var conn *net.UDPConn
148 var remote *net.UDPAddr
150 bindTo := "0.0.0.0:0"
152 if len(*bindAddr) > 1 {
157 bind, err := net.ResolveUDPAddr("udp", bindTo)
161 conn, err = net.ListenUDP("udp", bind)
166 if len(*remoteAddr) > 1 {
167 remote, err = net.ResolveUDPAddr("udp", *remoteAddr)
173 udpBuf := make([]byte, *mtu)
174 udpSink := make(chan *UDPPkt)
175 udpSinkReady := make(chan bool)
176 go func(conn *net.UDPConn) {
178 var addr *net.UDPAddr
182 conn.SetReadDeadline(time.Now().Add(time.Second))
183 n, addr, err = conn.ReadFromUDP(udpBuf)
190 udpSink <- &UDPPkt{addr, n}
198 var udpPktData []byte
201 var dataToSend []byte
209 states := make(map[string]*Handshake)
210 nonce := make([]byte, NonceSize)
211 keyAuth := new([KeySize]byte)
212 tag := new([poly1305.TagSize]byte)
213 buf := make([]byte, *mtu+S20BS)
214 emptyKey := make([]byte, KeySize)
217 states[remote.String()] = HandshakeStart(conn, remote, key)
220 heartbeat := time.Tick(time.Second * time.Duration(timeout/3))
221 go func() { <-heartbeat }()
222 heartbeatMark := []byte(HeartBeatMark)
224 termSignal := make(chan os.Signal, 1)
225 signal.Notify(termSignal, os.Interrupt, os.Kill)
232 if !serverMode && bytes > MaxBytesPerKey {
233 states[remote.String()] = HandshakeStart(conn, remote, key)
240 go func() { ethSink <- -1 }()
241 case udpPkt = <-udpSink:
243 if !serverMode && timeouts >= timeout {
250 udpPktData = udpBuf[:udpPkt.size]
251 if isValidHandshakePkt(udpPktData) {
252 addr = udpPkt.addr.String()
253 state, exists := states[addr]
256 state = &Handshake{addr: udpPkt.addr}
259 p = state.Server(noncediff, conn, key, udpPktData)
266 p = state.Client(noncediff, conn, key, udpPktData)
271 go ScriptCall(upPath)
283 copy(buf[:KeySize], emptyKey)
284 copy(tag[:], udpPktData[udpPkt.size-poly1305.TagSize:])
285 copy(buf[S20BS:], udpPktData[NonceSize:udpPkt.size-poly1305.TagSize])
286 salsa20.XORKeyStream(
287 buf[:S20BS+udpPkt.size-poly1305.TagSize],
288 buf[:S20BS+udpPkt.size-poly1305.TagSize],
289 udpPktData[:NonceSize],
292 copy(keyAuth[:], buf[:KeySize])
293 if !poly1305.Verify(tag, udpPktData[:udpPkt.size-poly1305.TagSize], keyAuth) {
298 peer.nonceCipher.Decrypt(buf, udpPktData[:NonceSize])
299 nonceRecv, _ = binary.Uvarint(buf[:NonceSize])
300 if nonceRecv < peer.nonceRecv-noncediff {
306 peer.nonceRecv = nonceRecv
308 frame = buf[S20BS : S20BS+udpPkt.size-NonceSize-poly1305.TagSize]
310 if string(frame[0:HeartBeatSize]) == HeartBeatMark {
313 if _, err = iface.Write(frame); err != nil {
314 log.Println("Error writing to iface: ", err)
319 case ethPktSize = <-ethSink:
320 if ethPktSize > maxIfacePktSize {
321 panic("Too large packet on interface")
328 peer.nonceOur = peer.nonceOur + 2
329 for i := 0; i < NonceSize; i++ {
332 binary.PutUvarint(nonce, peer.nonceOur)
333 peer.nonceCipher.Encrypt(nonce, nonce)
335 copy(buf[:KeySize], emptyKey)
337 copy(buf[S20BS:], ethBuf[:ethPktSize])
340 copy(buf[S20BS:], heartbeatMark)
341 ethPktSize = HeartBeatSize
343 salsa20.XORKeyStream(buf, buf, nonce, peer.key)
344 copy(buf[S20BS-NonceSize:S20BS], nonce)
345 copy(keyAuth[:], buf[:KeySize])
346 dataToSend = buf[S20BS-NonceSize : S20BS+ethPktSize]
347 poly1305.Sum(tag, dataToSend, keyAuth)
348 bytes += len(dataToSend)
349 if _, err = conn.WriteTo(append(dataToSend, tag[:]...), peer.addr); err != nil {
350 log.Println("Error sending UDP", err)