Signed-off-by: Sergey Matveev <stargrave@stargrave.org>
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.
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
+ HeartBeatSize = 12
+ HeartBeatMark = "\x00\x00\x00HEARTBEAT"
var udpPkt *UDPPkt
var udpPktData []byte
var ethPktSize int
var udpPkt *UDPPkt
var udpPktData []byte
var ethPktSize int
var addr string
var peer *Peer
var p *Peer
var addr string
var peer *Peer
var p *Peer
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 {
}
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 {
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)