]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/peer.go
Revert lenData=len(data) assignment
[govpn.git] / src / cypherpunks.ru / govpn / peer.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
4
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.
9
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.
14
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/>.
17 */
18
19 package govpn
20
21 import (
22         "bytes"
23         "crypto/subtle"
24         "encoding/binary"
25         "io"
26         "sync"
27         "sync/atomic"
28         "time"
29
30         "chacha20"
31         "github.com/Sirupsen/logrus"
32         "github.com/pkg/errors"
33         "golang.org/x/crypto/blake2b"
34         "golang.org/x/crypto/poly1305"
35 )
36
37 const (
38         // NonceSize is nonce size
39         NonceSize       = 8
40         nonceBucketSize = 256
41         tagSize         = poly1305.TagSize
42         CC20IBS         = 64
43         // MaxBytesPerKey is maximal amount of bytes transferred with single key (4 GiB)
44         MaxBytesPerKey uint64 = 1 << 32
45         // Heartbeat rate, relative to Timeout
46         timeoutHeartbeat = 4
47         // MinPktLength is minimal valid packet length
48         MinPktLength = 1 + 16 + 8
49         // padding byte
50         padByte = byte(0x80)
51
52         logPrefixPeer = "peer_"
53 )
54
55 func newNonces(key *[32]byte, i uint64) (chan *[NonceSize]byte, error) {
56         macKey := make([]byte, 32)
57         chacha20.XORKeyStream(macKey, make([]byte, 32), new([16]byte), key)
58         mac, err := blake2b.New256(macKey)
59         if err != nil {
60                 panic(err)
61         }
62         sum := make([]byte, mac.Size())
63         nonces := make(chan *[NonceSize]byte, nonceBucketSize*3)
64         go func() {
65                 for {
66                         buf := new([NonceSize]byte)
67                         binary.BigEndian.PutUint64(buf[:], i)
68                         mac.Write(buf[:])
69                         mac.Sum(sum[:0])
70                         copy(buf[:], sum)
71                         nonces <- buf
72                         mac.Reset()
73                         i += 2
74                 }
75         }()
76         return nonces, nil
77 }
78
79 // Peer is a GoVPN peer (client)
80 type Peer struct {
81         // Statistics (they are at the beginning for correct int64 alignment)
82         BytesIn         uint64
83         BytesOut        uint64
84         BytesPayloadIn  uint64
85         BytesPayloadOut uint64
86         FramesIn        uint64
87         FramesOut       uint64
88         FramesUnauth    uint64
89         FramesDup       uint64
90         HeartbeatRecv   uint64
91         HeartbeatSent   uint64
92
93         // Basic
94         Addr     string
95         ID       *PeerID
96         Conn     io.Writer `json:"-"`
97         Protocol Protocol
98
99         // Traffic behaviour
100         NoiseEnable bool
101         CPR         int
102         CPRCycle    time.Duration `json:"-"`
103         Encless     bool
104         MTU         int
105
106         key *[SSize]byte
107
108         // Timers
109         Timeout     time.Duration `json:"-"`
110         Established time.Time
111         LastPing    time.Time
112
113         // Receiver
114         BusyR    sync.Mutex `json:"-"`
115         bufR     []byte
116         tagR     *[tagSize]byte
117         keyAuthR *[SSize]byte
118         nonceR   *[16]byte
119         pktSizeR int
120
121         // UDP-related
122         noncesR      chan *[NonceSize]byte
123         nonceRecv    [NonceSize]byte
124         nonceBucketL map[[NonceSize]byte]struct{}
125         nonceBucketM map[[NonceSize]byte]struct{}
126         nonceBucketH map[[NonceSize]byte]struct{}
127
128         // TCP-related
129         NonceExpect  []byte `json:"-"`
130         noncesExpect chan *[NonceSize]byte
131
132         // Transmitter
133         BusyT    sync.Mutex `json:"-"`
134         bufT     []byte
135         tagT     *[tagSize]byte
136         keyAuthT *[SSize]byte
137         nonceT   *[16]byte
138         frameT   []byte
139         noncesT  chan *[NonceSize]byte
140 }
141
142 // LogFields returns a logrus compatible Fields to identity a single
143 // peer in logs
144 func (p *Peer) LogFields() logrus.Fields {
145         return logrus.Fields{
146                 logPrefixPeer + "addr":        p.Addr,
147                 logPrefixPeer + "id":          p.ID.String(),
148                 logPrefixPeer + "established": p.Established.String(),
149                 logPrefixPeer + "last_ping":   p.LastPing.String(),
150         }
151 }
152
153 // ConfigurationLogFields returns a logrus compatible Fields with the
154 // settings of a single peer. Complement LogFields() for extra debugging
155 // details.
156 func (p *Peer) ConfigurationLogFields() logrus.Fields {
157         return logrus.Fields{
158                 logPrefixPeer + "timeout":  p.Timeout.String(),
159                 logPrefixPeer + "protocol": p.Protocol.String(),
160                 logPrefixPeer + "noise":    p.NoiseEnable,
161                 logPrefixPeer + "cpr":      p.CPR,
162                 logPrefixPeer + "mtu":      p.MTU,
163                 logPrefixPeer + "encless":  p.Encless,
164         }
165 }
166
167 func (p *Peer) String() string {
168         return p.ID.String() + ":" + p.Addr
169 }
170
171 // Zero peer's memory state.
172 func (p *Peer) Zero() {
173         p.BusyT.Lock()
174         p.BusyR.Lock()
175         SliceZero(p.key[:])
176         SliceZero(p.bufR)
177         SliceZero(p.bufT)
178         SliceZero(p.keyAuthR[:])
179         SliceZero(p.keyAuthT[:])
180         p.BusyT.Unlock()
181         p.BusyR.Unlock()
182 }
183
184 func cprCycleCalculate(conf *PeerConf) time.Duration {
185         if conf.CPR == 0 {
186                 return time.Duration(0)
187         }
188         rate := conf.CPR * 1 << 10
189         if conf.Encless {
190                 rate /= EnclessEnlargeSize + conf.MTU
191         } else {
192                 rate /= conf.MTU
193         }
194         return time.Second / time.Duration(rate)
195 }
196
197 func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[SSize]byte) (*Peer, error) {
198         now := time.Now()
199         timeout := conf.Timeout
200
201         cprCycle := cprCycleCalculate(conf)
202         noiseEnable := conf.Noise
203         if conf.CPR > 0 {
204                 noiseEnable = true
205                 timeout = cprCycle
206         } else {
207                 timeout = timeout / timeoutHeartbeat
208         }
209
210         bufSize := CC20IBS + 2*conf.MTU
211         if conf.Encless {
212                 bufSize += EnclessEnlargeSize
213                 noiseEnable = true
214         }
215
216         peer := Peer{
217                 Addr: addr,
218                 ID:   conf.ID,
219                 Conn: conn,
220
221                 NoiseEnable: noiseEnable,
222                 CPR:         conf.CPR,
223                 CPRCycle:    cprCycle,
224                 Encless:     conf.Encless,
225                 MTU:         conf.MTU,
226
227                 key: key,
228
229                 Timeout:     timeout,
230                 Established: now,
231                 LastPing:    now,
232
233                 bufR:     make([]byte, bufSize),
234                 bufT:     make([]byte, bufSize),
235                 tagR:     new([tagSize]byte),
236                 tagT:     new([tagSize]byte),
237                 keyAuthR: new([SSize]byte),
238                 nonceR:   new([16]byte),
239                 keyAuthT: new([SSize]byte),
240                 nonceT:   new([16]byte),
241         }
242
243         var err error
244         if isClient {
245                 if peer.noncesT, err = newNonces(peer.key, 1+2); err != nil {
246                         return nil, err
247                 }
248                 if peer.noncesR, err = newNonces(peer.key, 0+2); err != nil {
249                         return nil, err
250                 }
251                 if peer.noncesExpect, err = newNonces(peer.key, 0+2); err != nil {
252                         return nil, err
253                 }
254         } else {
255                 if peer.noncesT, err = newNonces(peer.key, 0+2); err != nil {
256                         return nil, err
257                 }
258                 if peer.noncesR, err = newNonces(peer.key, 1+2); err != nil {
259                         return nil, err
260                 }
261                 if peer.noncesExpect, err = newNonces(peer.key, 1+2); err != nil {
262                         return nil, err
263                 }
264         }
265
266         peer.NonceExpect = make([]byte, NonceSize)
267         nonce := <-peer.noncesExpect
268         copy(peer.NonceExpect, nonce[:])
269
270         var i int
271         peer.nonceBucketL = make(map[[NonceSize]byte]struct{}, nonceBucketSize)
272         for i = 0; i < nonceBucketSize; i++ {
273                 nonce = <-peer.noncesR
274                 peer.nonceBucketL[*nonce] = struct{}{}
275         }
276         peer.nonceBucketM = make(map[[NonceSize]byte]struct{}, nonceBucketSize)
277         for i = 0; i < nonceBucketSize; i++ {
278                 nonce = <-peer.noncesR
279                 peer.nonceBucketM[*nonce] = struct{}{}
280         }
281         peer.nonceBucketH = make(map[[NonceSize]byte]struct{}, nonceBucketSize)
282         for i = 0; i < nonceBucketSize; i++ {
283                 nonce = <-peer.noncesR
284                 peer.nonceBucketH[*nonce] = struct{}{}
285         }
286
287         return &peer, nil
288 }
289
290 // EthProcess processes incoming Ethernet packet.
291 // ready channel is TAPListen's synchronization channel used to tell him
292 // that he is free to receive new packets. Encrypted and authenticated
293 // packets will be sent to remote Peer side immediately.
294 func (p *Peer) EthProcess(data []byte) error {
295         const paddingSize = 1
296         if len(data) > p.MTU-paddingSize {
297                 logger.WithFields(p.LogFields()).WithFields(
298                         p.ConfigurationLogFields(),
299                 ).WithFields(
300                         logrus.Fields{
301                                 "func":        logFuncPrefix + "Peer.EthProcess",
302                                 "padding":     paddingSize,
303                                 "packet_size": len(data),
304                         }).Warning("Ignore padded data packet larger than MTU")
305                 return nil
306         }
307         p.BusyT.Lock()
308         defer p.BusyT.Unlock()
309
310         // Zero size is a heartbeat packet
311         SliceZero(p.bufT)
312         if len(data) == 0 {
313                 p.bufT[CC20IBS+0] = padByte
314                 p.HeartbeatSent++
315         } else {
316                 // Copy payload to our internal buffer and we are ready to
317                 // accept the next one
318                 copy(p.bufT[CC20IBS:], data)
319                 p.bufT[CC20IBS+len(data)] = padByte
320                 p.BytesPayloadOut += uint64(len(data))
321         }
322
323         if p.NoiseEnable && !p.Encless {
324                 p.frameT = p.bufT[CC20IBS : CC20IBS+p.MTU-tagSize]
325         } else if p.Encless {
326                 p.frameT = p.bufT[CC20IBS : CC20IBS+p.MTU]
327         } else {
328                 p.frameT = p.bufT[CC20IBS : CC20IBS+len(data)+1+NonceSize]
329         }
330         copy(p.frameT[len(p.frameT)-NonceSize:], (<-p.noncesT)[:])
331         var out []byte
332         copy(p.nonceT[8:], p.frameT[len(p.frameT)-NonceSize:])
333         if p.Encless {
334                 var err error
335                 out, err = EnclessEncode(p.key, p.nonceT, p.frameT[:len(p.frameT)-NonceSize])
336                 if err != nil {
337                         return errors.Wrap(err, wrapEnclessEncode)
338                 }
339                 out = append(out, p.frameT[len(p.frameT)-NonceSize:]...)
340         } else {
341                 chacha20.XORKeyStream(
342                         p.bufT[:CC20IBS+len(p.frameT)-NonceSize],
343                         p.bufT[:CC20IBS+len(p.frameT)-NonceSize],
344                         p.nonceT,
345                         p.key,
346                 )
347                 copy(p.keyAuthT[:], p.bufT[:SSize])
348                 poly1305.Sum(p.tagT, p.frameT, p.keyAuthT)
349                 atomic.AddUint64(&p.BytesOut, uint64(len(p.frameT)+tagSize))
350                 out = append(p.tagT[:], p.frameT...)
351         }
352         p.FramesOut++
353         _, err := p.Conn.Write(out)
354         return errors.Wrap(err, "p.Conn.Write")
355 }
356
357 // PktProcess processes data of a single packet
358 func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
359         fields := logrus.Fields{
360                 "func":        logFuncPrefix + "Peer.PktProcess",
361                 "reorderable": reorderable,
362                 "data":        len(data),
363         }
364         if len(data) < MinPktLength {
365                 logger.WithFields(p.LogFields()).WithFields(fields).WithField(
366                         "minimum_packet_Length", MinPktLength,
367                 ).Debug("Ignore packet smaller than allowed minimum")
368                 return false
369         }
370         if !p.Encless && len(data) > len(p.bufR)-CC20IBS {
371                 return false
372         }
373         var out []byte
374         p.BusyR.Lock() // TODO use defer to unlock?
375         copy(p.nonceR[8:], data[len(data)-NonceSize:])
376         if p.Encless {
377                 var err error
378                 out, err = EnclessDecode(p.key, p.nonceR, data[:len(data)-NonceSize])
379                 if err != nil {
380                         logger.WithFields(p.LogFields()).WithError(err).Debug("Failed to decode encless")
381                         p.FramesUnauth++
382                         p.BusyR.Unlock()
383                         return false
384                 }
385         } else {
386                 for i := 0; i < SSize; i++ {
387                         p.bufR[i] = 0
388                 }
389                 copy(p.bufR[CC20IBS:], data[tagSize:])
390                 chacha20.XORKeyStream(
391                         p.bufR[:CC20IBS+len(data)-tagSize-NonceSize],
392                         p.bufR[:CC20IBS+len(data)-tagSize-NonceSize],
393                         p.nonceR,
394                         p.key,
395                 )
396                 copy(p.keyAuthR[:], p.bufR[:SSize])
397                 copy(p.tagR[:], data[:tagSize])
398                 if !poly1305.Verify(p.tagR, data[tagSize:], p.keyAuthR) {
399                         p.FramesUnauth++
400                         p.BusyR.Unlock()
401                         return false
402                 }
403                 out = p.bufR[CC20IBS : CC20IBS+len(data)-tagSize-NonceSize]
404         }
405
406         if reorderable {
407                 copy(p.nonceRecv[:], data[len(data)-NonceSize:])
408                 _, foundL := p.nonceBucketL[p.nonceRecv]
409                 _, foundM := p.nonceBucketM[p.nonceRecv]
410                 _, foundH := p.nonceBucketH[p.nonceRecv]
411                 // If found is none of buckets: either it is too old,
412                 // or too new (many packets were lost)
413                 if !(foundL || foundM || foundH) {
414                         p.FramesDup++
415                         p.BusyR.Unlock()
416                         return false
417                 }
418                 // Delete seen nonce
419                 if foundL {
420                         delete(p.nonceBucketL, p.nonceRecv)
421                 }
422                 if foundM {
423                         delete(p.nonceBucketM, p.nonceRecv)
424                 }
425                 if foundH {
426                         delete(p.nonceBucketH, p.nonceRecv)
427                 }
428                 // If we are dealing with the latest bucket, create the new one
429                 if foundH {
430                         p.nonceBucketL, p.nonceBucketM = p.nonceBucketM, p.nonceBucketH
431                         p.nonceBucketH = make(map[[NonceSize]byte]struct{})
432                         var nonce *[NonceSize]byte
433                         for i := 0; i < nonceBucketSize; i++ {
434                                 nonce = <-p.noncesR
435                                 p.nonceBucketH[*nonce] = struct{}{}
436                         }
437                 }
438         } else {
439                 if subtle.ConstantTimeCompare(data[len(data)-NonceSize:], p.NonceExpect) != 1 {
440                         p.FramesDup++
441                         p.BusyR.Unlock()
442                         return false
443                 }
444                 copy(p.NonceExpect, (<-p.noncesExpect)[:])
445         }
446
447         p.FramesIn++
448         atomic.AddUint64(&p.BytesIn, uint64(len(data)))
449         p.LastPing = time.Now()
450         p.pktSizeR = bytes.LastIndexByte(out, padByte)
451         if p.pktSizeR == -1 {
452                 p.BusyR.Unlock()
453                 return false
454         }
455         // Validate the pad
456         for i := p.pktSizeR + 1; i < len(out); i++ {
457                 if out[i] != 0 {
458                         p.BusyR.Unlock()
459                         return false
460                 }
461         }
462
463         if p.pktSizeR == 0 {
464                 p.HeartbeatRecv++
465                 p.BusyR.Unlock()
466                 return true
467         }
468         p.BytesPayloadIn += uint64(p.pktSizeR)
469         tap.Write(out[:p.pktSizeR])
470         p.BusyR.Unlock()
471         return true
472 }
473
474 // PeerTapProcessor processes a TUN/TAP peer
475 func PeerTapProcessor(peer *Peer, tap *TAP, terminator chan struct{}) {
476         var data []byte
477         var now time.Time
478         var err error
479         fields := logrus.Fields{
480                 "func": logFuncPrefix + "PeerTapProcessor",
481                 "tap":  tap.Name,
482         }
483         lastSent := time.Now()
484         heartbeat := time.NewTicker(peer.Timeout)
485         if peer.CPRCycle == time.Duration(0) {
486         RawProcessor:
487                 for {
488                         select {
489                         case <-terminator:
490                                 break RawProcessor
491                         case <-heartbeat.C:
492                                 now = time.Now()
493                                 if lastSent.Add(peer.Timeout).Before(now) {
494                                         if err = peer.EthProcess(nil); err != nil {
495                                                 logger.WithFields(
496                                                         fields,
497                                                 ).WithFields(
498                                                         peer.LogFields(),
499                                                 ).WithError(err).Warn(
500                                                         "Can't process nil ethernet packet",
501                                                 )
502                                         }
503                                         lastSent = now
504                                 }
505                         case data = <-tap.Sink:
506                                 if err = peer.EthProcess(data); err != nil {
507                                         logger.WithFields(fields).WithFields(
508                                                 peer.LogFields(),
509                                         ).WithError(err).Warn("Can't process ethernet packet")
510                                 }
511                                 lastSent = time.Now()
512                         }
513                 }
514         } else {
515         CPRProcessor:
516                 for {
517                         data = nil
518                         select {
519                         case <-terminator:
520                                 break CPRProcessor
521                         case data = <-tap.Sink:
522                                 if err = peer.EthProcess(data); err != nil {
523                                         logger.WithFields(fields).WithFields(
524                                                 peer.LogFields(),
525                                         ).WithError(err).Warn("Can't process ethernet packet")
526                                 }
527                         default:
528                         }
529                         if data == nil {
530                                 if err = peer.EthProcess(nil); err != nil {
531                                         logger.WithFields(fields).WithFields(
532                                                 peer.LogFields(),
533                                         ).WithError(err).Warn("Can't process nil ethernet packet")
534                                 }
535                         }
536                         time.Sleep(peer.CPRCycle)
537                 }
538         }
539         close(terminator)
540         peer.Zero()
541         heartbeat.Stop()
542 }