]> Cypherpunks.ru repositories - govpn.git/blob - src/govpn/transport.go
f46eeefb62b3aae5c9af6fbebe46705d9688e1b7
[govpn.git] / src / govpn / 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         "net"
25         "time"
26
27         "golang.org/x/crypto/poly1305"
28         "golang.org/x/crypto/salsa20"
29         "golang.org/x/crypto/xtea"
30 )
31
32 const (
33         NonceSize = 8
34         // S20BS is Salsa20's internal blocksize in bytes
35         S20BS = 64
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
39         PktSizeSize = 2
40         // Heartbeat rate, relative to Timeout
41         TimeoutHeartbeat = 4
42 )
43
44 type UDPPkt struct {
45         Addr *net.UDPAddr
46         Size int
47 }
48
49 type Peer struct {
50         Addr *net.UDPAddr
51         Id   *PeerId
52
53         // Traffic behaviour
54         NoiseEnable bool
55         CPR         int
56         CPRCycle    time.Duration `json:"-"`
57
58         // Cryptography related
59         Key         *[SSize]byte `json:"-"`
60         Noncediff   int
61         NonceOur    uint64       `json:"-"`
62         NonceRecv   uint64       `json:"-"`
63         NonceCipher *xtea.Cipher `json:"-"`
64
65         // Timers
66         Timeout       time.Duration `json:"-"`
67         Established   time.Time
68         LastPing      time.Time
69         LastSent      time.Time
70         willSentCycle time.Time
71
72         // This variables are initialized only once to relief GC
73         buf       []byte
74         tag       *[poly1305.TagSize]byte
75         keyAuth   *[32]byte
76         nonceRecv uint64
77         frame     []byte
78         nonce     []byte
79         pktSize   uint64
80         size      int
81         now       time.Time
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 *[32]byte) *xtea.Cipher {
213         nonceKey := make([]byte, 16)
214         salsa20.XORKeyStream(
215                 nonceKey,
216                 make([]byte, 32),
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, conf *PeerConf, nonce int, key *[SSize]byte) *Peer {
235         now := time.Now()
236         timeout := conf.Timeout
237         cprCycle := cprCycleCalculate(conf.CPR)
238         noiseEnable := conf.NoiseEnable
239         if conf.CPR > 0 {
240                 noiseEnable = true
241                 timeout = cprCycle
242         } else {
243                 timeout = timeout / TimeoutHeartbeat
244         }
245         peer := Peer{
246                 Addr:        addr,
247                 Timeout:     timeout,
248                 Established: now,
249                 LastPing:    now,
250                 Id:          conf.Id,
251                 NoiseEnable: noiseEnable,
252                 CPR:         conf.CPR,
253                 CPRCycle:    cprCycle,
254                 Noncediff:   conf.Noncediff,
255                 NonceOur:    uint64(conf.Noncediff + nonce),
256                 NonceRecv:   uint64(conf.Noncediff + 0),
257                 Key:         key,
258                 NonceCipher: newNonceCipher(key),
259                 buf:         make([]byte, MTU+S20BS),
260                 tag:         new([poly1305.TagSize]byte),
261                 keyAuth:     new([SSize]byte),
262                 nonce:       make([]byte, NonceSize),
263         }
264         return &peer
265 }
266
267 // Process incoming UDP packet.
268 // udpPkt is received data, related to the peer tap interface and
269 // ConnListen'es synchronization channel used to tell him that he is
270 // free to receive new packets. Authenticated and decrypted packets
271 // will be written to the interface immediately (except heartbeat ones).
272 func (p *Peer) UDPProcess(udpPkt []byte, tap io.Writer, ready chan struct{}) bool {
273         p.size = len(udpPkt)
274         copy(p.buf, Emptiness)
275         copy(p.tag[:], udpPkt[p.size-poly1305.TagSize:])
276         copy(p.buf[S20BS:], udpPkt[NonceSize:p.size-poly1305.TagSize])
277         salsa20.XORKeyStream(
278                 p.buf[:S20BS+p.size-poly1305.TagSize],
279                 p.buf[:S20BS+p.size-poly1305.TagSize],
280                 udpPkt[:NonceSize],
281                 p.Key,
282         )
283         copy(p.keyAuth[:], p.buf[:SSize])
284         if !poly1305.Verify(p.tag, udpPkt[:p.size-poly1305.TagSize], p.keyAuth) {
285                 ready <- struct{}{}
286                 p.FramesUnauth++
287                 return false
288         }
289         p.NonceCipher.Decrypt(p.buf, udpPkt[:NonceSize])
290         p.nonceRecv, _ = binary.Uvarint(p.buf[:NonceSize])
291         if int(p.NonceRecv)-p.Noncediff >= 0 && int(p.nonceRecv) < int(p.NonceRecv)-p.Noncediff {
292                 ready <- struct{}{}
293                 p.FramesDup++
294                 return false
295         }
296         ready <- struct{}{}
297         p.FramesIn++
298         p.BytesIn += int64(p.size)
299         p.LastPing = time.Now()
300         p.NonceRecv = p.nonceRecv
301         p.pktSize, _ = binary.Uvarint(p.buf[S20BS : S20BS+PktSizeSize])
302         if p.pktSize == 0 {
303                 p.HeartbeatRecv++
304                 return true
305         }
306         p.frame = p.buf[S20BS+PktSizeSize : S20BS+PktSizeSize+p.pktSize]
307         p.BytesPayloadIn += int64(p.pktSize)
308         tap.Write(p.frame)
309         return true
310 }
311
312 type WriteToUDPer interface {
313         WriteToUDP([]byte, *net.UDPAddr) (int, error)
314 }
315
316 // Process incoming Ethernet packet.
317 // ethPkt is received data, conn is our outgoing connection.
318 // ready channel is TAPListen's synchronization channel used to tell him
319 // that he is free to receive new packets. Encrypted and authenticated
320 // packets will be sent to remote Peer side immediately.
321 func (p *Peer) EthProcess(ethPkt []byte, conn WriteToUDPer, ready chan struct{}) {
322         p.now = time.Now()
323         p.size = len(ethPkt)
324         // If this heartbeat is necessary
325         if p.size == 0 && !p.LastSent.Add(p.Timeout).Before(p.now) {
326                 return
327         }
328         copy(p.buf, Emptiness)
329         if p.size > 0 {
330                 copy(p.buf[S20BS+PktSizeSize:], ethPkt)
331                 ready <- struct{}{}
332                 binary.PutUvarint(p.buf[S20BS:S20BS+PktSizeSize], uint64(p.size))
333                 p.BytesPayloadOut += int64(p.size)
334         } else {
335                 p.HeartbeatSent++
336         }
337
338         p.NonceOur += 2
339         copy(p.nonce, Emptiness)
340         binary.PutUvarint(p.nonce, p.NonceOur)
341         p.NonceCipher.Encrypt(p.nonce, p.nonce)
342
343         salsa20.XORKeyStream(p.buf, p.buf, p.nonce, p.Key)
344         copy(p.buf[S20BS-NonceSize:S20BS], p.nonce)
345         copy(p.keyAuth[:], p.buf[:SSize])
346         if p.NoiseEnable {
347                 p.frame = p.buf[S20BS-NonceSize : S20BS+MTU-NonceSize-poly1305.TagSize]
348         } else {
349                 p.frame = p.buf[S20BS-NonceSize : S20BS+PktSizeSize+p.size]
350         }
351         poly1305.Sum(p.tag, p.frame, p.keyAuth)
352
353         p.BytesOut += int64(len(p.frame) + poly1305.TagSize)
354         p.FramesOut++
355
356         if p.CPRCycle != time.Duration(0) {
357                 p.willSentCycle = p.LastSent.Add(p.CPRCycle)
358                 if p.willSentCycle.After(p.now) {
359                         time.Sleep(p.willSentCycle.Sub(p.now))
360                         p.now = p.willSentCycle
361                 }
362         }
363         p.LastSent = p.now
364         conn.WriteToUDP(append(p.frame, p.tag[:]...), p.Addr)
365 }