]> Cypherpunks.ru repositories - govpn.git/blob - transport.go
Use A-EKE instead of EKE. Doc refactoring. Preparing for 3.0 release
[govpn.git] / transport.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2015 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         "encoding/binary"
23         "io"
24         "log"
25         "net"
26         "time"
27
28         "golang.org/x/crypto/poly1305"
29         "golang.org/x/crypto/salsa20"
30         "golang.org/x/crypto/xtea"
31 )
32
33 const (
34         NonceSize = 8
35         // S20BS is Salsa20's internal blocksize in bytes
36         S20BS = 64
37         // Maximal amount of bytes transfered with single key (4 GiB)
38         MaxBytesPerKey int64 = 1 << 32
39         // Size of packet's size mark in bytes
40         PktSizeSize = 2
41         // Heartbeat rate, relative to Timeout
42         TimeoutHeartbeat = 4
43 )
44
45 type UDPPkt struct {
46         Addr *net.UDPAddr
47         Size int
48 }
49
50 type Peer struct {
51         Addr *net.UDPAddr
52         Id   *PeerId
53
54         // Traffic behaviour
55         NoiseEnable bool
56         CPR         int
57         CPRCycle    time.Duration `json:"-"`
58
59         // Cryptography related
60         Key         *[SSize]byte `json:"-"`
61         Noncediff   int
62         NonceOur    uint64       `json:"-"`
63         NonceRecv   uint64       `json:"-"`
64         NonceCipher *xtea.Cipher `json:"-"`
65
66         // Timers
67         Timeout       time.Duration `json:"-"`
68         Established   time.Time
69         LastPing      time.Time
70         LastSent      time.Time
71         willSentCycle time.Time
72
73         // This variables are initialized only once to relief GC
74         buf       []byte
75         tag       *[poly1305.TagSize]byte
76         keyAuth   *[32]byte
77         nonceRecv uint64
78         frame     []byte
79         nonce     []byte
80         pktSize   uint64
81
82         // Statistics
83         BytesIn         int64
84         BytesOut        int64
85         BytesPayloadIn  int64
86         BytesPayloadOut int64
87         FramesIn        int
88         FramesOut       int
89         FramesUnauth    int
90         FramesDup       int
91         HeartbeatRecv   int
92         HeartbeatSent   int
93 }
94
95 func (p *Peer) String() string {
96         return p.Id.String() + ":" + p.Addr.String()
97 }
98
99 // Zero peer's memory state.
100 func (p *Peer) Zero() {
101         sliceZero(p.Key[:])
102         sliceZero(p.tag[:])
103         sliceZero(p.keyAuth[:])
104         sliceZero(p.buf)
105         sliceZero(p.frame)
106         sliceZero(p.nonce)
107 }
108
109 var (
110         Emptiness = make([]byte, 1<<14)
111         taps      = make(map[string]*TAP)
112 )
113
114 // Create TAP listening goroutine.
115 // This function takes required TAP interface name, opens it and allocates
116 // a buffer where all frame data will be written, channel where information
117 // about number of read bytes is sent to, synchronization channel (external
118 // processes tell that read buffer can be used again) and possible channel
119 // opening error.
120 func TAPListen(ifaceName string, timeout time.Duration, cpr int) (*TAP, chan []byte, chan struct{}, chan struct{}, error) {
121         var tap *TAP
122         var err error
123         tap, exists := taps[ifaceName]
124         if !exists {
125                 tap, err = NewTAP(ifaceName)
126                 if err != nil {
127                         return nil, nil, nil, nil, err
128                 }
129                 taps[ifaceName] = tap
130         }
131         sink := make(chan []byte)
132         sinkReady := make(chan struct{})
133         sinkTerminate := make(chan struct{})
134         sinkSkip := make(chan struct{})
135
136         go func() {
137                 cprCycle := cprCycleCalculate(cpr)
138                 if cprCycle != time.Duration(0) {
139                         timeout = cprCycle
140                 } else {
141                         timeout = timeout / TimeoutHeartbeat
142                 }
143                 heartbeat := time.Tick(timeout)
144                 var pkt []byte
145         ListenCycle:
146                 for {
147                         select {
148                         case <-sinkTerminate:
149                                 break ListenCycle
150                         case <-heartbeat:
151                                 go func() { sink <- make([]byte, 0) }()
152                                 continue
153                         case <-sinkSkip:
154                         case <-sinkReady:
155                                 tap.ready <- struct{}{}
156                                 tap.synced = true
157                         }
158                 HeartbeatCatched:
159                         select {
160                         case <-heartbeat:
161                                 go func() { sink <- make([]byte, 0) }()
162                                 goto HeartbeatCatched
163                         case <-sinkTerminate:
164                                 break ListenCycle
165                         case pkt = <-tap.sink:
166                                 tap.synced = false
167                                 sink <- pkt
168                         }
169                 }
170                 close(sink)
171                 close(sinkReady)
172                 close(sinkTerminate)
173         }()
174         if exists && tap.synced {
175                 sinkSkip <- struct{}{}
176         } else {
177                 sinkReady <- struct{}{}
178         }
179         return tap, sink, sinkReady, sinkTerminate, nil
180 }
181
182 // Create UDP listening goroutine.
183 // This function takes already listening UDP socket and a buffer where
184 // all UDP packet data will be saved, channel where information about
185 // remote address and number of written bytes are stored, and a channel
186 // used to tell that buffer is ready to be overwritten.
187 func ConnListen(conn *net.UDPConn) (chan UDPPkt, []byte, chan struct{}) {
188         buf := make([]byte, MTU)
189         sink := make(chan UDPPkt)
190         sinkReady := make(chan struct{})
191         go func(conn *net.UDPConn) {
192                 var n int
193                 var addr *net.UDPAddr
194                 var err error
195                 for {
196                         <-sinkReady
197                         conn.SetReadDeadline(time.Now().Add(time.Second))
198                         n, addr, err = conn.ReadFromUDP(buf)
199                         if err != nil {
200                                 // This is needed for ticking the timeouts counter outside
201                                 sink <- UDPPkt{nil, 0}
202                                 continue
203                         }
204                         sink <- UDPPkt{addr, n}
205                 }
206         }(conn)
207         sinkReady <- struct{}{}
208         return sink, buf, sinkReady
209 }
210
211 func newNonceCipher(key *[32]byte) *xtea.Cipher {
212         nonceKey := make([]byte, 16)
213         salsa20.XORKeyStream(
214                 nonceKey,
215                 make([]byte, 32),
216                 make([]byte, xtea.BlockSize),
217                 key,
218         )
219         ciph, err := xtea.NewCipher(nonceKey)
220         if err != nil {
221                 panic(err)
222         }
223         return ciph
224 }
225
226 func cprCycleCalculate(rate int) time.Duration {
227         if rate == 0 {
228                 return time.Duration(0)
229         }
230         return time.Second / time.Duration(rate*(1<<10)/MTU)
231 }
232
233 func newPeer(addr *net.UDPAddr, conf *PeerConf, nonce int, key *[SSize]byte) *Peer {
234         now := time.Now()
235         timeout := conf.Timeout
236         cprCycle := cprCycleCalculate(conf.CPR)
237         noiseEnable := conf.NoiseEnable
238         if conf.CPR > 0 {
239                 noiseEnable = true
240                 timeout = cprCycle
241         } else {
242                 timeout = timeout / TimeoutHeartbeat
243         }
244         peer := Peer{
245                 Addr:        addr,
246                 Timeout:     timeout,
247                 Established: now,
248                 LastPing:    now,
249                 Id:          conf.Id,
250                 NoiseEnable: noiseEnable,
251                 CPR:         conf.CPR,
252                 CPRCycle:    cprCycle,
253                 Noncediff:   conf.Noncediff,
254                 NonceOur:    uint64(conf.Noncediff + nonce),
255                 NonceRecv:   uint64(conf.Noncediff + 0),
256                 Key:         key,
257                 NonceCipher: newNonceCipher(key),
258                 buf:         make([]byte, MTU+S20BS),
259                 tag:         new([poly1305.TagSize]byte),
260                 keyAuth:     new([SSize]byte),
261                 nonce:       make([]byte, NonceSize),
262         }
263         return &peer
264 }
265
266 // Process incoming UDP packet.
267 // udpPkt is received data, related to the peer tap interface and
268 // ConnListen'es synchronization channel used to tell him that he is
269 // free to receive new packets. Authenticated and decrypted packets
270 // will be written to the interface immediately (except heartbeat ones).
271 func (p *Peer) UDPProcess(udpPkt []byte, tap io.Writer, ready chan struct{}) bool {
272         size := len(udpPkt)
273         copy(p.buf, Emptiness)
274         copy(p.tag[:], udpPkt[size-poly1305.TagSize:])
275         copy(p.buf[S20BS:], udpPkt[NonceSize:size-poly1305.TagSize])
276         salsa20.XORKeyStream(
277                 p.buf[:S20BS+size-poly1305.TagSize],
278                 p.buf[:S20BS+size-poly1305.TagSize],
279                 udpPkt[:NonceSize],
280                 p.Key,
281         )
282         copy(p.keyAuth[:], p.buf[:SSize])
283         if !poly1305.Verify(p.tag, udpPkt[:size-poly1305.TagSize], p.keyAuth) {
284                 ready <- struct{}{}
285                 p.FramesUnauth++
286                 return false
287         }
288         p.NonceCipher.Decrypt(p.buf, udpPkt[:NonceSize])
289         p.nonceRecv, _ = binary.Uvarint(p.buf[:NonceSize])
290         if int(p.NonceRecv)-p.Noncediff >= 0 && int(p.nonceRecv) < int(p.NonceRecv)-p.Noncediff {
291                 ready <- struct{}{}
292                 p.FramesDup++
293                 return false
294         }
295         ready <- struct{}{}
296         p.FramesIn++
297         p.BytesIn += int64(size)
298         p.LastPing = time.Now()
299         p.NonceRecv = p.nonceRecv
300         p.pktSize, _ = binary.Uvarint(p.buf[S20BS : S20BS+PktSizeSize])
301         if p.pktSize == 0 {
302                 p.HeartbeatRecv++
303                 return true
304         }
305         p.frame = p.buf[S20BS+PktSizeSize : S20BS+PktSizeSize+p.pktSize]
306         p.BytesPayloadIn += int64(p.pktSize)
307         tap.Write(p.frame)
308         return true
309 }
310
311 type WriteToer interface {
312         WriteTo([]byte, net.Addr) (int, error)
313 }
314
315 // Process incoming Ethernet packet.
316 // ethPkt is received data, conn is our outgoing connection.
317 // ready channel is TAPListen's synchronization channel used to tell him
318 // that he is free to receive new packets. Encrypted and authenticated
319 // packets will be sent to remote Peer side immediately.
320 func (p *Peer) EthProcess(ethPkt []byte, conn WriteToer, ready chan struct{}) {
321         now := time.Now()
322         size := len(ethPkt)
323         // If this heartbeat is necessary
324         if size == 0 && !p.LastSent.Add(p.Timeout).Before(now) {
325                 return
326         }
327         copy(p.buf, Emptiness)
328         if size > 0 {
329                 copy(p.buf[S20BS+PktSizeSize:], ethPkt)
330                 ready <- struct{}{}
331                 binary.PutUvarint(p.buf[S20BS:S20BS+PktSizeSize], uint64(size))
332                 p.BytesPayloadOut += int64(size)
333         } else {
334                 p.HeartbeatSent++
335         }
336
337         p.NonceOur += 2
338         copy(p.nonce, Emptiness)
339         binary.PutUvarint(p.nonce, p.NonceOur)
340         p.NonceCipher.Encrypt(p.nonce, p.nonce)
341
342         salsa20.XORKeyStream(p.buf, p.buf, p.nonce, p.Key)
343         copy(p.buf[S20BS-NonceSize:S20BS], p.nonce)
344         copy(p.keyAuth[:], p.buf[:SSize])
345         if p.NoiseEnable {
346                 p.frame = p.buf[S20BS-NonceSize : S20BS+MTU-NonceSize-poly1305.TagSize]
347         } else {
348                 p.frame = p.buf[S20BS-NonceSize : S20BS+PktSizeSize+size]
349         }
350         poly1305.Sum(p.tag, p.frame, p.keyAuth)
351
352         p.BytesOut += int64(len(p.frame) + poly1305.TagSize)
353         p.FramesOut++
354
355         if p.CPRCycle != time.Duration(0) {
356                 p.willSentCycle = p.LastSent.Add(p.CPRCycle)
357                 if p.willSentCycle.After(now) {
358                         time.Sleep(p.willSentCycle.Sub(now))
359                         now = p.willSentCycle
360                 }
361         }
362         p.LastSent = now
363         if _, err := conn.WriteTo(append(p.frame, p.tag[:]...), p.Addr); err != nil {
364                 log.Println("Error sending UDP", err)
365         }
366 }