tunnel setup stubs moved into Conn Read()/Write() handling

This commit is contained in:
Russ Magee 2018-10-31 20:11:00 -07:00
parent 8ee0aea0b4
commit 081d88b9ad
3 changed files with 222 additions and 208 deletions

View file

@ -85,7 +85,7 @@ type (
Cols uint16
chaff ChaffConfig
tuns map[uint16]chan []byte
tuns map[uint16]*TunEndpoint
closeStat *CSOType // close status (CSOExitStatus)
r cipher.Stream //read cipherStream
@ -811,12 +811,16 @@ func (hc Conn) Read(b []byte) (n int, err error) {
}
hc.Close()
} else if ctrlStatOp == CSOTunSetup {
// Client wants a tunnel set up - args [lport:rport]
// server side tunnel setup in response to client
lport := binary.BigEndian.Uint16(payloadBytes)
rport := binary.BigEndian.Uint16(payloadBytes[2:4])
// spawn workers to listen for data and tunnel events
// via channel comms to hc.tuns[rport].tunCtl
startServerTunnel(&hc, lport, rport)
log.Printf("Tunnel setup [%d:%d]\r\n", lport, rport)
StartServerTunnel(&hc, lport, rport)
} else if ctrlStatOp == CSOTunSetupAck {
// client side has received ack from server
lport := binary.BigEndian.Uint16(payloadBytes)
rport := binary.BigEndian.Uint16(payloadBytes[2:4])
log.Printf("Tunnel ack [%d:%d]\r\n", lport, rport)
} else if ctrlStatOp == CSOTunData {
lport := binary.BigEndian.Uint16(payloadBytes)
rport := binary.BigEndian.Uint16(payloadBytes[2:4])
@ -825,16 +829,7 @@ func (hc Conn) Read(b []byte) (n int, err error) {
if hc.tuns[rport] == nil {
fmt.Printf("[Invalid rport:%d]\r\n", rport)
} else {
hc.tuns[rport] <- payloadBytes[4:]
}
//fmt.Printf("[Done stuffing hc.tuns[rport]\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]\r\n", lport, rport)
if hc.tuns[rport] != nil {
close(hc.tuns[rport])
hc.tuns[rport] = nil
hc.tuns[rport].Data <- payloadBytes[4:]
}
} else {
hc.dBuf.Write(payloadBytes)
@ -876,8 +871,8 @@ func (hc Conn) Write(b []byte) (n int, err error) {
return n, err
}
// Write a byte slice with specified ctrlStatusOp byte
func (hc *Conn) WritePacket(b []byte, op byte) (n int, err error) {
// Write a byte slice with specified ctrlStatOp byte
func (hc *Conn) WritePacket(b []byte, ctrlStatOp byte) (n int, err error) {
//log.Printf("[Encrypting...]\r\n")
var hmacOut []uint8
var payloadLen uint32
@ -886,7 +881,26 @@ func (hc *Conn) WritePacket(b []byte, op byte) (n int, err error) {
return 0, errors.New("Secure chan not ready for writing")
}
//Padding
if ctrlStatOp == CSOTunSetup {
// Client-side tunnel setup
lport := binary.BigEndian.Uint16(b)
rport := binary.BigEndian.Uint16(b[2:4])
// spawn workers to listen for data and tunnel events
// via channel comms to hc.tuns[rport].tunCtl
StartClientTunnel(hc, lport, rport)
// CSOTunSetup is written through to server side,
// see hc.Read()
} else if ctrlStatOp == CSOTunSetupAck {
lport := binary.BigEndian.Uint16(b)
rport := binary.BigEndian.Uint16(b[2:4])
if lport == 0 || rport == 0 {
log.Printf("Responded with tunnel setup nak [%d:%d]\r\n", lport, rport)
} else {
log.Printf("Responded with tunnel setup ack [%d:%d]\r\n", lport, rport)
}
}
//Padding prior to encryption
padSz := (rand.Intn(PAD_SZ) / 2) + (PAD_SZ / 2)
padLen := padSz - ((len(b) + padSz) % padSz)
if padLen == padSz {
@ -938,7 +952,6 @@ func (hc *Conn) WritePacket(b []byte, op byte) (n int, err error) {
}
log.Printf(" ->ctext:\r\n%s\r\n", hex.Dump(wb.Bytes()))
ctrlStatOp := op
err = binary.Write(*hc.c, binary.BigEndian, &ctrlStatOp)
if err == nil {
// Write hmac LSB, payloadLen followed by payload

View file

@ -11,12 +11,11 @@ package hkexnet
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"log"
//"fmt"
//"io"
//"log"
"net"
"blitter.com/go/hkexsh/logger"
//"blitter.com/go/hkexsh/logger"
)
type (
@ -43,7 +42,8 @@ type (
Rport uint16 // Names are from client's perspective
Lport uint16 // ... ie., RPort is on server, LPort is on client
Peer string //net.Addr
tunCtl chan<- rune //See TunCtl_* consts
Ctl chan<- rune //See TunCtl_* consts
Data chan []byte
}
TunPacket struct {
@ -52,104 +52,19 @@ type (
}
)
func startServerTunnel(hc *Conn, lport, rport uint16) {
if hc.tuns == nil {
hc.tuns = make(map[uint16]chan []byte)
}
if hc.tuns[rport] == nil {
hc.tuns[rport] = make(chan []byte, 32)
}
addrs, _ := net.InterfaceAddrs()
t := TunEndpoint{Peer: addrs[0].String(), Lport: lport, Rport: rport}
var resp bytes.Buffer
binary.Write(&resp, binary.BigEndian, t.Lport)
//var dialHangup chan<- bool
c, err := net.Dial("tcp", fmt.Sprintf(":%d", rport))
if err != nil {
logger.LogErr(fmt.Sprintf("Nothing is serving at rport :%d!", rport))
binary.Write(&resp, binary.BigEndian, uint16(0))
// Inform client of the tunPort
hc.WritePacket(resp.Bytes(), CSOTunRefused)
} else {
binary.Write(&resp, binary.BigEndian, t.Rport)
logger.LogNotice(fmt.Sprintf("[Tunnel Opened - %d:%s:%d]", t.Lport, t.Peer, t.Rport))
//
// worker to read data from the rport (to encrypt & send to client)
//
go func() {
defer func() {
//if hc.tuns[rport] != nil {
// close(hc.tuns[rport])
// hc.tuns[rport] = nil
//}
c.Close()
}()
var tunDst bytes.Buffer
binary.Write(&tunDst, binary.BigEndian, t.Lport)
binary.Write(&tunDst, binary.BigEndian, t.Rport)
for {
rBuf := make([]byte, 1024)
// Read data from c, encrypt/write via hc to client(lport)
n, e := c.Read(rBuf)
if e != nil {
if e == io.EOF {
logger.LogNotice(fmt.Sprintf("rport Disconnected: shutting down tunnel %v\n", t))
} else {
logger.LogErr(fmt.Sprintf("Read error from rport of tun %v\n%s", t, e))
}
hc.WritePacket(resp.Bytes(), CSOTunClose)
fmt.Printf("Closing server rport net.Dial()\n")
break
}
if n > 0 {
rBuf = append(tunDst.Bytes(), rBuf[:n]...)
logger.LogNotice(fmt.Sprintf("Got rport data:%v", tunDst.Bytes()))
hc.WritePacket(rBuf[:n+4], CSOTunData)
}
}
}()
// worker to read data from client (already decrypted) & fwd to rport
go func() {
defer func() {
//if hc.tuns[rport] != nil {
//close(hc.tuns[rport])
//hc.tuns[rport] = nil
//}
c.Close()
}()
for {
rData, ok := <-hc.tuns[rport]
if ok {
logger.LogNotice(fmt.Sprintf("Got client data:%v", rData))
c.Write(rData)
} else {
logger.LogErr("!!! ERROR reading from hc.tuns[] channel !!!")
break
}
}
}()
// Inform client of the tunPort
hc.WritePacket(resp.Bytes(), CSOTunAck)
}
}
func StartClientTunnel(hc *Conn, lport, rport uint16) {
go func() {
if hc.tuns == nil {
hc.tuns = make(map[uint16]chan []byte)
hc.tuns = make(map[uint16]*TunEndpoint)
}
if hc.tuns[rport] == nil {
hc.tuns[rport] = make(chan []byte, 32)
addrs, _ := net.InterfaceAddrs()
hc.tuns[rport] = &TunEndpoint{Peer: addrs[0].String(),
Lport: lport, Rport: rport, Ctl: make(chan<- rune)}
}
/*
go func() {
l, e := net.Listen("tcp", fmt.Sprintf(":%d", lport))
if e != nil {
fmt.Printf("[Could not get lport %d! (%s)\n", lport, e)
@ -226,4 +141,101 @@ func StartClientTunnel(hc *Conn, lport, rport uint16) {
}
}
}()
*/
}
func StartServerTunnel(hc *Conn, lport, rport uint16) {
if hc.tuns == nil {
hc.tuns = make(map[uint16]*TunEndpoint)
}
if hc.tuns[rport] == nil {
addrs, _ := net.InterfaceAddrs()
hc.tuns[rport] = &TunEndpoint{Peer: addrs[0].String(),
Lport: lport, Rport: rport, Ctl: make(chan<- rune)}
}
// Inform client of the tunPort
var resp bytes.Buffer
binary.Write(&resp, binary.BigEndian, hc.tuns[rport].Lport)
binary.Write(&resp, binary.BigEndian, hc.tuns[rport].Rport)
hc.WritePacket(resp.Bytes(), CSOTunSetupAck)
/*
t := TunEndpoint{Peer: addrs[0].String(), Lport: lport, Rport: rport}
var resp bytes.Buffer
binary.Write(&resp, binary.BigEndian, t.Lport)
//var dialHangup chan<- bool
c, err := net.Dial("tcp", fmt.Sprintf(":%d", rport))
if err != nil {
logger.LogErr(fmt.Sprintf("Nothing is serving at rport :%d!", rport))
binary.Write(&resp, binary.BigEndian, uint16(0))
// Inform client of the tunPort
hc.WritePacket(resp.Bytes(), CSOTunRefused)
} else {
binary.Write(&resp, binary.BigEndian, t.Rport)
logger.LogNotice(fmt.Sprintf("[Tunnel Opened - %d:%s:%d]", t.Lport, t.Peer, t.Rport))
//
// worker to read data from the rport (to encrypt & send to client)
//
go func() {
defer func() {
//if hc.tuns[rport] != nil {
// close(hc.tuns[rport])
// hc.tuns[rport] = nil
//}
c.Close()
}()
var tunDst bytes.Buffer
binary.Write(&tunDst, binary.BigEndian, t.Lport)
binary.Write(&tunDst, binary.BigEndian, t.Rport)
for {
rBuf := make([]byte, 1024)
// Read data from c, encrypt/write via hc to client(lport)
n, e := c.Read(rBuf)
if e != nil {
if e == io.EOF {
logger.LogNotice(fmt.Sprintf("rport Disconnected: shutting down tunnel %v\n", t))
} else {
logger.LogErr(fmt.Sprintf("Read error from rport of tun %v\n%s", t, e))
}
hc.WritePacket(resp.Bytes(), CSOTunClose)
fmt.Printf("Closing server rport net.Dial()\n")
break
}
if n > 0 {
rBuf = append(tunDst.Bytes(), rBuf[:n]...)
logger.LogNotice(fmt.Sprintf("Got rport data:%v", tunDst.Bytes()))
hc.WritePacket(rBuf[:n+4], CSOTunData)
}
}
}()
// worker to read data from client (already decrypted) & fwd to rport
go func() {
defer func() {
//if hc.tuns[rport] != nil {
//close(hc.tuns[rport])
//hc.tuns[rport] = nil
//}
c.Close()
}()
for {
rData, ok := <-hc.tuns[rport]
if ok {
logger.LogNotice(fmt.Sprintf("Got client data:%v", rData))
c.Write(rData)
} else {
logger.LogErr("!!! ERROR reading from hc.tuns[] channel !!!")
break
}
}
}()
}
*/
}

View file

@ -340,24 +340,18 @@ func rejectUserMsg() string {
// Transmit request to server for it to set up the remote end of a tunnel
//
// Server responds with [CSOTunAck:rport] or [CSOTunRefused:rport]
func requestTunnel(hc *hkexnet.Conn, lp uint16, p string /*net.Addr*/, rp uint16) (t hkexnet.TunEndpoint) {
// (handled in hkexnet.Read())
func reqTunnel(hc *hkexnet.Conn, lp uint16, p string /*net.Addr*/, rp uint16) {
// Write request to server so it can attempt to set up its end
var bTmp bytes.Buffer
binary.Write(&bTmp, binary.BigEndian, lp)
binary.Write(&bTmp, binary.BigEndian, rp)
hc.WritePacket(bTmp.Bytes(), hkexnet.CSOTunReq)
hc.WritePacket(bTmp.Bytes(), hkexnet.CSOTunSetup)
// hkexnet.WritePacket() handles processing of client side tun setup,
// calling hkexnet.StartClientTunnel()
// 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]\r\n", lportReply, rportReply)
hkexnet.StartClientTunnel(hc, lp, rp)
} else {
fmt.Println("FAILED reading remPort")
}
t = hkexnet.TunEndpoint{Lport: lportReply, Peer: p, Rport: rportReply}
// Server should reply immediately with CSOTunSetupAck[lport:rport]
// hkexnet.Read() on server side handles server side tun setup.
return
}
@ -648,12 +642,7 @@ func main() {
if shellMode {
// TESTING - tunnel
remAddrs, _ := net.LookupHost(remoteHost)
t := requestTunnel(&conn, 6001, remAddrs[0], 7001)
_ = t
//t := hkexnet.TunEndpoint{DataPort: 6001, Peer: nil, TunPort: 7001}
//var bTmp bytes.Buffer
//binary.Write(&bTmp, binary.BigEndian, t.DataPort)
//conn.WritePacket(bTmp.Bytes(), hkexnet.CSOTunReq)
reqTunnel(&conn, 6001, remAddrs[0], 7001)
// END TESTING - tunnel
doShellMode(isInteractive, &conn, oldState, rec)