Tunnel keepalives from client implemented. If client dies/exits unexpectedly the server

tunnel will disconnect from rport in a timely manner.

Signed-off-by: Russ Magee <rmagee@gmail.com>
This commit is contained in:
Russ Magee 2018-11-11 22:46:39 -08:00
parent 709f2ae3dd
commit b0f614f82e
4 changed files with 41 additions and 13 deletions

View file

@ -55,13 +55,14 @@ const (
CSOChaff // Dummy packet, do not pass beyond decryption CSOChaff // Dummy packet, do not pass beyond decryption
// Tunnel setup/control/status // Tunnel setup/control/status
CSOTunSetup // client -> server tunnel setup request (dstport) CSOTunSetup // client -> server tunnel setup request (dstport)
CSOTunSetupAck // server -> client tunnel setup ack CSOTunSetupAck // server -> client tunnel setup ack
CSOTunAccept // client -> server: tunnel client got an Accept() CSOTunAccept // client -> server: tunnel client got an Accept()
CSOTunRefused // server -> client: tunnel rport connection refused CSOTunRefused // server -> client: tunnel rport connection refused
CSOTunData // packet contains tunnel data [rport:data] CSOTunData // packet contains tunnel data [rport:data]
CSOTunDisconn // server -> client: tunnel rport disconnected CSOTunKeepAlive // client tunnel heartbeat
CSOTunHangup // client -> server: tunnel lport hung up CSOTunDisconn // server -> client: tunnel rport disconnected
CSOTunHangup // client -> server: tunnel lport hung up
) )
// TunEndpoint.tunCtl control values - used to control workers for client or server tunnels // TunEndpoint.tunCtl control values - used to control workers for client or server tunnels

View file

@ -877,6 +877,15 @@ func (hc Conn) Read(b []byte) (n int, err error) {
} else { } else {
logger.LogDebug(fmt.Sprintf("[Attempt to write data to closed tun [%d:%d]", lport, rport)) logger.LogDebug(fmt.Sprintf("[Attempt to write data to closed tun [%d:%d]", lport, rport))
} }
} else if ctrlStatOp == CSOTunKeepAlive {
// client side has sent keepalive for tunnels -- if client
// dies or exits unexpectedly the absence of this will
// let the server know to hang up on Dial()ed server rports.
_ = binary.BigEndian.Uint16(payloadBytes[0:2])
//logger.LogDebug(fmt.Sprintf("[Server] Got CSOTunKeepAlive"))
for _, t := range *hc.tuns {
t.KeepAlive = 0
}
} else if ctrlStatOp == CSONone { } else if ctrlStatOp == CSONone {
hc.dBuf.Write(payloadBytes) hc.dBuf.Write(payloadBytes)
} else { } else {

View file

@ -42,12 +42,13 @@ type (
// TunEndpoint [securePort:peer:dataPort] // TunEndpoint [securePort:peer:dataPort]
TunEndpoint struct { TunEndpoint struct {
Rport uint16 // Names are from client's perspective Rport uint16 // Names are from client's perspective
Lport uint16 // ... ie., RPort is on server, LPort is on client Lport uint16 // ... ie., RPort is on server, LPort is on client
Peer string //net.Addr Peer string //net.Addr
Died bool // set by client upon receipt of a CSOTunDisconn Died bool // set by client upon receipt of a CSOTunDisconn
Ctl chan rune //See TunCtl_* consts KeepAlive uint // must be reset by client to keep server dial() alive
Data chan []byte Ctl chan rune //See TunCtl_* consts
Data chan []byte
} }
) )
@ -328,6 +329,14 @@ func (hc *Conn) StartServerTunnel(lport, rport uint16) {
rBuf = append(tunDst.Bytes(), rBuf[:n]...) rBuf = append(tunDst.Bytes(), rBuf[:n]...)
hc.WritePacket(rBuf[:n+4], CSOTunData) hc.WritePacket(rBuf[:n+4], CSOTunData)
} }
if (*hc.tuns)[rport].KeepAlive > 50 {
(*hc.tuns)[rport].Died = true
logger.LogDebug("[ServerTun] worker A: Oh dear, client appears to have died. Hanging up rport Dial().")
} else {
(*hc.tuns)[rport].KeepAlive += 1
}
} }
logger.LogDebug("[ServerTun] worker A: exiting") logger.LogDebug("[ServerTun] worker A: exiting")
}() }()

View file

@ -26,6 +26,7 @@ import (
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
"time"
hkexsh "blitter.com/go/hkexsh" hkexsh "blitter.com/go/hkexsh"
"blitter.com/go/hkexsh/hkexnet" "blitter.com/go/hkexsh/hkexnet"
@ -638,6 +639,14 @@ func main() {
defer conn.ShutdownChaff() defer conn.ShutdownChaff()
} }
// Keepalive for any tunnels that may exist
go func() {
for {
time.Sleep(time.Duration(2) * time.Second)
conn.WritePacket([]byte{0,0}, hkexnet.CSOTunKeepAlive)
}
}()
if shellMode { if shellMode {
// TESTING - tunnel // TESTING - tunnel
remAddrs, _ := net.LookupHost(remoteHost) remAddrs, _ := net.LookupHost(remoteHost)