]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/peer.go
989fd31ef1720deedd0ccd88c90de7fed81c336d
[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(
298                         p.LogFields(),
299                 ).WithFields(
300                         p.ConfigurationLogFields(),
301                 ).WithFields(
302                         logrus.Fields{
303                                 "func":        logFuncPrefix + "Peer.EthProcess",
304                                 "padding":     paddingSize,
305                                 "packet_size": len(data),
306                         },
307                 ).Warning("Ignore padded data packet larger than MTU")
308                 return nil
309         }
310         p.BusyT.Lock()
311         defer p.BusyT.Unlock()
312
313         // Zero size is a heartbeat packet
314         SliceZero(p.bufT)
315         if len(data) == 0 {
316                 p.bufT[CC20IBS+0] = padByte
317                 p.HeartbeatSent++
318         } else {
319                 // Copy payload to our internal buffer and we are ready to
320                 // accept the next one
321                 copy(p.bufT[CC20IBS:], data)
322                 p.bufT[CC20IBS+len(data)] = padByte
323                 p.BytesPayloadOut += uint64(len(data))
324         }
325
326         if p.NoiseEnable && !p.Encless {
327                 p.frameT = p.bufT[CC20IBS : CC20IBS+p.MTU-tagSize]
328         } else if p.Encless {
329                 p.frameT = p.bufT[CC20IBS : CC20IBS+p.MTU]
330         } else {
331                 p.frameT = p.bufT[CC20IBS : CC20IBS+len(data)+1+NonceSize]
332         }
333         copy(p.frameT[len(p.frameT)-NonceSize:], (<-p.noncesT)[:])
334         var out []byte
335         copy(p.nonceT[8:], p.frameT[len(p.frameT)-NonceSize:])
336         if p.Encless {
337                 var err error
338                 out, err = EnclessEncode(p.key, p.nonceT, p.frameT[:len(p.frameT)-NonceSize])
339                 if err != nil {
340                         return errors.Wrap(err, wrapEnclessEncode)
341                 }
342                 out = append(out, p.frameT[len(p.frameT)-NonceSize:]...)
343         } else {
344                 chacha20.XORKeyStream(
345                         p.bufT[:CC20IBS+len(p.frameT)-NonceSize],
346                         p.bufT[:CC20IBS+len(p.frameT)-NonceSize],
347                         p.nonceT,
348                         p.key,
349                 )
350                 copy(p.keyAuthT[:], p.bufT[:SSize])
351                 poly1305.Sum(p.tagT, p.frameT, p.keyAuthT)
352                 atomic.AddUint64(&p.BytesOut, uint64(len(p.frameT)+tagSize))
353                 out = append(p.tagT[:], p.frameT...)
354         }
355         p.FramesOut++
356         _, err := p.Conn.Write(out)
357         return errors.Wrap(err, "p.Conn.Write")
358 }
359
360 // PktProcess processes data of a single packet
361 func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
362         fields := logrus.Fields{
363                 "func":        logFuncPrefix + "Peer.PktProcess",
364                 "reorderable": reorderable,
365                 "data":        len(data),
366         }
367         if len(data) < MinPktLength {
368                 logger.WithFields(
369                         p.LogFields(),
370                 ).WithFields(
371                         fields,
372                 ).WithField(
373                         "minimum_packet_Length",
374                         MinPktLength,
375                 ).Debug("Ignore packet smaller than allowed minimum")
376                 return false
377         }
378         if !p.Encless && len(data) > len(p.bufR)-CC20IBS {
379                 return false
380         }
381         var out []byte
382         p.BusyR.Lock()
383         defer p.BusyR.Unlock()
384         copy(p.nonceR[8:], data[len(data)-NonceSize:])
385         if p.Encless {
386                 var err error
387                 out, err = EnclessDecode(p.key, p.nonceR, data[:len(data)-NonceSize])
388                 if err != nil {
389                         logger.WithFields(
390                                 p.LogFields(),
391                         ).WithError(err).Debug("Failed to decode encless")
392                         p.FramesUnauth++
393                         return false
394                 }
395         } else {
396                 for i := 0; i < SSize; i++ {
397                         p.bufR[i] = 0
398                 }
399                 copy(p.bufR[CC20IBS:], data[tagSize:])
400                 chacha20.XORKeyStream(
401                         p.bufR[:CC20IBS+len(data)-tagSize-NonceSize],
402                         p.bufR[:CC20IBS+len(data)-tagSize-NonceSize],
403                         p.nonceR,
404                         p.key,
405                 )
406                 copy(p.keyAuthR[:], p.bufR[:SSize])
407                 copy(p.tagR[:], data[:tagSize])
408                 if !poly1305.Verify(p.tagR, data[tagSize:], p.keyAuthR) {
409                         p.FramesUnauth++
410                         return false
411                 }
412                 out = p.bufR[CC20IBS : CC20IBS+len(data)-tagSize-NonceSize]
413         }
414
415         if reorderable {
416                 copy(p.nonceRecv[:], data[len(data)-NonceSize:])
417                 _, foundL := p.nonceBucketL[p.nonceRecv]
418                 _, foundM := p.nonceBucketM[p.nonceRecv]
419                 _, foundH := p.nonceBucketH[p.nonceRecv]
420                 // If found is none of buckets: either it is too old,
421                 // or too new (many packets were lost)
422                 if !(foundL || foundM || foundH) {
423                         p.FramesDup++
424                         return false
425                 }
426                 // Delete seen nonce
427                 if foundL {
428                         delete(p.nonceBucketL, p.nonceRecv)
429                 }
430                 if foundM {
431                         delete(p.nonceBucketM, p.nonceRecv)
432                 }
433                 if foundH {
434                         delete(p.nonceBucketH, p.nonceRecv)
435                 }
436                 // If we are dealing with the latest bucket, create the new one
437                 if foundH {
438                         p.nonceBucketL, p.nonceBucketM = p.nonceBucketM, p.nonceBucketH
439                         p.nonceBucketH = make(map[[NonceSize]byte]struct{})
440                         var nonce *[NonceSize]byte
441                         for i := 0; i < nonceBucketSize; i++ {
442                                 nonce = <-p.noncesR
443                                 p.nonceBucketH[*nonce] = struct{}{}
444                         }
445                 }
446         } else {
447                 if subtle.ConstantTimeCompare(data[len(data)-NonceSize:], p.NonceExpect) != 1 {
448                         p.FramesDup++
449                         return false
450                 }
451                 copy(p.NonceExpect, (<-p.noncesExpect)[:])
452         }
453
454         p.FramesIn++
455         atomic.AddUint64(&p.BytesIn, uint64(len(data)))
456         p.LastPing = time.Now()
457         p.pktSizeR = bytes.LastIndexByte(out, padByte)
458         if p.pktSizeR == -1 {
459                 return false
460         }
461         // Validate the pad
462         for i := p.pktSizeR + 1; i < len(out); i++ {
463                 if out[i] != 0 {
464                         return false
465                 }
466         }
467
468         if p.pktSizeR == 0 {
469                 p.HeartbeatRecv++
470                 return true
471         }
472         p.BytesPayloadIn += uint64(p.pktSizeR)
473         tap.Write(out[:p.pktSizeR])
474         return true
475 }
476
477 // PeerTapProcessor processes a TUN/TAP peer
478 func PeerTapProcessor(peer *Peer, tap *TAP, terminator chan struct{}) {
479         var data []byte
480         var now time.Time
481         var err error
482         fields := logrus.Fields{
483                 "func": logFuncPrefix + "PeerTapProcessor",
484                 "tap":  tap.Name,
485         }
486         lastSent := time.Now()
487         heartbeat := time.NewTicker(peer.Timeout)
488         if peer.CPRCycle == time.Duration(0) {
489         RawProcessor:
490                 for {
491                         select {
492                         case <-terminator:
493                                 break RawProcessor
494                         case <-heartbeat.C:
495                                 now = time.Now()
496                                 if lastSent.Add(peer.Timeout).Before(now) {
497                                         if err = peer.EthProcess(nil); err != nil {
498                                                 logger.WithFields(
499                                                         fields,
500                                                 ).WithFields(
501                                                         peer.LogFields(),
502                                                 ).WithError(err).Warn(
503                                                         "Can't process nil ethernet packet",
504                                                 )
505                                         }
506                                         lastSent = now
507                                 }
508                         case data = <-tap.Sink:
509                                 if err = peer.EthProcess(data); err != nil {
510                                         logger.WithFields(
511                                                 fields,
512                                         ).WithFields(
513                                                 peer.LogFields(),
514                                         ).WithError(err).Warn("Can't process ethernet packet")
515                                 }
516                                 lastSent = time.Now()
517                         }
518                 }
519         } else {
520         CPRProcessor:
521                 for {
522                         data = nil
523                         select {
524                         case <-terminator:
525                                 break CPRProcessor
526                         case data = <-tap.Sink:
527                                 if err = peer.EthProcess(data); err != nil {
528                                         logger.WithFields(
529                                                 fields,
530                                         ).WithFields(
531                                                 peer.LogFields(),
532                                         ).WithError(err).Warn("Can't process ethernet packet")
533                                 }
534                         default:
535                         }
536                         if data == nil {
537                                 if err = peer.EthProcess(nil); err != nil {
538                                         logger.WithFields(
539                                                 fields,
540                                         ).WithFields(
541                                                 peer.LogFields(),
542                                         ).WithError(err).Warn("Can't process nil ethernet packet")
543                                 }
544                         }
545                         time.Sleep(peer.CPRCycle)
546                 }
547         }
548         close(terminator)
549         peer.Zero()
550         heartbeat.Stop()
551 }