]> Cypherpunks.ru repositories - govpn.git/blob - cmd/govpn-server/tcp.go
Raise copyright years
[govpn.git] / cmd / govpn-server / tcp.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2020 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, version 3 of the License.
8
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.
13
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/>.
16 */
17
18 package main
19
20 import (
21         "bytes"
22         "log"
23         "net"
24         "time"
25
26         "go.cypherpunks.ru/govpn/v7"
27 )
28
29 func startTCP() {
30         bind, err := net.ResolveTCPAddr("tcp", *bindAddr)
31         if err != nil {
32                 log.Fatalln("Can not resolve bind address:", err)
33         }
34         listener, err := net.ListenTCP("tcp", bind)
35         if err != nil {
36                 log.Fatalln("Can not listen on TCP:", err)
37         }
38         govpn.BothPrintf(`[tcp-listen bind="%s"]`, *bindAddr)
39         go func() {
40                 for {
41                         conn, err := listener.AcceptTCP()
42                         if err != nil {
43                                 govpn.Printf(`[tcp-accept-failed bind="%s" err="%s"]`, *bindAddr, err)
44                                 continue
45                         }
46                         go handleTCP(conn)
47                 }
48         }()
49 }
50
51 func handleTCP(conn net.Conn) {
52         addr := conn.RemoteAddr().String()
53         buf := make([]byte, govpn.EnclessEnlargeSize+2*govpn.MTUMax)
54         var n int
55         var err error
56         var prev int
57         var hs *govpn.Handshake
58         var ps *PeerState
59         var peer *govpn.Peer
60         var tap *govpn.TAP
61         var conf *govpn.PeerConf
62         var addrPrev string
63         var peerPrevI interface{}
64         var peerPrev *PeerState
65         for {
66                 if prev == len(buf) {
67                         break
68                 }
69                 conn.SetReadDeadline(time.Now().Add(time.Duration(govpn.TimeoutDefault) * time.Second))
70                 n, err = conn.Read(buf[prev:])
71                 if err != nil {
72                         // Either EOFed or timeouted
73                         break
74                 }
75                 prev += n
76                 peerID := idsCache.Find(buf[:prev])
77                 if peerID == nil {
78                         continue
79                 }
80                 if hs == nil {
81                         conf = confs[*peerID]
82                         if conf == nil {
83                                 govpn.Printf(
84                                         `[conf-get-failed bind="%s" peer="%s"]`,
85                                         *bindAddr, peerID.String(),
86                                 )
87                                 break
88                         }
89                         hs = govpn.NewHandshake(addr, conn, conf)
90                 }
91                 peer = hs.Server(buf[:prev])
92                 prev = 0
93                 if peer == nil {
94                         continue
95                 }
96                 hs.Zero()
97                 govpn.Printf(
98                         `[handshake-completed bind="%s" addr="%s" peer="%s"]`,
99                         *bindAddr, addr, peerID.String(),
100                 )
101                 addrPrevI, exists := peersByID.Load(*peer.ID)
102                 if exists {
103                         addrPrev = addrPrevI.(string)
104                         peerPrevI, exists = peers.Load(addrPrev)
105                         if exists {
106                                 peerPrev = peerPrevI.(*PeerState)
107                                 exists = peerPrev == nil
108                         }
109                 }
110                 if exists {
111                         peerPrev.terminator <- struct{}{}
112                         tap = peerPrev.tap
113                         ps = &PeerState{
114                                 peer:       peer,
115                                 tap:        tap,
116                                 terminator: make(chan struct{}),
117                         }
118                         go govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
119                         peers.Delete(addrPrev)
120                         peers.Store(addr, ps)
121                         knownPeers.Delete(addrPrev)
122                         knownPeers.Store(addr, &peer)
123                         peersByID.Store(*peer.ID, addr)
124                         govpn.Printf(
125                                 `[rehandshake-completed bind="%s" peer="%s"]`,
126                                 *bindAddr, peerID.String(),
127                         )
128                 } else {
129                         ifaceName, err := callUp(peer.ID, peer.Addr)
130                         if err != nil {
131                                 peer = nil
132                                 break
133                         }
134                         tap, err = govpn.TAPListen(ifaceName, peer.MTU)
135                         if err != nil {
136                                 govpn.Printf(
137                                         `[tap-failed bind="%s" peer="%s" err="%s"]`,
138                                         *bindAddr, peerID.String(), err,
139                                 )
140                                 peer = nil
141                                 break
142                         }
143                         ps = &PeerState{
144                                 peer:       peer,
145                                 tap:        tap,
146                                 terminator: make(chan struct{}, 1),
147                         }
148                         go govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
149                         peers.Store(addr, ps)
150                         peersByID.Store(*peer.ID, addr)
151                         knownPeers.Store(addr, &peer)
152                         govpn.Printf(`[peer-created bind="%s" peer="%s"]`, *bindAddr, peerID.String())
153                 }
154                 break
155         }
156         if hs != nil {
157                 hs.Zero()
158         }
159         if peer == nil {
160                 return
161         }
162
163         prev = 0
164         var i int
165         for {
166                 if prev == len(buf) {
167                         break
168                 }
169                 conn.SetReadDeadline(time.Now().Add(conf.Timeout))
170                 n, err = conn.Read(buf[prev:])
171                 if err != nil {
172                         // Either EOFed or timeouted
173                         break
174                 }
175                 prev += n
176         CheckMore:
177                 if prev < govpn.MinPktLength {
178                         continue
179                 }
180                 i = bytes.Index(buf[:prev], peer.NonceExpect)
181                 if i == -1 {
182                         continue
183                 }
184                 if !peer.PktProcess(buf[:i+govpn.NonceSize], tap, false) {
185                         govpn.Printf(
186                                 `[packet-unauthenticated bind="%s" addr="%s" peer="%s"]`,
187                                 *bindAddr, addr, peer.ID.String(),
188                         )
189                         break
190                 }
191                 copy(buf, buf[i+govpn.NonceSize:prev])
192                 prev = prev - i - govpn.NonceSize
193                 goto CheckMore
194         }
195         peer.Zero()
196 }