README | 3 ++- govpn.go | 14 +++++++++++++- diff --git a/README b/README index c529c3e67bbd359db466d789612da520658e8949..2852a09cd71045f15f9c9f52ee33a39a2d699c8b 100644 --- a/README +++ b/README @@ -26,7 +26,8 @@ High security and high performance are the goals for that daemon. It uses fast cryptography algorithms with 128bit security margin, strong mutual zero-knowledge authentication and perfect-forward secrecy property. An attacker can not know anything from captured traffic, even -if pre-shared key is compromised. +if pre-shared key is compromised. Rehandshake is performed by client +every 4 GiB of transfered data. Also you can provide up and down scripts that will be executed after either connection is initiated (up-script in background), or is went diff --git a/govpn.go b/govpn.go index 1e157107c33cafab4cbdd7631184bed511666acb..b4eda05acd98f559e79f5b31f57d86b21decf4ab 100644 --- a/govpn.go +++ b/govpn.go @@ -55,6 +55,8 @@ // S20BS is Salsa20's internal blocksize in bytes S20BS = 64 HeartBeatSize = 12 HeartBeatMark = "\x00\x00\x00HEARTBEAT" + // Maximal amount of bytes transfered with single key (4 GiB) + MaxBytesPerKey = 4294967296 ) type TAP interface { @@ -189,6 +191,7 @@ var peer *Peer var p *Peer timeouts := 0 + bytes := 0 states := make(map[string]*Handshake) nonce := make([]byte, NonceSize) keyAuth := new([KeySize]byte) @@ -203,6 +206,7 @@ states[remote.String()] = HandshakeStart(conn, remote, key) } heartbeat := time.Tick(time.Second * time.Duration(timeout/3)) + go func() { <-heartbeat }() heartbeatMark := []byte(HeartBeatMark) termSignal := make(chan os.Signal, 1) @@ -213,6 +217,10 @@ for { if finished { break } + if !serverMode && bytes > MaxBytesPerKey { + states[remote.String()] = HandshakeStart(conn, remote, key) + bytes = 0 + } select { case <-termSignal: finished = true @@ -248,9 +256,11 @@ p = state.Client(conn, key, udpPktData) } if p != nil { fmt.Print("[HS-OK]") + if peer == nil { + go ScriptCall(upPath) + } peer = p delete(states, addr) - go ScriptCall(upPath) } continue } @@ -279,6 +289,7 @@ } peer.nonceRecv = nonceRecv timeouts = 0 frame = buf[S20BS : S20BS+udpPkt.size-NonceSize-poly1305.TagSize] + bytes += len(frame) if string(frame[0:HeartBeatSize]) == HeartBeatMark { continue } @@ -312,6 +323,7 @@ copy(buf[S20BS-NonceSize:S20BS], nonce) copy(keyAuth[:], buf[:KeySize]) dataToSend := buf[S20BS-NonceSize : S20BS+ethPktSize] poly1305.Sum(tag, dataToSend, keyAuth) + bytes += len(dataToSend) if _, err := conn.WriteTo(append(dataToSend, tag[:]...), peer.addr); err != nil { log.Println("Error sending UDP", err) }