2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2017 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/>.
29 "github.com/Sirupsen/logrus"
30 "github.com/pkg/errors"
32 "cypherpunks.ru/govpn"
35 func (c *Client) startTCP() {
37 l := c.logger.WithField("func", logFuncPrefix+"Client.startTCP")
38 // initialize using a file descriptor
39 if c.config.FileDescriptor > 0 {
40 l.WithField("fd", c.config.FileDescriptor).Debug("Connect using file descriptor")
42 conn, err = net.FileConn(os.NewFile(
43 uintptr(c.config.FileDescriptor),
44 fmt.Sprintf("fd[%s]", c.config.RemoteAddress),
47 c.Error <- errors.Wrapf(err, "net.FileConn fd:%d", c.config.FileDescriptor)
51 // TODO move resolution into the loop, as the name might change over time
52 l.WithField("fd", c.config.RemoteAddress).Debug("Connect using TCP")
53 remote, err := net.ResolveTCPAddr("tcp", c.config.RemoteAddress)
55 c.Error <- errors.Wrapf(err, "net.ResolveTCPAdd %s", c.config.RemoteAddress)
58 l.WithField("remote", remote.String()).Debug("dial")
59 conn, err = net.DialTCP("tcp", nil, remote)
61 c.Error <- errors.Wrapf(err, "net.DialTCP: %s", remote.String())
65 l.WithFields(c.config.LogFields()).Info("Connected")
69 func (c *Client) handleTCP(conn net.Conn) {
70 hs, err := govpn.HandshakeStart(c.config.RemoteAddress, conn, c.config.Peer)
72 govpn.CloseLog(conn, c.logger, c.LogFields())
73 c.Error <- errors.Wrap(err, "govpn.HandshakeStart")
76 buf := make([]byte, 2*(govpn.EnclessEnlargeSize+c.config.Peer.MTU)+c.config.Peer.MTU)
81 var deadLine time.Time
82 var terminator chan struct{}
83 fields := logrus.Fields{"func": logFuncPrefix + "Client.handleTCP"}
92 c.logger.WithFields(fields).WithFields(
94 ).Debug("Packet timeouted")
95 c.timeouted <- struct{}{}
99 deadLine = time.Now().Add(c.config.Peer.Timeout)
100 if err = conn.SetReadDeadline(deadLine); err != nil {
101 c.Error <- errors.Wrapf(err, "conn.SetReadDeadline %s", deadLine.String())
104 n, err = conn.Read(buf[prev:])
110 ).Debug("Packet timeouted")
111 c.timeouted <- struct{}{}
116 _, err = c.idsCache.Find(buf[:prev])
122 ).WithError(err).Debug("Can't find peer in ids")
125 peer, err = hs.Client(buf[:prev])
134 ).Debug("Can't create new peer")
137 c.logger.WithFields(fields).WithFields(c.LogFields()).Info("Handshake completed")
138 c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer})
140 if err = c.postUpAction(); err != nil {
141 c.Error <- errors.Wrap(err, "c.postUpAction")
144 c.firstUpCall = false
147 terminator = make(chan struct{})
148 go govpn.PeerTapProcessor(peer, c.tap, terminator)
163 case <-c.termination:
167 if prev == len(buf) {
170 ).Debug("Packet timeouted")
171 c.timeouted <- struct{}{}
174 if err = conn.SetReadDeadline(time.Now().Add(c.config.Peer.Timeout)); err != nil {
175 c.Error <- errors.Wrap(err, "conn.SetReadDeadline")
178 n, err = conn.Read(buf[prev:])
184 ).Debug("Connection timeouted")
185 c.timeouted <- struct{}{}
190 if prev < govpn.MinPktLength {
193 i = bytes.Index(buf[:prev], peer.NonceExpect)
197 if !peer.PktProcess(buf[:i+govpn.NonceSize], c.tap, false) {
198 c.logger.WithFields(c.LogFields()).Debug("Packet unauthenticated")
199 c.timeouted <- struct{}{}
202 if atomic.LoadUint64(&peer.BytesIn)+atomic.LoadUint64(&peer.BytesOut) > govpn.MaxBytesPerKey {
203 c.logger.WithFields(c.LogFields()).Debug("Rehandshake required")
204 c.rehandshaking <- struct{}{}
207 copy(buf, buf[i+govpn.NonceSize:prev])
208 prev = prev - i - govpn.NonceSize
211 if terminator != nil {
212 terminator <- struct{}{}
215 if err = conn.Close(); err != nil {
216 c.Error <- errors.Wrap(err, "conn.Close")
218 if err = c.tap.Close(); err != nil {
219 c.Error <- errors.Wrap(err, logFuncPrefix+"Client.tap.Close")