]> Cypherpunks.ru repositories - govpn.git/commitdiff
Heartbeating the channel twice during timeout
authorSergey Matveev <stargrave@stargrave.org>
Sat, 10 Jan 2015 18:57:14 +0000 (21:57 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sat, 10 Jan 2015 20:02:23 +0000 (23:02 +0300)
Signed-off-by: Sergey Matveev <stargrave@stargrave.org>
README
govpn.go

diff --git a/README b/README
index 078c42e7917bf7dffbd3ac999202275a71f3c2e1..058ef02937ec51fe90f24e9337ec28107c607a63 100644 (file)
--- a/README
+++ b/README
@@ -12,9 +12,8 @@ All packets captured on network interface are encrypted, authenticated
 and sent to remote server, that writes them to his interface, and vice
 versa. Client and server use pre-shared authentication key (PSK).
 Because of stateless UDP nature, after some timeout of inactivity peers
 and sent to remote server, that writes them to his interface, and vice
 versa. Client and server use pre-shared authentication key (PSK).
 Because of stateless UDP nature, after some timeout of inactivity peers
-forget about each other and have to retry handshake process again. As a
-rule, there are enough time-to-time traffic in ordinary Ethernet
-networks to heartbeat connection.
+forget about each other and have to retry handshake process again,
+therefore background heartbeat process will be ran.
 
 Handshake is used to mutually authenticate peers, exchange common secret
 per-session encryption key and checks UDP transport availability.
 
 Handshake is used to mutually authenticate peers, exchange common secret
 per-session encryption key and checks UDP transport availability.
index 25792e8a5b0665c4e72926c391ffa848effd890b..89ccabffa6e602f7b767639457b10fd38a7ecfc1 100644 (file)
--- a/govpn.go
+++ b/govpn.go
@@ -46,7 +46,9 @@ const (
        NonceSize = 8
        KeySize   = 32
        // S20BS is Salsa20's internal blocksize in bytes
        NonceSize = 8
        KeySize   = 32
        // S20BS is Salsa20's internal blocksize in bytes
-       S20BS = 64
+       S20BS         = 64
+       HeartBeatSize = 12
+       HeartBeatMark = "\x00\x00\x00HEARTBEAT"
 )
 
 type TAP interface {
 )
 
 type TAP interface {
@@ -163,6 +165,7 @@ func main() {
        var udpPkt *UDPPkt
        var udpPktData []byte
        var ethPktSize int
        var udpPkt *UDPPkt
        var udpPktData []byte
        var ethPktSize int
+       var frame []byte
        var addr string
        var peer *Peer
        var p *Peer
        var addr string
        var peer *Peer
        var p *Peer
@@ -181,12 +184,17 @@ func main() {
                states[remote.String()] = HandshakeStart(conn, remote, key)
        }
 
                states[remote.String()] = HandshakeStart(conn, remote, key)
        }
 
+       heartbeat := time.Tick(time.Second * time.Duration(timeout/3))
+       heartbeatMark := []byte(HeartBeatMark)
+
        finished := false
        for {
                if finished {
                        break
                }
                select {
        finished := false
        for {
                if finished {
                        break
                }
                select {
+               case <-heartbeat:
+                       go func() { ethSink <- -1 }()
                case udpPkt = <-udpSink:
                        timeouts++
                        if !serverMode && timeouts >= timeout {
                case udpPkt = <-udpSink:
                        timeouts++
                        if !serverMode && timeouts >= timeout {
@@ -246,7 +254,11 @@ func main() {
                        }
                        peer.nonceRecv = nonceRecv
                        timeouts = 0
                        }
                        peer.nonceRecv = nonceRecv
                        timeouts = 0
-                       if _, err := iface.Write(buf[S20BS : S20BS+udpPkt.size-NonceSize-poly1305.TagSize]); err != nil {
+                       frame = buf[S20BS : S20BS+udpPkt.size-NonceSize-poly1305.TagSize]
+                       if string(frame[0:HeartBeatSize]) == HeartBeatMark {
+                               continue
+                       }
+                       if _, err := iface.Write(frame); err != nil {
                                log.Println("Error writing to iface: ", err)
                        }
                        if verbose {
                                log.Println("Error writing to iface: ", err)
                        }
                        if verbose {
@@ -260,8 +272,13 @@ func main() {
                                ethSinkReady <- true
                                continue
                        }
                                ethSinkReady <- true
                                continue
                        }
-                       copy(ethPkt, ethBuf[:ethPktSize])
-                       ethSinkReady <- true
+                       if ethPktSize > -1 {
+                               copy(ethPkt, ethBuf[:ethPktSize])
+                               ethSinkReady <- true
+                       } else {
+                               copy(ethPkt, heartbeatMark)
+                               ethPktSize = HeartBeatSize
+                       }
                        peer.nonceOur = peer.nonceOur + 2
                        binary.PutUvarint(nonce, peer.nonceOur)
                        copy(buf[:KeySize], emptyKey)
                        peer.nonceOur = peer.nonceOur + 2
                        binary.PutUvarint(nonce, peer.nonceOur)
                        copy(buf[:KeySize], emptyKey)