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