2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2016 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/>.
31 "github.com/Sirupsen/logrus"
32 "github.com/pkg/errors"
33 "golang.org/x/crypto/blake2b"
34 "golang.org/x/crypto/poly1305"
38 // NonceSize is nonce size
41 tagSize = poly1305.TagSize
42 chacha20InternalBlockSize = 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
47 // MinPktLength is minimal valid packet length
48 MinPktLength = 1 + 16 + 8
52 logPrefixPeer = "peer_"
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)
62 sum := make([]byte, mac.Size())
63 nonces := make(chan *[NonceSize]byte, nonceBucketSize*3)
66 buf := new([NonceSize]byte)
67 binary.BigEndian.PutUint64(buf[:], i)
79 // Peer is a GoVPN peer (client)
81 // Statistics (they are at the beginning for correct int64 alignment)
85 BytesPayloadOut uint64
96 Conn io.Writer `json:"-"`
102 CPRCycle time.Duration `json:"-"`
109 Timeout time.Duration `json:"-"`
110 Established time.Time
114 BusyR sync.Mutex `json:"-"`
117 keyAuthR *[SSize]byte
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{}
129 NonceExpect []byte `json:"-"`
130 noncesExpect chan *[NonceSize]byte
133 BusyT sync.Mutex `json:"-"`
136 keyAuthT *[SSize]byte
139 noncesT chan *[NonceSize]byte
142 // LogFields return a logrus compatible Fields to identity a single peer in logs
143 func (p *Peer) LogFields() logrus.Fields {
144 return logrus.Fields{
145 logPrefixPeer + "addr": p.Addr,
146 logPrefixPeer + "id": p.ID.String(),
147 logPrefixPeer + "established": p.Established.String(),
148 logPrefixPeer + "last_ping": p.LastPing.String(),
152 // ConfigurationLogFields return a logrus compatible Fields with the settings of
153 // a single peer. Complement LogFields() for extra debugging details.
154 func (p *Peer) ConfigurationLogFields() logrus.Fields {
155 return logrus.Fields{
156 logPrefixPeer + "timeout": p.Timeout.String(),
157 logPrefixPeer + "protocol": p.Protocol.String(),
158 logPrefixPeer + "noise": p.NoiseEnable,
159 logPrefixPeer + "cpr": p.CPR,
160 logPrefixPeer + "mtu": p.MTU,
161 logPrefixPeer + "encless": p.Encless,
165 func (p *Peer) String() string {
166 return p.ID.String() + ":" + p.Addr
169 // Zero peer's memory state.
170 func (p *Peer) Zero() {
176 SliceZero(p.keyAuthR[:])
177 SliceZero(p.keyAuthT[:])
182 func cprCycleCalculate(conf *PeerConf) time.Duration {
184 return time.Duration(0)
186 rate := conf.CPR * 1 << 10
188 rate /= EnclessEnlargeSize + conf.MTU
192 return time.Second / time.Duration(rate)
195 func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[SSize]byte) (*Peer, error) {
197 timeout := conf.Timeout
199 cprCycle := cprCycleCalculate(conf)
200 noiseEnable := conf.Noise
205 timeout = timeout / timeoutHeartbeat
208 bufSize := chacha20InternalBlockSize + 2*conf.MTU
210 bufSize += EnclessEnlargeSize
219 NoiseEnable: noiseEnable,
222 Encless: conf.Encless,
231 bufR: make([]byte, bufSize),
232 bufT: make([]byte, bufSize),
233 tagR: new([tagSize]byte),
234 tagT: new([tagSize]byte),
235 keyAuthR: new([SSize]byte),
236 nonceR: new([16]byte),
237 keyAuthT: new([SSize]byte),
238 nonceT: new([16]byte),
243 if peer.noncesT, err = newNonces(peer.key, 1+2); err != nil {
246 if peer.noncesR, err = newNonces(peer.key, 0+2); err != nil {
249 if peer.noncesExpect, err = newNonces(peer.key, 0+2); err != nil {
253 if peer.noncesT, err = newNonces(peer.key, 0+2); err != nil {
256 if peer.noncesR, err = newNonces(peer.key, 1+2); err != nil {
259 if peer.noncesExpect, err = newNonces(peer.key, 1+2); err != nil {
264 peer.NonceExpect = make([]byte, NonceSize)
265 nonce := <-peer.noncesExpect
266 copy(peer.NonceExpect, nonce[:])
269 peer.nonceBucketL = make(map[[NonceSize]byte]struct{}, nonceBucketSize)
270 for i = 0; i < nonceBucketSize; i++ {
271 nonce = <-peer.noncesR
272 peer.nonceBucketL[*nonce] = struct{}{}
274 peer.nonceBucketM = make(map[[NonceSize]byte]struct{}, nonceBucketSize)
275 for i = 0; i < nonceBucketSize; i++ {
276 nonce = <-peer.noncesR
277 peer.nonceBucketM[*nonce] = struct{}{}
279 peer.nonceBucketH = make(map[[NonceSize]byte]struct{}, nonceBucketSize)
280 for i = 0; i < nonceBucketSize; i++ {
281 nonce = <-peer.noncesR
282 peer.nonceBucketH[*nonce] = struct{}{}
288 // EthProcess processes incoming Ethernet packet.
289 // ready channel is TAPListen's synchronization channel used to tell him
290 // that he is free to receive new packets. Encrypted and authenticated
291 // packets will be sent to remote Peer side immediately.
292 func (p *Peer) EthProcess(data []byte) error {
293 const paddingSize = 1
295 if lenData > p.MTU-paddingSize {
296 logger.WithFields(p.LogFields()).WithFields(p.ConfigurationLogFields()).WithFields(
298 "func": logFuncPrefix + "Peer.EthProcess",
299 "padding": paddingSize,
300 "packet_size": lenData,
301 }).Warning("Ignore padded data packet larger than MTU")
305 defer p.BusyT.Unlock()
307 // Zero size is a heartbeat packet
310 p.bufT[chacha20InternalBlockSize+0] = padByte
313 // Copy payload to our internal buffer and we are ready to
314 // accept the next one
315 copy(p.bufT[chacha20InternalBlockSize:], data)
316 p.bufT[chacha20InternalBlockSize+lenData] = padByte
317 p.BytesPayloadOut += uint64(lenData)
320 if p.NoiseEnable && !p.Encless {
321 p.frameT = p.bufT[chacha20InternalBlockSize : chacha20InternalBlockSize+p.MTU-tagSize]
322 } else if p.Encless {
323 p.frameT = p.bufT[chacha20InternalBlockSize : chacha20InternalBlockSize+p.MTU]
325 p.frameT = p.bufT[chacha20InternalBlockSize : chacha20InternalBlockSize+lenData+1+NonceSize]
327 copy(p.frameT[len(p.frameT)-NonceSize:], (<-p.noncesT)[:])
329 copy(p.nonceT[8:], p.frameT[len(p.frameT)-NonceSize:])
332 out, err = EnclessEncode(p.key, p.nonceT, p.frameT[:len(p.frameT)-NonceSize])
334 return errors.Wrap(err, wrapEnclessEncode)
336 out = append(out, p.frameT[len(p.frameT)-NonceSize:]...)
338 chacha20.XORKeyStream(
339 p.bufT[:chacha20InternalBlockSize+len(p.frameT)-NonceSize],
340 p.bufT[:chacha20InternalBlockSize+len(p.frameT)-NonceSize],
344 copy(p.keyAuthT[:], p.bufT[:SSize])
345 poly1305.Sum(p.tagT, p.frameT, p.keyAuthT)
346 atomic.AddUint64(&p.BytesOut, uint64(len(p.frameT)+tagSize))
347 out = append(p.tagT[:], p.frameT...)
350 _, err := p.Conn.Write(out)
351 return errors.Wrap(err, "p.Conn.Write")
354 // PktProcess processes data of a single packet
355 func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
357 fields := logrus.Fields{
358 "func": logFuncPrefix + "Peer.PktProcess",
359 "reorderable": reorderable,
362 if lenData < MinPktLength {
363 logger.WithFields(p.LogFields()).WithFields(fields).WithField("minimum_packet_Length", MinPktLength).Debug("Ignore packet smaller than allowed minimum")
366 if !p.Encless && lenData > len(p.bufR)-chacha20InternalBlockSize {
370 p.BusyR.Lock() // TODO use defer to unlock?
371 copy(p.nonceR[8:], data[lenData-NonceSize:])
374 out, err = EnclessDecode(p.key, p.nonceR, data[:lenData-NonceSize])
376 logger.WithFields(p.LogFields()).WithError(err).Debug("Failed to decode encless")
382 for i := 0; i < SSize; i++ {
385 copy(p.bufR[chacha20InternalBlockSize:], data[tagSize:])
386 chacha20.XORKeyStream(
387 p.bufR[:chacha20InternalBlockSize+lenData-tagSize-NonceSize],
388 p.bufR[:chacha20InternalBlockSize+lenData-tagSize-NonceSize],
392 copy(p.keyAuthR[:], p.bufR[:SSize])
393 copy(p.tagR[:], data[:tagSize])
394 if !poly1305.Verify(p.tagR, data[tagSize:], p.keyAuthR) {
399 out = p.bufR[chacha20InternalBlockSize : chacha20InternalBlockSize+lenData-tagSize-NonceSize]
403 copy(p.nonceRecv[:], data[lenData-NonceSize:])
404 _, foundL := p.nonceBucketL[p.nonceRecv]
405 _, foundM := p.nonceBucketM[p.nonceRecv]
406 _, foundH := p.nonceBucketH[p.nonceRecv]
407 // If found is none of buckets: either it is too old,
408 // or too new (many packets were lost)
409 if !(foundL || foundM || foundH) {
416 delete(p.nonceBucketL, p.nonceRecv)
419 delete(p.nonceBucketM, p.nonceRecv)
422 delete(p.nonceBucketH, p.nonceRecv)
424 // If we are dealing with the latest bucket, create the new one
426 p.nonceBucketL, p.nonceBucketM = p.nonceBucketM, p.nonceBucketH
427 p.nonceBucketH = make(map[[NonceSize]byte]struct{})
428 var nonce *[NonceSize]byte
429 for i := 0; i < nonceBucketSize; i++ {
431 p.nonceBucketH[*nonce] = struct{}{}
435 if subtle.ConstantTimeCompare(data[lenData-NonceSize:], p.NonceExpect) != 1 {
440 copy(p.NonceExpect, (<-p.noncesExpect)[:])
444 atomic.AddUint64(&p.BytesIn, uint64(lenData))
445 p.LastPing = time.Now()
446 p.pktSizeR = bytes.LastIndexByte(out, padByte)
447 if p.pktSizeR == -1 {
452 for i := p.pktSizeR + 1; i < len(out); i++ {
464 p.BytesPayloadIn += uint64(p.pktSizeR)
465 tap.Write(out[:p.pktSizeR])
470 // PeerTapProcessor processes a TUN/TAP peer
471 func PeerTapProcessor(peer *Peer, tap *TAP, terminator chan struct{}) {
475 fields := logrus.Fields{
476 "func": logFuncPrefix + "PeerTapProcessor",
479 lastSent := time.Now()
480 heartbeat := time.NewTicker(peer.Timeout)
481 if peer.CPRCycle == time.Duration(0) {
489 if lastSent.Add(peer.Timeout).Before(now) {
490 if err = peer.EthProcess(nil); err != nil {
491 logger.WithFields(fields).WithFields(peer.LogFields()).WithError(err).Warn("Can't process nil ethernet packet")
495 case data = <-tap.Sink:
496 if err = peer.EthProcess(data); err != nil {
497 logger.WithFields(fields).WithFields(peer.LogFields()).WithError(err).Warn("Can't process ethernet packet")
499 lastSent = time.Now()
509 case data = <-tap.Sink:
510 if err = peer.EthProcess(data); err != nil {
511 logger.WithFields(fields).WithFields(peer.LogFields()).WithError(err).Warn("Can't process ethernet packet")
516 if err = peer.EthProcess(nil); err != nil {
517 logger.WithFields(fields).WithFields(peer.LogFields()).WithError(err).Warn("Can't process nil ethernet packet")
520 time.Sleep(peer.CPRCycle)