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/>.
26 "golang.org/x/crypto/poly1305"
27 "golang.org/x/crypto/salsa20"
28 "golang.org/x/crypto/xtea"
34 // S20BS is Salsa20's internal blocksize in bytes
36 // Maximal amount of bytes transfered with single key (4 GiB)
37 MaxBytesPerKey int64 = 1 << 32
38 // Size of packet's size mark in bytes
40 // Heartbeat rate, relative to Timeout
44 type RemoteConn interface {
46 // Can incoming packets be reordered
58 CPRCycle time.Duration `json:"-"`
60 // Cryptography related
61 Key *[SSize]byte `json:"-"`
62 NonceOur uint64 `json:"-"`
63 NonceRecv uint64 `json:"-"`
64 NonceCipher *xtea.Cipher `json:"-"`
65 nonceExpect uint64 `json:"-"`
66 nonceBucket0 map[uint64]struct{}
67 nonceBucket1 map[uint64]struct{}
72 Timeout time.Duration `json:"-"`
76 willSentCycle time.Time
78 // This variables are initialized only once to relief GC
80 tag *[poly1305.TagSize]byte
102 func (p *Peer) String() string {
103 return p.Id.String() + ":" + p.Addr
106 // Zero peer's memory state.
107 func (p *Peer) Zero() {
110 sliceZero(p.keyAuth[:])
117 taps = make(map[string]*TAP)
120 // Create TAP listening goroutine.
121 // This function takes required TAP interface name, opens it and allocates
122 // a buffer where all frame data will be written, channel where information
123 // about number of read bytes is sent to, synchronization channel (external
124 // processes tell that read buffer can be used again) and possible channel
126 func TAPListen(ifaceName string, timeout time.Duration, cpr int) (*TAP, chan []byte, chan struct{}, chan struct{}, error) {
129 tap, exists := taps[ifaceName]
131 tap, err = NewTAP(ifaceName)
133 return nil, nil, nil, nil, err
135 taps[ifaceName] = tap
137 sink := make(chan []byte)
138 sinkReady := make(chan struct{})
139 sinkTerminate := make(chan struct{})
140 sinkSkip := make(chan struct{})
143 cprCycle := cprCycleCalculate(cpr)
144 if cprCycle != time.Duration(0) {
147 timeout = timeout / TimeoutHeartbeat
149 heartbeat := time.Tick(timeout)
154 case <-sinkTerminate:
157 go func() { sink <- make([]byte, 0) }()
161 tap.ready <- struct{}{}
167 go func() { sink <- make([]byte, 0) }()
168 goto HeartbeatCatched
169 case <-sinkTerminate:
171 case pkt = <-tap.sink:
180 if exists && tap.synced {
181 sinkSkip <- struct{}{}
183 sinkReady <- struct{}{}
185 return tap, sink, sinkReady, sinkTerminate, nil
188 func newNonceCipher(key *[32]byte) *xtea.Cipher {
189 nonceKey := make([]byte, 16)
190 salsa20.XORKeyStream(
193 make([]byte, xtea.BlockSize),
196 ciph, err := xtea.NewCipher(nonceKey)
203 func cprCycleCalculate(rate int) time.Duration {
205 return time.Duration(0)
207 return time.Second / time.Duration(rate*(1<<10)/MTU)
210 func newPeer(isClient bool, addr string, conn RemoteConn, conf *PeerConf, key *[SSize]byte) *Peer {
212 timeout := conf.Timeout
213 cprCycle := cprCycleCalculate(conf.CPR)
214 noiseEnable := conf.NoiseEnable
219 timeout = timeout / TimeoutHeartbeat
228 NoiseEnable: noiseEnable,
233 NonceCipher: newNonceCipher(key),
234 buf: make([]byte, MTU+S20BS+NonceSize+poly1305.TagSize),
235 tag: new([poly1305.TagSize]byte),
236 keyAuth: new([SSize]byte),
237 nonce: make([]byte, NonceSize),
241 peer.nonceExpect = 0 + 2
244 peer.nonceExpect = 1 + 2
246 if conn.Reorderable() {
247 peer.nonceBucket0 = make(map[uint64]struct{}, NonceBucketSize)
248 peer.nonceBucket1 = make(map[uint64]struct{}, NonceBucketSize)
253 // Process incoming UDP packet.
254 // ConnListen'es synchronization channel used to tell him that he is
255 // free to receive new packets. Authenticated and decrypted packets
256 // will be written to the interface immediately (except heartbeat ones).
257 func (p *Peer) PktProcess(data []byte, tap io.Writer, ready chan struct{}) bool {
259 p.frame = make([]byte, p.size)
263 copy(p.buf[S20BS:], p.frame[:p.size-NonceSize-poly1305.TagSize])
264 for i := 0; i < S20BS; i++ {
267 salsa20.XORKeyStream(
268 p.buf[:S20BS+p.size-NonceSize-poly1305.TagSize],
269 p.buf[:S20BS+p.size-NonceSize-poly1305.TagSize],
270 p.frame[p.size-NonceSize-poly1305.TagSize:p.size-poly1305.TagSize],
273 copy(p.tag[:], p.frame[p.size-poly1305.TagSize:])
274 copy(p.keyAuth[:], p.buf[:SSize])
275 if !poly1305.Verify(p.tag, p.frame[:p.size-poly1305.TagSize], p.keyAuth) {
280 // Check if received nonce is known to us in either of two buckets.
281 // If yes, then this is ignored duplicate.
282 // Check from the oldest bucket, as in most cases this will result
283 // in constant time check.
284 // If Bucket0 is filled, then it becomes Bucket1.
285 p.NonceCipher.Decrypt(
287 p.frame[p.size-NonceSize-poly1305.TagSize:p.size-poly1305.TagSize],
290 p.nonceRecv = binary.BigEndian.Uint64(p.nonce)
291 if p.Conn.Reorderable() {
292 if _, p.nonceFound = p.nonceBucket1[p.NonceRecv]; p.nonceFound {
296 if _, p.nonceFound = p.nonceBucket0[p.NonceRecv]; p.nonceFound {
300 p.nonceBucket0[p.NonceRecv] = struct{}{}
302 if p.nonceBucketN == NonceBucketSize {
303 p.nonceBucket1 = p.nonceBucket0
304 p.nonceBucket0 = make(map[uint64]struct{}, NonceBucketSize)
308 if p.nonceRecv != p.nonceExpect {
316 p.BytesIn += int64(p.size)
317 p.LastPing = time.Now()
318 p.NonceRecv = p.nonceRecv
319 p.pktSize = binary.BigEndian.Uint16(p.buf[S20BS : S20BS+PktSizeSize])
324 p.BytesPayloadIn += int64(p.pktSize)
325 tap.Write(p.buf[S20BS+PktSizeSize : S20BS+PktSizeSize+p.pktSize])
329 // Process incoming Ethernet packet.
330 // ready channel is TAPListen's synchronization channel used to tell him
331 // that he is free to receive new packets. Encrypted and authenticated
332 // packets will be sent to remote Peer side immediately.
333 func (p *Peer) EthProcess(data []byte, ready chan struct{}) {
336 // If this heartbeat is necessary
337 if p.size == 0 && !p.LastSent.Add(p.Timeout).Before(p.now) {
341 copy(p.buf[S20BS+PktSizeSize:], data)
343 binary.BigEndian.PutUint16(p.buf[S20BS:S20BS+PktSizeSize], uint16(p.size))
344 p.BytesPayloadOut += int64(p.size)
346 p.buf[S20BS+0] = byte(0)
347 p.buf[S20BS+1] = byte(0)
352 binary.BigEndian.PutUint64(p.nonce, p.NonceOur)
353 p.NonceCipher.Encrypt(p.nonce, p.nonce)
355 for i := 0; i < S20BS; i++ {
358 salsa20.XORKeyStream(p.buf, p.buf, p.nonce, p.Key)
360 p.frame = append(p.buf[S20BS:S20BS+MTU-NonceSize-poly1305.TagSize], p.nonce...)
362 p.frame = append(p.buf[S20BS:S20BS+PktSizeSize+p.size], p.nonce...)
364 copy(p.keyAuth[:], p.buf[:SSize])
365 poly1305.Sum(p.tag, p.frame, p.keyAuth)
367 p.BytesOut += int64(len(p.frame) + poly1305.TagSize)
370 if p.CPRCycle != time.Duration(0) {
371 p.willSentCycle = p.LastSent.Add(p.CPRCycle)
372 if p.willSentCycle.After(p.now) {
373 time.Sleep(p.willSentCycle.Sub(p.now))
374 p.now = p.willSentCycle
378 p.Conn.Write(append(p.frame, p.tag[:]...))