mirror of https://gogs.blitter.com/RLabs/xs
Chaffing slight improvements (rand size, timing). TODO: Move into hkexsh.Conn
This commit is contained in:
parent
b8a07e9648
commit
4d85236d16
48
hkexnet.go
48
hkexnet.go
|
@ -25,6 +25,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -391,7 +392,7 @@ func (c Conn) Read(b []byte) (n int, err error) {
|
||||||
|
|
||||||
// Throw away pkt if it's chaff (ie., caller to Read() won't see this data)
|
// Throw away pkt if it's chaff (ie., caller to Read() won't see this data)
|
||||||
if ctrlStatOp == CSOChaff {
|
if ctrlStatOp == CSOChaff {
|
||||||
log.Printf("[Chaff pkt, discarded]\n")
|
log.Printf("[Chaff pkt, discarded (len %d)]\n", decryptN)
|
||||||
} else if ctrlStatOp == CSOTermSize {
|
} else if ctrlStatOp == CSOTermSize {
|
||||||
fmt.Sscanf(string(payloadBytes), "%d %d", &c.Rows, &c.Cols)
|
fmt.Sscanf(string(payloadBytes), "%d %d", &c.Rows, &c.Cols)
|
||||||
log.Printf("[TermSize pkt: rows %v cols %v]\n", c.Rows, c.Cols)
|
log.Printf("[TermSize pkt: rows %v cols %v]\n", c.Rows, c.Cols)
|
||||||
|
@ -478,3 +479,48 @@ func (c Conn) WritePacket(b []byte, op byte) (n int, err error) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hkexsh.Copy() is a modified version of io.Copy() with locking,
|
||||||
|
// on a passed-in mutex, around the actual call to Write() to permit
|
||||||
|
// multiple producers to write hkexsh buffers to the same destination.
|
||||||
|
//
|
||||||
|
// (Used to generate chaff during sessions)
|
||||||
|
func Copy(m *sync.Mutex, dst io.Writer, src io.Reader) (written int64, err error) {
|
||||||
|
// // If the reader has a WriteTo method, use it to do the copy.
|
||||||
|
// // Avoids an allocation and a copy.
|
||||||
|
// if wt, ok := src.(io.WriterTo); ok {
|
||||||
|
// return wt.WriteTo(dst)
|
||||||
|
// }
|
||||||
|
// // Similarly, if the writer has a ReadFrom method, use it to do the copy.
|
||||||
|
// if rt, ok := dst.(io.ReaderFrom); ok {
|
||||||
|
// return rt.ReadFrom(src)
|
||||||
|
// }
|
||||||
|
|
||||||
|
buf := make([]byte, 32*1024)
|
||||||
|
for {
|
||||||
|
nr, er := src.Read(buf)
|
||||||
|
if nr > 0 {
|
||||||
|
m.Lock()
|
||||||
|
nw, ew := dst.Write(buf[0:nr])
|
||||||
|
m.Unlock()
|
||||||
|
if nw > 0 {
|
||||||
|
written += int64(nw)
|
||||||
|
}
|
||||||
|
if ew != nil {
|
||||||
|
err = ew
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if nr != nw {
|
||||||
|
err = io.ErrShortWrite
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if er != nil {
|
||||||
|
if er != io.EOF {
|
||||||
|
err = er
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -220,15 +221,19 @@ func main() {
|
||||||
ch <- syscall.SIGWINCH // Initial resize.
|
ch <- syscall.SIGWINCH // Initial resize.
|
||||||
|
|
||||||
// client chaffing goroutine
|
// client chaffing goroutine
|
||||||
|
// TODO: Consider making this a feature of hkexsh.Conn itself
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
m.Lock()
|
m.Lock()
|
||||||
conn.WritePacket([]byte("CHAFF"), hkexsh.CSOChaff)
|
chaff := make([]byte, rand.Intn(512))
|
||||||
|
nextDurationMin := 1000 //ms
|
||||||
|
nextDuration := rand.Intn(5000-nextDurationMin) + nextDurationMin
|
||||||
|
_, _ = rand.Read(chaff)
|
||||||
|
conn.WritePacket(chaff, hkexsh.CSOChaff)
|
||||||
m.Unlock()
|
m.Unlock()
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(time.Duration(nextDuration) * time.Millisecond)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -241,7 +246,7 @@ func main() {
|
||||||
// exit with outerr == nil
|
// exit with outerr == nil
|
||||||
//!_, outerr := io.Copy(conn, os.Stdin)
|
//!_, outerr := io.Copy(conn, os.Stdin)
|
||||||
_, outerr := func(m *sync.Mutex, conn *hkexsh.Conn, r io.Reader) (w int64, e error) {
|
_, outerr := func(m *sync.Mutex, conn *hkexsh.Conn, r io.Reader) (w int64, e error) {
|
||||||
return safeCopy(m, conn, r)
|
return hkexsh.Copy(m, conn, r)
|
||||||
}(m, conn, os.Stdin)
|
}(m, conn, os.Stdin)
|
||||||
|
|
||||||
if outerr != nil {
|
if outerr != nil {
|
||||||
|
@ -260,43 +265,3 @@ func main() {
|
||||||
// Wait until both stdin and stdout goroutines finish
|
// Wait until both stdin and stdout goroutines finish
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func safeCopy(m *sync.Mutex, dst io.Writer, src io.Reader) (written int64, err error) {
|
|
||||||
// // If the reader has a WriteTo method, use it to do the copy.
|
|
||||||
// // Avoids an allocation and a copy.
|
|
||||||
// if wt, ok := src.(io.WriterTo); ok {
|
|
||||||
// return wt.WriteTo(dst)
|
|
||||||
// }
|
|
||||||
// // Similarly, if the writer has a ReadFrom method, use it to do the copy.
|
|
||||||
// if rt, ok := dst.(io.ReaderFrom); ok {
|
|
||||||
// return rt.ReadFrom(src)
|
|
||||||
// }
|
|
||||||
|
|
||||||
buf := make([]byte, 32*1024)
|
|
||||||
for {
|
|
||||||
nr, er := src.Read(buf)
|
|
||||||
if nr > 0 {
|
|
||||||
m.Lock()
|
|
||||||
nw, ew := dst.Write(buf[0:nr])
|
|
||||||
m.Unlock()
|
|
||||||
if nw > 0 {
|
|
||||||
written += int64(nw)
|
|
||||||
}
|
|
||||||
if ew != nil {
|
|
||||||
err = ew
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if nr != nw {
|
|
||||||
err = io.ErrShortWrite
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if er != nil {
|
|
||||||
if er != io.EOF {
|
|
||||||
err = er
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue