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

@ -60,6 +60,7 @@ const (
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]
CSOTunKeepAlive // client tunnel heartbeat
CSOTunDisconn // server -> client: tunnel rport disconnected CSOTunDisconn // server -> client: tunnel rport disconnected
CSOTunHangup // client -> server: tunnel lport hung up CSOTunHangup // client -> server: tunnel lport hung up
) )

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

@ -46,6 +46,7 @@ type (
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
KeepAlive uint // must be reset by client to keep server dial() alive
Ctl chan rune //See TunCtl_* consts Ctl chan rune //See TunCtl_* consts
Data chan []byte 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)