ssh: localhost remote by default, auto username, update proto lib
This commit is contained in:
parent
57af057708
commit
64fa306f8d
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -69,9 +70,21 @@ func New(ctx context.Context, name string, params config.DriverParams) (base.Dri
|
|||||||
return drv, nil
|
return drv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *SSH) getUser() string {
|
||||||
|
if d.params.Auth.User != "" {
|
||||||
|
return d.params.Auth.User
|
||||||
|
}
|
||||||
|
userData, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
d.Log().Warn("cannot get current user name - using 'root'")
|
||||||
|
return "root"
|
||||||
|
}
|
||||||
|
return userData.Username
|
||||||
|
}
|
||||||
|
|
||||||
func (d *SSH) forward(val sshtun.Forward, domainMatcher func(string)) conn {
|
func (d *SSH) forward(val sshtun.Forward, domainMatcher func(string)) conn {
|
||||||
tun := sshtun.New(d.params.Address,
|
tun := sshtun.New(d.params.Address,
|
||||||
d.params.Auth.User,
|
d.getUser(),
|
||||||
d.auth,
|
d.auth,
|
||||||
sshtun.TunnelConfig{
|
sshtun.TunnelConfig{
|
||||||
Forward: val,
|
Forward: val,
|
||||||
@ -307,7 +320,7 @@ func (d *SSH) remoteEndpoint(remoteHost string) sshtun.Endpoint {
|
|||||||
}
|
}
|
||||||
if remoteHost == "" && !d.params.FakeRemoteHost {
|
if remoteHost == "" && !d.params.FakeRemoteHost {
|
||||||
// Listen on all interfaces if no host was provided.
|
// Listen on all interfaces if no host was provided.
|
||||||
remoteHost = "0.0.0.0"
|
remoteHost = "127.0.0.1"
|
||||||
}
|
}
|
||||||
return sshtun.Endpoint{
|
return sshtun.Endpoint{
|
||||||
Host: remoteHost,
|
Host: remoteHost,
|
||||||
|
@ -151,6 +151,7 @@ func (t *Tunnel) connect(ctx context.Context,
|
|||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
_ = sess.Wait()
|
_ = sess.Wait()
|
||||||
|
t.log.Debug("main session has been terminated")
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/Neur0toxine/sshpoke/internal/server/driver/base"
|
"github.com/Neur0toxine/sshpoke/internal/server/driver/base"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/server/driver/plugin"
|
"github.com/Neur0toxine/sshpoke/internal/server/driver/plugin"
|
||||||
"github.com/Neur0toxine/sshpoke/pkg/dto"
|
"github.com/Neur0toxine/sshpoke/pkg/dto"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
@ -26,6 +27,7 @@ type Manager struct {
|
|||||||
statusLock sync.RWMutex
|
statusLock sync.RWMutex
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
defaultServer string
|
defaultServer string
|
||||||
|
log *zap.SugaredLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerStatus struct {
|
type ServerStatus struct {
|
||||||
@ -47,23 +49,24 @@ func NewManager(ctx context.Context, servers []config.Server, defaultServer stri
|
|||||||
statusMap: make(map[string]ServerStatus),
|
statusMap: make(map[string]ServerStatus),
|
||||||
forwards: make(map[string]bool),
|
forwards: make(map[string]bool),
|
||||||
defaultServer: defaultServer,
|
defaultServer: defaultServer,
|
||||||
|
log: logger.Sugar.With("component", "manager"),
|
||||||
}
|
}
|
||||||
for _, serverConfig := range servers {
|
for _, serverConfig := range servers {
|
||||||
server, err := driver.New(ctx, serverConfig.Name, serverConfig.Driver, serverConfig.Params)
|
server, err := driver.New(ctx, serverConfig.Name, serverConfig.Driver, serverConfig.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Sugar.Errorf("cannot initialize server '%s': %s", serverConfig.Name, err)
|
m.log.Errorf("cannot initialize server '%s': %s", serverConfig.Name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
server.SetEventStatusCallback(m.eventStatusCallback(server.Name()))
|
server.SetEventStatusCallback(m.eventStatusCallback(server.Name()))
|
||||||
if server.Driver() == config.DriverPlugin {
|
if server.Driver() == config.DriverPlugin {
|
||||||
pl := server.(plugin.Plugin)
|
pl := server.(plugin.Plugin)
|
||||||
if pl.Token() == "" {
|
if pl.Token() == "" {
|
||||||
logger.Sugar.Warnf("server '%s' will not work because it doesn't have a token", pl.Name())
|
m.log.Warnf("server '%s' will not work because it doesn't have a token", pl.Name())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
existing, found := m.plugins[pl.Token()]
|
existing, found := m.plugins[pl.Token()]
|
||||||
if found {
|
if found {
|
||||||
logger.Sugar.Fatalw("two plugins cannot have the same token",
|
m.log.Fatalw("two plugins cannot have the same token",
|
||||||
"plugin1", existing.Name(), "plugin2", pl.Name(), "token", pl.Token())
|
"plugin1", existing.Name(), "plugin2", pl.Name(), "token", pl.Token())
|
||||||
}
|
}
|
||||||
m.plugins[pl.Token()] = pl
|
m.plugins[pl.Token()] = pl
|
||||||
@ -114,7 +117,7 @@ func (m *Manager) eventStatusCallback(serverName string) base.EventStatusCallbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) processEventStatus(serverName string, event dto.EventStatus) {
|
func (m *Manager) processEventStatus(serverName string, event dto.EventStatus) {
|
||||||
logger.Sugar.Debugw("received EventStatus from server",
|
m.log.Debugw("received EventStatus from server",
|
||||||
"serverName", serverName, "eventStatus", event)
|
"serverName", serverName, "eventStatus", event)
|
||||||
item, found := docker.Default.GetContainer(event.ID, true)
|
item, found := docker.Default.GetContainer(event.ID, true)
|
||||||
if !found {
|
if !found {
|
||||||
@ -175,10 +178,16 @@ func (m *Manager) markAndSweepForwards() {
|
|||||||
m.forwards[id] = false // unmark
|
m.forwards[id] = false // unmark
|
||||||
} else {
|
} else {
|
||||||
if state {
|
if state {
|
||||||
m.processEventStatus(serverName, dto.EventStatus{
|
err := m.ProcessEvent(dto.Event{
|
||||||
Type: dto.EventStop,
|
Type: dto.EventStop,
|
||||||
ID: containerID,
|
Container: dto.Container{
|
||||||
|
ID: containerID,
|
||||||
|
Server: serverName,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
m.log.Warnf("cannot process mark-and-sweep event: %s", err)
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
m.forwards[id] = true // mark
|
m.forwards[id] = true // mark
|
||||||
|
@ -1,38 +1,20 @@
|
|||||||
diff -Naru cryptolib/ssh/cipher.go pkg/proto/ssh/cipher.go
|
diff -Naru cryptolib/ssh/cipher.go pkg/proto/ssh/cipher.go
|
||||||
--- cryptolib/ssh/cipher.go 2023-11-21 18:52:03.117248053 +0300
|
--- cryptolib/ssh/cipher.go 2023-11-24 21:59:11.581318943 +0300
|
||||||
+++ pkg/proto/ssh/cipher.go 2023-11-21 17:19:04.688042738 +0300
|
+++ pkg/proto/ssh/cipher.go 2023-11-24 21:39:11.897832847 +0300
|
||||||
@@ -16,8 +16,8 @@
|
@@ -16,8 +16,8 @@
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
- "golang.org/x/crypto/chacha20"
|
- "golang.org/x/crypto/chacha20"
|
||||||
"github.com/Neur0toxine/sshpoke/pkg/proto/ssh/internal/poly1305"
|
"github.com/Neur0toxine/sshpoke/pkg/proto/ssh/internal/poly1305"
|
||||||
+ "golang.org/x/crypto/chacha20"
|
+ "golang.org/x/crypto/chacha20"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
diff -Naru cryptolib/ssh/common.go pkg/proto/ssh/common.go
|
diff -Naru cryptolib/ssh/common.go pkg/proto/ssh/common.go
|
||||||
--- cryptolib/ssh/common.go 2023-11-21 18:52:03.217249582 +0300
|
--- cryptolib/ssh/common.go 2023-11-24 21:59:11.677320636 +0300
|
||||||
+++ pkg/proto/ssh/common.go 2023-11-21 17:28:23.221203344 +0300
|
+++ pkg/proto/ssh/common.go 2023-11-24 21:39:08.401775359 +0300
|
||||||
@@ -7,14 +7,13 @@
|
@@ -287,6 +287,9 @@
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/rand"
|
|
||||||
+ _ "crypto/sha1"
|
|
||||||
+ _ "crypto/sha256"
|
|
||||||
+ _ "crypto/sha512"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"math"
|
|
||||||
"sync"
|
|
||||||
-
|
|
||||||
- _ "crypto/sha1"
|
|
||||||
- _ "crypto/sha256"
|
|
||||||
- _ "crypto/sha512"
|
|
||||||
)
|
|
||||||
|
|
||||||
// These are string constants in the SSH protocol.
|
|
||||||
@@ -279,6 +278,9 @@
|
|
||||||
// The allowed MAC algorithms. If unspecified then a sensible default is
|
// The allowed MAC algorithms. If unspecified then a sensible default is
|
||||||
// used. Unsupported values are silently ignored.
|
// used. Unsupported values are silently ignored.
|
||||||
MACs []string
|
MACs []string
|
||||||
@ -40,15 +22,15 @@ diff -Naru cryptolib/ssh/common.go pkg/proto/ssh/common.go
|
|||||||
+ // Called on every incoming handshake packet for client. Only receives data and extended data packets.
|
+ // Called on every incoming handshake packet for client. Only receives data and extended data packets.
|
||||||
+ HandshakePacketReader func(p []byte)
|
+ HandshakePacketReader func(p []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets sensible values for unset fields in config. This is
|
// SetDefaults sets sensible values for unset fields in config. This is
|
||||||
diff -Naru cryptolib/ssh/handshake.go pkg/proto/ssh/handshake.go
|
diff -Naru cryptolib/ssh/handshake.go pkg/proto/ssh/handshake.go
|
||||||
--- cryptolib/ssh/handshake.go 2023-11-21 18:52:03.209249460 +0300
|
--- cryptolib/ssh/handshake.go 2023-11-24 21:59:11.673320566 +0300
|
||||||
+++ pkg/proto/ssh/handshake.go 2023-11-21 18:51:58.681180283 +0300
|
+++ pkg/proto/ssh/handshake.go 2023-11-24 21:59:05.113204819 +0300
|
||||||
@@ -401,6 +401,14 @@
|
@@ -401,6 +401,14 @@
|
||||||
t.printPacket(p, false)
|
t.printPacket(p, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
+ if t.config.HandshakePacketReader != nil && p[0] == msgChannelData {
|
+ if t.config.HandshakePacketReader != nil && p[0] == msgChannelData {
|
||||||
+ data, err := decode(p)
|
+ data, err := decode(p)
|
||||||
+ packetData, ok := data.(*channelDataMsg)
|
+ packetData, ok := data.(*channelDataMsg)
|
||||||
@ -61,8 +43,8 @@ diff -Naru cryptolib/ssh/handshake.go pkg/proto/ssh/handshake.go
|
|||||||
return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
|
return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
|
||||||
}
|
}
|
||||||
diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
|
diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
|
||||||
--- cryptolib/ssh/tcpip.go 2023-11-21 18:52:03.129248237 +0300
|
--- cryptolib/ssh/tcpip.go 2023-11-24 21:59:11.593319154 +0300
|
||||||
+++ pkg/proto/ssh/tcpip.go 2023-11-21 17:19:04.688042738 +0300
|
+++ pkg/proto/ssh/tcpip.go 2023-11-24 21:39:08.401775359 +0300
|
||||||
@@ -101,14 +101,18 @@
|
@@ -101,14 +101,18 @@
|
||||||
// ListenTCP requests the remote peer open a listening socket
|
// ListenTCP requests the remote peer open a listening socket
|
||||||
// on laddr. Incoming connections will be available by calling
|
// on laddr. Incoming connections will be available by calling
|
||||||
@ -73,7 +55,7 @@ diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
|
|||||||
if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
|
if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
|
||||||
return c.autoPortListenWorkaround(laddr)
|
return c.autoPortListenWorkaround(laddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
+ host := laddr.IP.String()
|
+ host := laddr.IP.String()
|
||||||
+ if len(fakeHost) > 0 {
|
+ if len(fakeHost) > 0 {
|
||||||
+ host = fakeHost[0]
|
+ host = fakeHost[0]
|
||||||
@ -86,7 +68,7 @@ diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
|
|||||||
// send message
|
// send message
|
||||||
@@ -133,7 +137,12 @@
|
@@ -133,7 +137,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register this forward, using the port number we obtained.
|
// Register this forward, using the port number we obtained.
|
||||||
- ch := c.forwards.add(laddr)
|
- ch := c.forwards.add(laddr)
|
||||||
+ var ch chan forward
|
+ var ch chan forward
|
||||||
@ -95,7 +77,7 @@ diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
|
|||||||
+ } else {
|
+ } else {
|
||||||
+ ch = c.forwards.add(laddr)
|
+ ch = c.forwards.add(laddr)
|
||||||
+ }
|
+ }
|
||||||
|
|
||||||
return &tcpListener{laddr, c, ch}, nil
|
return &tcpListener{laddr, c, ch}, nil
|
||||||
}
|
}
|
||||||
@@ -142,7 +151,9 @@
|
@@ -142,7 +151,9 @@
|
||||||
@ -107,12 +89,12 @@ diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
|
|||||||
+ fakeDomainsMap map[string]string
|
+ fakeDomainsMap map[string]string
|
||||||
+ entries []forwardEntry
|
+ entries []forwardEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
// forwardEntry represents an established mapping of a laddr on a
|
// forwardEntry represents an established mapping of a laddr on a
|
||||||
@@ -160,17 +171,30 @@
|
@@ -160,17 +171,30 @@
|
||||||
raddr net.Addr // the raddr of the incoming connection
|
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) chan forward {
|
||||||
+func (l *forwardList) add(addr net.Addr, fakeHost ...string) chan forward {
|
+func (l *forwardList) add(addr net.Addr, fakeHost ...string) chan forward {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
@ -132,7 +114,7 @@ diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
|
|||||||
l.entries = append(l.entries, f)
|
l.entries = append(l.entries, f)
|
||||||
return f.c
|
return f.c
|
||||||
}
|
}
|
||||||
|
|
||||||
+func (l *forwardList) ipFromAddr(addr net.Addr) string {
|
+func (l *forwardList) ipFromAddr(addr net.Addr) string {
|
||||||
+ host, _, _ := net.SplitHostPort(addr.String())
|
+ host, _, _ := net.SplitHostPort(addr.String())
|
||||||
+ return host
|
+ return host
|
||||||
@ -144,7 +126,7 @@ diff -Naru cryptolib/ssh/tcpip.go pkg/proto/ssh/tcpip.go
|
|||||||
@@ -206,6 +230,15 @@
|
@@ -206,6 +230,15 @@
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
+ l.fdm.RLock()
|
+ l.fdm.RLock()
|
||||||
+ if addr, ok := l.fakeDomainsMap[payload.Addr]; ok {
|
+ if addr, ok := l.fakeDomainsMap[payload.Addr]; ok {
|
||||||
+ payload.Addr = addr
|
+ payload.Addr = addr
|
||||||
|
@ -307,7 +307,10 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
}
|
}
|
||||||
var methods []string
|
var methods []string
|
||||||
var errSigAlgo error
|
var errSigAlgo error
|
||||||
for _, signer := range signers {
|
|
||||||
|
origSignersLen := len(signers)
|
||||||
|
for idx := 0; idx < len(signers); idx++ {
|
||||||
|
signer := signers[idx]
|
||||||
pub := signer.PublicKey()
|
pub := signer.PublicKey()
|
||||||
as, algo, err := pickSignatureAlgorithm(signer, extensions)
|
as, algo, err := pickSignatureAlgorithm(signer, extensions)
|
||||||
if err != nil && errSigAlgo == nil {
|
if err != nil && errSigAlgo == nil {
|
||||||
@ -321,6 +324,21 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return authFailure, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
// OpenSSH 7.2-7.7 advertises support for rsa-sha2-256 and rsa-sha2-512
|
||||||
|
// in the "server-sig-algs" extension but doesn't support these
|
||||||
|
// algorithms for certificate authentication, so if the server rejects
|
||||||
|
// the key try to use the obtained algorithm as if "server-sig-algs" had
|
||||||
|
// not been implemented if supported from the algorithm signer.
|
||||||
|
if !ok && idx < origSignersLen && isRSACert(algo) && algo != CertAlgoRSAv01 {
|
||||||
|
if contains(as.Algorithms(), KeyAlgoRSA) {
|
||||||
|
// We retry using the compat algorithm after all signers have
|
||||||
|
// been tried normally.
|
||||||
|
signers = append(signers, &multiAlgorithmSigner{
|
||||||
|
AlgorithmSigner: as,
|
||||||
|
supportedAlgorithms: []string{KeyAlgoRSA},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,14 @@ package ssh
|
|||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
_ "crypto/sha1"
|
|
||||||
_ "crypto/sha256"
|
|
||||||
_ "crypto/sha512"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
_ "crypto/sha1"
|
||||||
|
_ "crypto/sha256"
|
||||||
|
_ "crypto/sha512"
|
||||||
)
|
)
|
||||||
|
|
||||||
// These are string constants in the SSH protocol.
|
// These are string constants in the SSH protocol.
|
||||||
@ -126,6 +127,14 @@ func isRSA(algo string) bool {
|
|||||||
return contains(algos, underlyingAlgo(algo))
|
return contains(algos, underlyingAlgo(algo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRSACert(algo string) bool {
|
||||||
|
_, ok := certKeyAlgoNames[algo]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isRSA(algo)
|
||||||
|
}
|
||||||
|
|
||||||
// supportedPubKeyAuthAlgos specifies the supported client public key
|
// supportedPubKeyAuthAlgos specifies the supported client public key
|
||||||
// authentication algorithms. Note that this doesn't include certificate types
|
// authentication algorithms. Note that this doesn't include certificate types
|
||||||
// since those use the underlying algorithm. This list is sent to the client if
|
// since those use the underlying algorithm. This list is sent to the client if
|
||||||
|
Loading…
Reference in New Issue
Block a user