sshpoke/patch/ssh_proto_patches.patch

142 lines
4.2 KiB
Diff

diff -Naru cryptolib/ssh/cipher.go pkg/proto/ssh/cipher.go
--- cryptolib/ssh/cipher.go 2023-11-24 21:59:11.581318943 +0300
+++ pkg/proto/ssh/cipher.go 2023-11-24 21:39:11.897832847 +0300
@@ -16,8 +16,8 @@
"hash"
"io"
- "golang.org/x/crypto/chacha20"
"github.com/Neur0toxine/sshpoke/pkg/proto/ssh/internal/poly1305"
+ "golang.org/x/crypto/chacha20"
)
const (
diff -Naru cryptolib/ssh/common.go pkg/proto/ssh/common.go
--- cryptolib/ssh/common.go 2023-11-24 21:59:11.677320636 +0300
+++ pkg/proto/ssh/common.go 2023-11-24 21:39:08.401775359 +0300
@@ -287,6 +287,9 @@
// The allowed MAC algorithms. If unspecified then a sensible default is
// used. Unsupported values are silently ignored.
MACs []string
+
+ // Called on every incoming handshake packet for client. Only receives data and extended data packets.
+ HandshakePacketReader func(p []byte)
}
// SetDefaults sets sensible values for unset fields in config. This is
diff -Naru cryptolib/ssh/handshake.go pkg/proto/ssh/handshake.go
--- cryptolib/ssh/handshake.go 2023-11-24 21:59:11.673320566 +0300
+++ pkg/proto/ssh/handshake.go 2023-11-24 21:59:05.113204819 +0300
@@ -401,6 +401,14 @@
t.printPacket(p, false)
}
+ if t.config.HandshakePacketReader != nil && p[0] == msgChannelData {
+ data, err := decode(p)
+ packetData, ok := data.(*channelDataMsg)
+ if err == nil && ok && packetData != nil {
+ t.config.HandshakePacketReader(packetData.Rest)
+ }
+ }
+
if first && p[0] != msgKexInit {
return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
}
diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
--- cryptolib/ssh/tcpip.go 2023-11-24 21:59:11.593319154 +0300
+++ pkg/proto/ssh/tcpip.go 2023-11-24 21:39:08.401775359 +0300
@@ -101,14 +101,18 @@
// ListenTCP requests the remote peer open a listening socket
// on laddr. Incoming connections will be available by calling
// Accept on the returned net.Listener.
-func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
+func (c *Client) ListenTCP(laddr *net.TCPAddr, fakeHost ...string) (net.Listener, error) {
c.handleForwardsOnce.Do(c.handleForwards)
if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
return c.autoPortListenWorkaround(laddr)
}
+ host := laddr.IP.String()
+ if len(fakeHost) > 0 {
+ host = fakeHost[0]
+ }
m := channelForwardMsg{
- laddr.IP.String(),
+ host,
uint32(laddr.Port),
}
// send message
@@ -133,7 +137,12 @@
}
// Register this forward, using the port number we obtained.
- ch := c.forwards.add(laddr)
+ var ch chan forward
+ if len(fakeHost) > 0 {
+ ch = c.forwards.add(laddr, fakeHost[0])
+ } else {
+ ch = c.forwards.add(laddr)
+ }
return &tcpListener{laddr, c, ch}, nil
}
@@ -142,7 +151,9 @@
// forward requests and the tcpListeners.
type forwardList struct {
sync.Mutex
- entries []forwardEntry
+ fdm sync.RWMutex
+ fakeDomainsMap map[string]string
+ entries []forwardEntry
}
// forwardEntry represents an established mapping of a laddr on a
@@ -160,17 +171,30 @@
raddr net.Addr // the raddr of the incoming connection
}
-func (l *forwardList) add(addr net.Addr) chan forward {
+func (l *forwardList) add(addr net.Addr, fakeHost ...string) chan forward {
l.Lock()
defer l.Unlock()
f := forwardEntry{
laddr: addr,
c: make(chan forward, 1),
}
+ if len(fakeHost) > 0 {
+ if l.fakeDomainsMap == nil {
+ l.fakeDomainsMap = make(map[string]string)
+ }
+ defer l.fdm.Unlock()
+ l.fdm.Lock()
+ l.fakeDomainsMap[fakeHost[0]] = l.ipFromAddr(addr)
+ }
l.entries = append(l.entries, f)
return f.c
}
+func (l *forwardList) ipFromAddr(addr net.Addr) string {
+ host, _, _ := net.SplitHostPort(addr.String())
+ return host
+}
+
// See RFC 4254, section 7.2
type forwardedTCPPayload struct {
Addr string
@@ -206,6 +230,15 @@
continue
}
+ l.fdm.RLock()
+ if addr, ok := l.fakeDomainsMap[payload.Addr]; ok {
+ payload.Addr = addr
+ }
+ if addr, ok := l.fakeDomainsMap[payload.OriginAddr]; ok {
+ payload.OriginAddr = addr
+ }
+ l.fdm.RUnlock()
+
// RFC 4254 section 7.2 specifies that incoming
// addresses should list the address, in string
// format. It is implied that this should be an IP