2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2019 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, version 3 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 "golang.org/x/crypto/blake2b"
32 "golang.org/x/crypto/poly1305"
38 TagSize = poly1305.TagSize
39 // S20BS is ChaCha20's internal blocksize in bytes
41 // Maximal amount of bytes transfered with single key (4 GiB)
42 MaxBytesPerKey uint64 = 1 << 32
43 // Heartbeat rate, relative to Timeout
45 // Minimal valid packet length
46 MinPktLength = 1 + 16 + 8
51 func newNonces(key *[32]byte, i uint64) chan *[NonceSize]byte {
52 macKey := make([]byte, 32)
53 chacha20.XORKeyStream(macKey, make([]byte, 32), new([16]byte), key)
54 mac, err := blake2b.New256(macKey)
58 sum := make([]byte, mac.Size())
59 nonces := make(chan *[NonceSize]byte, NonceBucketSize*3)
62 buf := new([NonceSize]byte)
63 binary.BigEndian.PutUint64(buf[:], i)
76 // Statistics (they are at the beginning for correct int64 alignment)
80 BytesPayloadOut uint64
91 Conn io.Writer `json:"-"`
96 CPRCycle time.Duration `json:"-"`
103 Timeout time.Duration `json:"-"`
104 Established time.Time
108 BusyR sync.Mutex `json:"-"`
111 keyAuthR *[SSize]byte
116 noncesR chan *[NonceSize]byte
117 nonceRecv [NonceSize]byte
118 nonceBucketL map[[NonceSize]byte]struct{}
119 nonceBucketM map[[NonceSize]byte]struct{}
120 nonceBucketH map[[NonceSize]byte]struct{}
123 NonceExpect []byte `json:"-"`
124 noncesExpect chan *[NonceSize]byte
127 BusyT sync.Mutex `json:"-"`
130 keyAuthT *[SSize]byte
133 noncesT chan *[NonceSize]byte
136 func (p *Peer) String() string {
137 return p.ID.String() + ":" + p.Addr
140 // Zero peer's memory state.
141 func (p *Peer) Zero() {
147 SliceZero(p.keyAuthR[:])
148 SliceZero(p.keyAuthT[:])
153 func cprCycleCalculate(conf *PeerConf) time.Duration {
155 return time.Duration(0)
157 rate := conf.CPR * 1 << 10
159 rate /= EnclessEnlargeSize + conf.MTU
163 return time.Second / time.Duration(rate)
166 func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[SSize]byte) *Peer {
168 timeout := conf.Timeout
170 cprCycle := cprCycleCalculate(conf)
171 noiseEnable := conf.Noise
176 timeout = timeout / TimeoutHeartbeat
179 bufSize := S20BS + 2*conf.MTU
181 bufSize += EnclessEnlargeSize
190 NoiseEnable: noiseEnable,
193 Encless: conf.Encless,
202 bufR: make([]byte, bufSize),
203 bufT: make([]byte, bufSize),
204 tagR: new([TagSize]byte),
205 tagT: new([TagSize]byte),
206 keyAuthR: new([SSize]byte),
207 nonceR: new([16]byte),
208 keyAuthT: new([SSize]byte),
209 nonceT: new([16]byte),
213 peer.noncesT = newNonces(peer.key, 1+2)
214 peer.noncesR = newNonces(peer.key, 0+2)
215 peer.noncesExpect = newNonces(peer.key, 0+2)
217 peer.noncesT = newNonces(peer.key, 0+2)
218 peer.noncesR = newNonces(peer.key, 1+2)
219 peer.noncesExpect = newNonces(peer.key, 1+2)
222 peer.NonceExpect = make([]byte, NonceSize)
223 nonce := <-peer.noncesExpect
224 copy(peer.NonceExpect, nonce[:])
227 peer.nonceBucketL = make(map[[NonceSize]byte]struct{}, NonceBucketSize)
228 for i = 0; i < NonceBucketSize; i++ {
229 nonce = <-peer.noncesR
230 peer.nonceBucketL[*nonce] = struct{}{}
232 peer.nonceBucketM = make(map[[NonceSize]byte]struct{}, NonceBucketSize)
233 for i = 0; i < NonceBucketSize; i++ {
234 nonce = <-peer.noncesR
235 peer.nonceBucketM[*nonce] = struct{}{}
237 peer.nonceBucketH = make(map[[NonceSize]byte]struct{}, NonceBucketSize)
238 for i = 0; i < NonceBucketSize; i++ {
239 nonce = <-peer.noncesR
240 peer.nonceBucketH[*nonce] = struct{}{}
246 // Process incoming Ethernet packet.
247 // ready channel is TAPListen's synchronization channel used to tell him
248 // that he is free to receive new packets. Encrypted and authenticated
249 // packets will be sent to remote Peer side immediately.
250 func (p *Peer) EthProcess(data []byte) {
251 if len(data) > p.MTU-1 { // 1 is for padding byte
252 log.Println("Padded data packet size", len(data)+1, "is bigger than MTU", p.MTU, p)
257 // Zero size is a heartbeat packet
260 p.bufT[S20BS+0] = PadByte
263 // Copy payload to our internal buffer and we are ready to
264 // accept the next one
265 copy(p.bufT[S20BS:], data)
266 p.bufT[S20BS+len(data)] = PadByte
267 p.BytesPayloadOut += uint64(len(data))
270 if p.NoiseEnable && !p.Encless {
271 p.frameT = p.bufT[S20BS : S20BS+p.MTU-TagSize]
272 } else if p.Encless {
273 p.frameT = p.bufT[S20BS : S20BS+p.MTU]
275 p.frameT = p.bufT[S20BS : S20BS+len(data)+1+NonceSize]
277 copy(p.frameT[len(p.frameT)-NonceSize:], (<-p.noncesT)[:])
279 copy(p.nonceT[8:], p.frameT[len(p.frameT)-NonceSize:])
282 out, err = EnclessEncode(p.key, p.nonceT, p.frameT[:len(p.frameT)-NonceSize])
286 out = append(out, p.frameT[len(p.frameT)-NonceSize:]...)
288 chacha20.XORKeyStream(
289 p.bufT[:S20BS+len(p.frameT)-NonceSize],
290 p.bufT[:S20BS+len(p.frameT)-NonceSize],
294 copy(p.keyAuthT[:], p.bufT[:SSize])
295 poly1305.Sum(p.tagT, p.frameT, p.keyAuthT)
296 atomic.AddUint64(&p.BytesOut, uint64(len(p.frameT)+TagSize))
297 out = append(p.tagT[:], p.frameT...)
304 func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
305 if len(data) < MinPktLength {
308 if !p.Encless && len(data) > len(p.bufR)-S20BS {
313 copy(p.nonceR[8:], data[len(data)-NonceSize:])
316 out, err = EnclessDecode(p.key, p.nonceR, data[:len(data)-NonceSize])
323 for i := 0; i < SSize; i++ {
326 copy(p.bufR[S20BS:], data[TagSize:])
327 chacha20.XORKeyStream(
328 p.bufR[:S20BS+len(data)-TagSize-NonceSize],
329 p.bufR[:S20BS+len(data)-TagSize-NonceSize],
333 copy(p.keyAuthR[:], p.bufR[:SSize])
334 copy(p.tagR[:], data[:TagSize])
335 if !poly1305.Verify(p.tagR, data[TagSize:], p.keyAuthR) {
340 out = p.bufR[S20BS : S20BS+len(data)-TagSize-NonceSize]
344 copy(p.nonceRecv[:], data[len(data)-NonceSize:])
345 _, foundL := p.nonceBucketL[p.nonceRecv]
346 _, foundM := p.nonceBucketM[p.nonceRecv]
347 _, foundH := p.nonceBucketH[p.nonceRecv]
348 // If found is none of buckets: either it is too old,
349 // or too new (many packets were lost)
350 if !(foundL || foundM || foundH) {
357 delete(p.nonceBucketL, p.nonceRecv)
360 delete(p.nonceBucketM, p.nonceRecv)
363 delete(p.nonceBucketH, p.nonceRecv)
365 // If we are dealing with the latest bucket, create the new one
367 p.nonceBucketL, p.nonceBucketM = p.nonceBucketM, p.nonceBucketH
368 p.nonceBucketH = make(map[[NonceSize]byte]struct{})
369 var nonce *[NonceSize]byte
370 for i := 0; i < NonceBucketSize; i++ {
372 p.nonceBucketH[*nonce] = struct{}{}
376 if subtle.ConstantTimeCompare(data[len(data)-NonceSize:], p.NonceExpect) != 1 {
381 copy(p.NonceExpect, (<-p.noncesExpect)[:])
385 atomic.AddUint64(&p.BytesIn, uint64(len(data)))
386 p.LastPing = time.Now()
387 p.pktSizeR = bytes.LastIndexByte(out, PadByte)
388 if p.pktSizeR == -1 {
393 for i := p.pktSizeR + 1; i < len(out); i++ {
405 p.BytesPayloadIn += uint64(p.pktSizeR)
406 tap.Write(out[:p.pktSizeR])
411 func PeerTapProcessor(peer *Peer, tap *TAP, terminator chan struct{}) {
414 lastSent := time.Now()
415 heartbeat := time.NewTicker(peer.Timeout)
416 if peer.CPRCycle == time.Duration(0) {
424 if lastSent.Add(peer.Timeout).Before(now) {
428 case data = <-tap.Sink:
429 peer.EthProcess(data)
430 lastSent = time.Now()
440 case data = <-tap.Sink:
441 peer.EthProcess(data)
447 time.Sleep(peer.CPRCycle)