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/>.
27 "golang.org/x/crypto/poly1305"
28 "golang.org/x/crypto/salsa20"
29 "golang.org/x/crypto/xtea"
35 // S20BS is Salsa20's internal blocksize in bytes
37 // Maximal amount of bytes transfered with single key (4 GiB)
38 MaxBytesPerKey int64 = 1 << 32
39 // Size of packet's size mark in bytes
41 // Heartbeat rate, relative to Timeout
57 CPRCycle time.Duration `json:"-"`
59 // Cryptography related
60 Key *[SSize]byte `json:"-"`
61 NonceOur uint64 `json:"-"`
62 NonceRecv uint64 `json:"-"`
63 NonceCipher *xtea.Cipher `json:"-"`
64 nonceBucket0 map[uint64]struct{}
65 nonceBucket1 map[uint64]struct{}
70 Timeout time.Duration `json:"-"`
74 willSentCycle time.Time
76 // This variables are initialized only once to relief GC
78 tag *[poly1305.TagSize]byte
100 func (p *Peer) String() string {
101 return p.Id.String() + ":" + p.Addr.String()
104 // Zero peer's memory state.
105 func (p *Peer) Zero() {
108 sliceZero(p.keyAuth[:])
115 Emptiness = make([]byte, 1<<14)
116 taps = make(map[string]*TAP)
119 // Create TAP listening goroutine.
120 // This function takes required TAP interface name, opens it and allocates
121 // a buffer where all frame data will be written, channel where information
122 // about number of read bytes is sent to, synchronization channel (external
123 // processes tell that read buffer can be used again) and possible channel
125 func TAPListen(ifaceName string, timeout time.Duration, cpr int) (*TAP, chan []byte, chan struct{}, chan struct{}, error) {
128 tap, exists := taps[ifaceName]
130 tap, err = NewTAP(ifaceName)
132 return nil, nil, nil, nil, err
134 taps[ifaceName] = tap
136 sink := make(chan []byte)
137 sinkReady := make(chan struct{})
138 sinkTerminate := make(chan struct{})
139 sinkSkip := make(chan struct{})
142 cprCycle := cprCycleCalculate(cpr)
143 if cprCycle != time.Duration(0) {
146 timeout = timeout / TimeoutHeartbeat
148 heartbeat := time.Tick(timeout)
153 case <-sinkTerminate:
156 go func() { sink <- make([]byte, 0) }()
160 tap.ready <- struct{}{}
166 go func() { sink <- make([]byte, 0) }()
167 goto HeartbeatCatched
168 case <-sinkTerminate:
170 case pkt = <-tap.sink:
179 if exists && tap.synced {
180 sinkSkip <- struct{}{}
182 sinkReady <- struct{}{}
184 return tap, sink, sinkReady, sinkTerminate, nil
187 // Create UDP listening goroutine.
188 // This function takes already listening UDP socket and a buffer where
189 // all UDP packet data will be saved, channel where information about
190 // remote address and number of written bytes are stored, and a channel
191 // used to tell that buffer is ready to be overwritten.
192 func ConnListen(conn *net.UDPConn) (chan UDPPkt, []byte, chan struct{}) {
193 buf := make([]byte, MTU)
194 sink := make(chan UDPPkt)
195 sinkReady := make(chan struct{})
196 go func(conn *net.UDPConn) {
198 var addr *net.UDPAddr
202 conn.SetReadDeadline(time.Now().Add(time.Second))
203 n, addr, err = conn.ReadFromUDP(buf)
205 // This is needed for ticking the timeouts counter outside
206 sink <- UDPPkt{nil, 0}
209 sink <- UDPPkt{addr, n}
212 sinkReady <- struct{}{}
213 return sink, buf, sinkReady
216 func newNonceCipher(key *[32]byte) *xtea.Cipher {
217 nonceKey := make([]byte, 16)
218 salsa20.XORKeyStream(
221 make([]byte, xtea.BlockSize),
224 ciph, err := xtea.NewCipher(nonceKey)
231 func cprCycleCalculate(rate int) time.Duration {
233 return time.Duration(0)
235 return time.Second / time.Duration(rate*(1<<10)/MTU)
238 func newPeer(addr *net.UDPAddr, conf *PeerConf, nonce int, key *[SSize]byte) *Peer {
240 timeout := conf.Timeout
241 cprCycle := cprCycleCalculate(conf.CPR)
242 noiseEnable := conf.NoiseEnable
247 timeout = timeout / TimeoutHeartbeat
255 NoiseEnable: noiseEnable,
258 NonceOur: uint64(nonce),
259 NonceRecv: uint64(0),
260 nonceBucket0: make(map[uint64]struct{}, NonceBucketSize),
261 nonceBucket1: make(map[uint64]struct{}, NonceBucketSize),
263 NonceCipher: newNonceCipher(key),
264 buf: make([]byte, MTU+S20BS),
265 tag: new([poly1305.TagSize]byte),
266 keyAuth: new([SSize]byte),
267 nonce: make([]byte, NonceSize),
272 // Process incoming UDP packet.
273 // udpPkt is received data, related to the peer tap interface and
274 // ConnListen'es synchronization channel used to tell him that he is
275 // free to receive new packets. Authenticated and decrypted packets
276 // will be written to the interface immediately (except heartbeat ones).
277 func (p *Peer) UDPProcess(udpPkt []byte, tap io.Writer, ready chan struct{}) bool {
279 copy(p.buf, Emptiness)
280 copy(p.tag[:], udpPkt[p.size-poly1305.TagSize:])
281 copy(p.buf[S20BS:], udpPkt[NonceSize:p.size-poly1305.TagSize])
282 salsa20.XORKeyStream(
283 p.buf[:S20BS+p.size-poly1305.TagSize],
284 p.buf[:S20BS+p.size-poly1305.TagSize],
288 copy(p.keyAuth[:], p.buf[:SSize])
289 if !poly1305.Verify(p.tag, udpPkt[:p.size-poly1305.TagSize], p.keyAuth) {
295 // Check if received nonce is known to us in either of two buckets.
296 // If yes, then this is ignored duplicate.
297 // Check from the oldest bucket, as in most cases this will result
298 // in constant time check.
299 // If Bucket0 is filled, then it becomes Bucket1.
300 p.NonceCipher.Decrypt(p.buf, udpPkt[:NonceSize])
302 p.nonceRecv, _ = binary.Uvarint(p.buf[:NonceSize])
303 if _, p.nonceFound = p.nonceBucket1[p.NonceRecv]; p.nonceFound {
307 if _, p.nonceFound = p.nonceBucket0[p.NonceRecv]; p.nonceFound {
311 p.nonceBucket0[p.NonceRecv] = struct{}{}
313 if p.nonceBucketN == NonceBucketSize {
314 p.nonceBucket1 = p.nonceBucket0
315 p.nonceBucket0 = make(map[uint64]struct{}, NonceBucketSize)
320 p.BytesIn += int64(p.size)
321 p.LastPing = time.Now()
322 p.NonceRecv = p.nonceRecv
323 p.pktSize, _ = binary.Uvarint(p.buf[S20BS : S20BS+PktSizeSize])
328 p.frame = p.buf[S20BS+PktSizeSize : S20BS+PktSizeSize+p.pktSize]
329 p.BytesPayloadIn += int64(p.pktSize)
334 type WriteToUDPer interface {
335 WriteToUDP([]byte, *net.UDPAddr) (int, error)
338 // Process incoming Ethernet packet.
339 // ethPkt is received data, conn is our outgoing connection.
340 // ready channel is TAPListen's synchronization channel used to tell him
341 // that he is free to receive new packets. Encrypted and authenticated
342 // packets will be sent to remote Peer side immediately.
343 func (p *Peer) EthProcess(ethPkt []byte, conn WriteToUDPer, ready chan struct{}) {
346 // If this heartbeat is necessary
347 if p.size == 0 && !p.LastSent.Add(p.Timeout).Before(p.now) {
350 copy(p.buf, Emptiness)
352 copy(p.buf[S20BS+PktSizeSize:], ethPkt)
354 binary.PutUvarint(p.buf[S20BS:S20BS+PktSizeSize], uint64(p.size))
355 p.BytesPayloadOut += int64(p.size)
361 copy(p.nonce, Emptiness)
362 binary.PutUvarint(p.nonce, p.NonceOur)
363 p.NonceCipher.Encrypt(p.nonce, p.nonce)
365 salsa20.XORKeyStream(p.buf, p.buf, p.nonce, p.Key)
366 copy(p.buf[S20BS-NonceSize:S20BS], p.nonce)
367 copy(p.keyAuth[:], p.buf[:SSize])
369 p.frame = p.buf[S20BS-NonceSize : S20BS+MTU-NonceSize-poly1305.TagSize]
371 p.frame = p.buf[S20BS-NonceSize : S20BS+PktSizeSize+p.size]
373 poly1305.Sum(p.tag, p.frame, p.keyAuth)
375 p.BytesOut += int64(len(p.frame) + poly1305.TagSize)
378 if p.CPRCycle != time.Duration(0) {
379 p.willSentCycle = p.LastSent.Add(p.CPRCycle)
380 if p.willSentCycle.After(p.now) {
381 time.Sleep(p.willSentCycle.Sub(p.now))
382 p.now = p.willSentCycle
386 conn.WriteToUDP(append(p.frame, p.tag[:]...), p.Addr)