From e57d97d3e68befc5dd14ba07908c2a9272cd430d Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Wed, 26 Sep 2018 22:57:36 -0700 Subject: [PATCH] Changed many funcs to take *hkexnet.Conn to allow tracking of packets sent, total bytes sent and experimental moving avg chaff --- hkexnet/hkexnet.go | 48 ++++++++++++++++++++++++++++++++++++---------- hkexshd/hkexshd.go | 8 ++++---- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/hkexnet/hkexnet.go b/hkexnet/hkexnet.go index 04312f5..da217a6 100644 --- a/hkexnet/hkexnet.go +++ b/hkexnet/hkexnet.go @@ -80,9 +80,11 @@ type ( Rows uint16 Cols uint16 - chaff ChaffConfig + chaff ChaffConfig + totBytes *uint64 // total bytes xmitted so far + totPackets *uint64 // total packets xmitted so far - closeStat *CSOType // close status (CSOExitStatus) + closeStat *CSOType // close status (CSOExitStatus) r cipher.Stream //read cipherStream rm hash.Hash w cipher.Stream //write cipherStream @@ -259,7 +261,7 @@ func Dial(protocol string, ipport string, extensions ...string) (hc *Conn, err e // NOTE: kex default of KEX_HERRADURA may be overridden by // future extension args to applyConnExtensions(), which is // called prior to Dial() - hc = &Conn{m: &sync.Mutex{}, c: c, closeStat: new(CSOType), h: hkex.New(0, 0), dBuf: new(bytes.Buffer)} + hc = &Conn{m: &sync.Mutex{}, c: c, closeStat: new(CSOType), h: hkex.New(0, 0), dBuf: new(bytes.Buffer), totBytes: new(uint64), totPackets: new(uint64)} hc.applyConnExtensions(extensions...) // TODO: Factor out ALL params following this to helpers for @@ -387,18 +389,18 @@ func (hl HKExListener) Addr() net.Addr { // Accept a client connection, conforming to net.Listener.Accept() // // See go doc net.Listener.Accept -func (hl *HKExListener) Accept() (hc Conn, err error) { +func (hl *HKExListener) Accept() (hc *Conn, err error) { // Open raw Conn c c, err := hl.l.Accept() if err != nil { - hc := Conn{m: &sync.Mutex{}, c: nil, h: nil, closeStat: new(CSOType), cipheropts: 0, opts: 0, - r: nil, w: nil} + hc := &Conn{m: &sync.Mutex{}, c: nil, h: nil, closeStat: new(CSOType), cipheropts: 0, opts: 0, + r: nil, w: nil, totBytes: new(uint64), totPackets: new(uint64)} return hc, err } log.Println("[Accepted]") - hc = Conn{ /*kex: from client,*/ m: &sync.Mutex{}, c: c, h: hkex.New(0, 0), closeStat: new(CSOType), WinCh: make(chan WinSize, 1), - dBuf: new(bytes.Buffer)} + hc = &Conn{ /*kex: from client,*/ m: &sync.Mutex{}, c: c, h: hkex.New(0, 0), closeStat: new(CSOType), WinCh: make(chan WinSize, 1), + dBuf: new(bytes.Buffer), totBytes: new(uint64), totPackets: new(uint64)} // TODO: Factor out ALL params following this to helpers for // specific KEx algs @@ -413,7 +415,7 @@ func (hl *HKExListener) Accept() (hc Conn, err error) { switch kexAlg { case KEX_HERRADURA: log.Printf("[KEx alg %d accepted]\n", kexAlg) - if HKExAcceptSetup(c, &hc) != nil { + if HKExAcceptSetup(c, hc) != nil { return hc, nil } default: @@ -607,6 +609,18 @@ func (hc *Conn) WritePacket(b []byte, op byte) (n int, err error) { err = binary.Write(hc.c, binary.BigEndian, payloadLen) if err == nil { n, err = hc.c.Write(wb.Bytes()) + + // If regular traffic, update running avg stats + if op != CSOChaff { + if *hc.totBytes+uint64(n) > *hc.totBytes { + *hc.totBytes = *hc.totBytes + uint64(n) + *hc.totPackets = *hc.totPackets + 1 + log.Printf("totPackets:%d totBytes:%d\n", + *hc.totPackets, *hc.totBytes) + } else { + //overflow, don't add to totBytes + } + } } else { //fmt.Println("[c]WriteError!") } @@ -653,7 +667,21 @@ func (hc *Conn) chaffHelper() { for { var nextDuration int if hc.chaff.enabled { - bufTmp := make([]byte, rand.Intn(int(hc.chaff.szMax))) + var bufTmp []byte + if false { + bufTmp = make([]byte, rand.Intn(int(hc.chaff.szMax))) + } else { + // size chaff with running avg of actual traffic + denom := *hc.totPackets + numer := *hc.totBytes + if numer == 0 { + numer = uint64(rand.Intn(63) + 1) + } + if denom == 0 { + denom = 1 + } + bufTmp = make([]byte, (numer / denom)) + } min := int(hc.chaff.msecsMin) nextDuration = rand.Intn(int(hc.chaff.msecsMax)-min) + min _, _ = rand.Read(bufTmp) diff --git a/hkexshd/hkexshd.go b/hkexshd/hkexshd.go index 6a1cca4..7594be2 100755 --- a/hkexshd/hkexshd.go +++ b/hkexshd/hkexshd.go @@ -34,7 +34,7 @@ import ( /* -------------------------------------------------------------- */ // Perform a client->server copy -func runClientToServerCopyAs(who, ttype string, conn hkexnet.Conn, fpath string, chaffing bool) (err error, exitStatus uint32) { +func runClientToServerCopyAs(who, ttype string, conn *hkexnet.Conn, fpath string, chaffing bool) (err error, exitStatus uint32) { u, _ := user.Lookup(who) var uid, gid uint32 fmt.Sscanf(u.Uid, "%d", &uid) @@ -134,7 +134,7 @@ func runClientToServerCopyAs(who, ttype string, conn hkexnet.Conn, fpath string, } // Perform a server->client copy -func runServerToClientCopyAs(who, ttype string, conn hkexnet.Conn, srcPath string, chaffing bool) (err error, exitStatus uint32) { +func runServerToClientCopyAs(who, ttype string, conn *hkexnet.Conn, srcPath string, chaffing bool) (err error, exitStatus uint32) { u, _ := user.Lookup(who) var uid, gid uint32 fmt.Sscanf(u.Uid, "%d", &uid) @@ -220,7 +220,7 @@ func runServerToClientCopyAs(who, ttype string, conn hkexnet.Conn, srcPath strin // Run a command (via default shell) as a specific user // // Uses ptys to support commands which expect a terminal. -func runShellAs(who, ttype string, cmd string, interactive bool, conn hkexnet.Conn, chaffing bool) (err error, exitStatus uint32) { +func runShellAs(who, ttype string, cmd string, interactive bool, conn *hkexnet.Conn, chaffing bool) (err error, exitStatus uint32) { var wg sync.WaitGroup u, _ := user.Lookup(who) var uid, gid uint32 @@ -416,7 +416,7 @@ func main() { // Handle the connection in a new goroutine. // The loop then returns to accepting, so that // multiple connections may be served concurrently. - go func(hc hkexnet.Conn) (e error) { + go func(hc *hkexnet.Conn) (e error) { defer hc.Close() //We use io.ReadFull() here to guarantee we consume