mirror of https://gogs.blitter.com/RLabs/xs
Tunnel rough work-in-progress; data sent (wrong length) and CSOTunClose handling needs work, but it's a start...
This commit is contained in:
parent
1e6da733a2
commit
632f24354b
|
@ -33,8 +33,8 @@ type KEXAlg uint8
|
||||||
// Extended exit status codes - indicate comm/pty issues
|
// Extended exit status codes - indicate comm/pty issues
|
||||||
// rather than remote end normal UNIX exit codes
|
// rather than remote end normal UNIX exit codes
|
||||||
const (
|
const (
|
||||||
CSENone = 1024 + iota
|
CSENone = 1024 + iota
|
||||||
CSEBadAuth // Failed login password
|
//CSEBadAuth // Failed login password
|
||||||
CSETruncCSO // No CSOExitStatus in payload
|
CSETruncCSO // No CSOExitStatus in payload
|
||||||
CSEStillOpen // Channel closed unexpectedly
|
CSEStillOpen // Channel closed unexpectedly
|
||||||
CSEExecFail // cmd.Start() (exec) failed
|
CSEExecFail // cmd.Start() (exec) failed
|
||||||
|
@ -50,8 +50,11 @@ const (
|
||||||
CSONone = iota // No error, normal packet
|
CSONone = iota // No error, normal packet
|
||||||
CSOHmacInvalid // HMAC mismatch detected on remote end
|
CSOHmacInvalid // HMAC mismatch detected on remote end
|
||||||
CSOTermSize // set term size (rows:cols)
|
CSOTermSize // set term size (rows:cols)
|
||||||
CSOTunReq // client tunnel open request (dstport)
|
CSOTunReq // client tunnel open request (dstport)
|
||||||
CSOTunAck // server tunnel open ack (tunport)
|
CSOTunAck // server tunnel open ack (tunport)
|
||||||
|
CSOTunData // packet contains [rport:data]
|
||||||
|
CSOTunClose // request to close connection (tunnel stays open)
|
||||||
|
CSOTunRefused // tunnel has died or could not be established to rport
|
||||||
CSOExitStatus // Remote cmd exit status
|
CSOExitStatus // Remote cmd exit status
|
||||||
CSOChaff // Dummy packet, do not pass beyond decryption
|
CSOChaff // Dummy packet, do not pass beyond decryption
|
||||||
)
|
)
|
||||||
|
|
|
@ -73,30 +73,6 @@ type (
|
||||||
szMax uint // max size in bytes
|
szMax uint // max size in bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tunnels
|
|
||||||
// --
|
|
||||||
// 1. client is given (lport, remhost, rport) by local user
|
|
||||||
// 2. client sends [CSOTunReq:rport] to server
|
|
||||||
// client=> [CSOTunReq:rport] =>remhost
|
|
||||||
// t := TunEndpoint{dataPort: lport, peer: remhost}
|
|
||||||
//
|
|
||||||
// remhost allocates dynamic (Tport)
|
|
||||||
// t := TunEndpoint{dataPort: rport, peer: client, tunPort: Tport}
|
|
||||||
//
|
|
||||||
// remhost spawns goroutine forwarding data between (Tport,rport)
|
|
||||||
// client<= [CSOTunAck:Tport] <=remhost
|
|
||||||
// t.tunPort = Tport
|
|
||||||
//
|
|
||||||
// client spawns goroutine forwarding data between (lport,Tport)
|
|
||||||
// --
|
|
||||||
|
|
||||||
// TunEndpoint [securePort:peer:dataPort]
|
|
||||||
TunEndpoint struct {
|
|
||||||
TunPort uint16
|
|
||||||
Peer string //net.Addr
|
|
||||||
DataPort uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conn is a connection wrapping net.Conn with KEX & session state
|
// Conn is a connection wrapping net.Conn with KEX & session state
|
||||||
Conn struct {
|
Conn struct {
|
||||||
kex KEXAlg // KEX/KEM propsal (client -> server)
|
kex KEXAlg // KEX/KEM propsal (client -> server)
|
||||||
|
@ -109,8 +85,7 @@ type (
|
||||||
Cols uint16
|
Cols uint16
|
||||||
|
|
||||||
chaff ChaffConfig
|
chaff ChaffConfig
|
||||||
|
tuns map[uint16]chan []byte
|
||||||
tuns []TunEndpoint
|
|
||||||
|
|
||||||
closeStat *CSOType // close status (CSOExitStatus)
|
closeStat *CSOType // close status (CSOExitStatus)
|
||||||
r cipher.Stream //read cipherStream
|
r cipher.Stream //read cipherStream
|
||||||
|
@ -127,7 +102,7 @@ var (
|
||||||
|
|
||||||
// Return string (suitable as map key) for a tunnel endpoint
|
// Return string (suitable as map key) for a tunnel endpoint
|
||||||
func (t *TunEndpoint) String() string {
|
func (t *TunEndpoint) String() string {
|
||||||
return fmt.Sprintf("[%d:%s:%d]", t.DataPort, t.Peer, t.TunPort)
|
return fmt.Sprintf("[%d:%s:%d]", t.Lport, t.Peer, t.Rport)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _initLogging(d bool, c string, f logger.Priority) {
|
func _initLogging(d bool, c string, f logger.Priority) {
|
||||||
|
@ -261,12 +236,6 @@ func _new(kexAlg KEXAlg, conn *net.Conn) (hc *Conn, e error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *Conn) applyConnExtensions(extensions ...string) {
|
func (hc *Conn) applyConnExtensions(extensions ...string) {
|
||||||
//fmt.Printf("CSENone:%d CSEBadAuth:%d CSETruncCSO:%d CSEStillOpen:%d CSEExecFail:%d CSEPtyExecFail:%d\n",
|
|
||||||
// CSENone, CSEBadAuth, CSETruncCSO, CSEStillOpen, CSEExecFail, CSEPtyExecFail)
|
|
||||||
|
|
||||||
//fmt.Printf("CSONone:%d CSOHmacInvalid:%d CSOTermSize:%d CSOExitStatus:%d CSOChaff:%d\n",
|
|
||||||
// CSONone, CSOHmacInvalid, CSOTermSize, CSOExitStatus, CSOChaff)
|
|
||||||
|
|
||||||
for _, s := range extensions {
|
for _, s := range extensions {
|
||||||
switch s {
|
switch s {
|
||||||
case "C_AES_256":
|
case "C_AES_256":
|
||||||
|
@ -821,16 +790,20 @@ func (hc Conn) Read(b []byte) (n int, err error) {
|
||||||
}
|
}
|
||||||
hc.Close()
|
hc.Close()
|
||||||
} else if ctrlStatOp == CSOTunReq {
|
} else if ctrlStatOp == CSOTunReq {
|
||||||
// This should ONLY be sent from client -> server!
|
// Client wants a tunnel set up - args [lport:rport]
|
||||||
// TODO: Hmm. should this package (hkexnet) take a 'server'/'client' context
|
lport := binary.BigEndian.Uint16(payloadBytes)
|
||||||
// in order to know how to handle mis-uses?
|
rport := binary.BigEndian.Uint16(payloadBytes[2:4])
|
||||||
addrs, _ := net.InterfaceAddrs()
|
startServerTunnel(&hc, lport, rport)
|
||||||
t := TunEndpoint{Peer: addrs[0].String()}
|
} else if ctrlStatOp == CSOTunData {
|
||||||
t.TunPort = binary.BigEndian.Uint16(payloadBytes)
|
lport := binary.BigEndian.Uint16(payloadBytes)
|
||||||
//fmt.Sscanf(string(payloadBytes), "%d", &t.tunPort)
|
rport := binary.BigEndian.Uint16(payloadBytes[2:4])
|
||||||
Log.Notice(fmt.Sprintf("[TODO: Client Tunnel Open Request - traffic for server %s, port %d]\n", t.Peer, t.TunPort))
|
fmt.Printf("[Got CSOTunData: [lport %d:rport %d] data:%v\n", lport, rport, payloadBytes[4:])
|
||||||
} else if ctrlStatOp == CSOTunAck {
|
hc.tuns[rport] <- payloadBytes[4:]
|
||||||
Log.Notice("[Server Tunnel Open Ack - TODO]\n")
|
} else if ctrlStatOp == CSOTunClose {
|
||||||
|
lport := binary.BigEndian.Uint16(payloadBytes)
|
||||||
|
rport := binary.BigEndian.Uint16(payloadBytes[2:4])
|
||||||
|
fmt.Printf("[Got CSOTunClose: [lport %d:rport %d]\n", lport, rport)
|
||||||
|
hc.tuns[rport] = nil
|
||||||
} else {
|
} else {
|
||||||
hc.dBuf.Write(payloadBytes)
|
hc.dBuf.Write(payloadBytes)
|
||||||
//log.Printf("hc.dBuf: %s\n", hex.Dump(hc.dBuf.Bytes()))
|
//log.Printf("hc.dBuf: %s\n", hex.Dump(hc.dBuf.Bytes()))
|
||||||
|
|
|
@ -337,12 +337,27 @@ func rejectUserMsg() string {
|
||||||
return "Begone, " + spinsult.GetSentence() + "\r\n"
|
return "Begone, " + spinsult.GetSentence() + "\r\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestTunnel(c *hkexnet.Conn, dp uint16, p string /*net.Addr*/, tp uint16) (t hkexnet.TunEndpoint) {
|
// Transmit request to server for it to set up the remote end of a tunnel
|
||||||
t = hkexnet.TunEndpoint{DataPort: dp, Peer: p, TunPort: tp}
|
//
|
||||||
|
// Server responds with [CSOTunAck:rport] or [CSOTunRefused:rport]
|
||||||
|
func requestTunnel(hc *hkexnet.Conn, lp uint16, p string /*net.Addr*/, rp uint16) (t hkexnet.TunEndpoint) {
|
||||||
var bTmp bytes.Buffer
|
var bTmp bytes.Buffer
|
||||||
binary.Write(&bTmp, binary.BigEndian, t.DataPort)
|
binary.Write(&bTmp, binary.BigEndian, lp)
|
||||||
c.WritePacket(bTmp.Bytes(), hkexnet.CSOTunReq)
|
binary.Write(&bTmp, binary.BigEndian, rp)
|
||||||
|
hc.WritePacket(bTmp.Bytes(), hkexnet.CSOTunReq)
|
||||||
|
|
||||||
|
// Server should reply immediately with success (lport:rport) or
|
||||||
|
// refusal (lport:0)
|
||||||
|
var lportReply, rportReply uint16
|
||||||
|
errL := binary.Read(hc, binary.BigEndian, &lportReply)
|
||||||
|
errR := binary.Read(hc, binary.BigEndian, &rportReply)
|
||||||
|
if errL == nil && errR == nil {
|
||||||
|
fmt.Printf("Server established tunnel [%d:%d]\n", lportReply, rportReply)
|
||||||
|
hkexnet.StartClientTunnel(hc, lp, rp)
|
||||||
|
} else {
|
||||||
|
fmt.Println("FAILED reading remPort")
|
||||||
|
}
|
||||||
|
t = hkexnet.TunEndpoint{Lport: lportReply, Peer: p, Rport: rportReply}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,8 +646,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if shellMode {
|
if shellMode {
|
||||||
// TODO: tunnel setup would be here or within doShellMode()
|
|
||||||
|
|
||||||
// TESTING - tunnel
|
// TESTING - tunnel
|
||||||
remAddrs, _ := net.LookupHost(remoteHost)
|
remAddrs, _ := net.LookupHost(remoteHost)
|
||||||
t := requestTunnel(&conn, 6001, remAddrs[0], 7001)
|
t := requestTunnel(&conn, 6001, remAddrs[0], 7001)
|
||||||
|
|
Loading…
Reference in New Issue