ssh: remove nopty option, request shell by default

This commit is contained in:
Pavel 2023-11-21 20:02:07 +03:00
parent 725f650193
commit b89011c631
4 changed files with 38 additions and 47 deletions

View File

@ -39,14 +39,11 @@ servers:
# Set this to true if you're using sish, otherwise you'll get weird domains with IP's in them.
# Default: false
fake_remote_host: true
# Disables PTY request for this server. Default: false
nopty: true
# Requests interactive shell for SSH sessions. Should be `true` for the `commands`.
# You can also pass a string with shell binary, for example, "/bin/sh".
# Note: commands will be executed using provided shell binary.
# Note (2): some servers won't send you any data until you request a shell even without a PTY.
# You can use a combination of `nopty: true` & `shell: true`. Also, even with PTY you may need `shell` to be `true`.
# Default: false
# Note (2): some servers won't send you any data until you request a shell.
# Default: true
shell: false
# Spoof client version with provided (value below is taken directly from OpenSSH). This value must be compliant with RFC-4253.
# Default: SSH-2.0-Go
@ -97,7 +94,6 @@ servers:
address: "your2.server"
forward_port: 80
fake_remote_host: true
nopty: false
shell: "/usr/bin/bash"
mode: single
keepalive:

View File

@ -76,8 +76,7 @@ func (d *SSH) forward(val sshtun.Forward, domainMatcher func(string)) conn {
sshtun.TunnelConfig{
Forward: val,
HostKeyCallback: d.hostKeyCallback,
NoPTY: d.params.NoPTY,
Shell: sshtun.BoolOrStr(d.params.Shell),
Shell: d.params.Shell,
ClientVersion: d.clientVersion,
FakeRemoteHost: d.params.FakeRemoteHost,
KeepAliveInterval: uint(d.params.KeepAlive.Interval),

View File

@ -1,36 +1,31 @@
package ssh
import (
"errors"
"github.com/Neur0toxine/sshpoke/internal/server/driver/ssh/sshtun"
"github.com/Neur0toxine/sshpoke/internal/server/driver/ssh/types"
"github.com/Neur0toxine/sshpoke/internal/server/driver/util"
)
type Params struct {
Address string `mapstructure:"address" validate:"required"`
HostKeys string `mapstructure:"host_keys"`
DefaultHost *string `mapstructure:"default_host,omitempty"`
ForwardPort uint16 `mapstructure:"forward_port"`
Auth types.Auth `mapstructure:"auth"`
KeepAlive types.KeepAlive `mapstructure:"keepalive"`
DomainExtractRegex string `mapstructure:"domain_extract_regex" validate:"validregexp"`
ReadRawPackets bool `mapstructure:"read_raw_packets"`
ReadSessionsOutput *bool `mapstructure:"read_sessions_output"`
Mode types.DomainMode `mapstructure:"mode" validate:"required,oneof=single multi"`
FakeRemoteHost bool `mapstructure:"fake_remote_host"`
NoPTY bool `mapstructure:"nopty"`
Shell string `mapstructure:"shell"`
ClientVersion string `mapstructure:"client_version"`
Commands types.Commands `mapstructure:"commands"`
Address string `mapstructure:"address" validate:"required"`
HostKeys string `mapstructure:"host_keys"`
DefaultHost *string `mapstructure:"default_host,omitempty"`
ForwardPort uint16 `mapstructure:"forward_port"`
Auth types.Auth `mapstructure:"auth"`
KeepAlive types.KeepAlive `mapstructure:"keepalive"`
DomainExtractRegex string `mapstructure:"domain_extract_regex" validate:"validregexp"`
ReadRawPackets bool `mapstructure:"read_raw_packets"`
ReadSessionsOutput *bool `mapstructure:"read_sessions_output"`
Mode types.DomainMode `mapstructure:"mode" validate:"required,oneof=single multi"`
FakeRemoteHost bool `mapstructure:"fake_remote_host"`
Shell *sshtun.BoolOrStr `mapstructure:"shell"`
ClientVersion string `mapstructure:"client_version"`
Commands types.Commands `mapstructure:"commands"`
}
func (p *Params) Validate() error {
if err := util.Validator.Struct(p); err != nil {
return err
}
if p.NoPTY && (len(p.Commands.OnConnect) > 0 || len(p.Commands.OnDisconnect) > 0) {
return errors.New("commands aren't available without PTY (nopty = true)")
}
return p.Auth.Validate()
}

View File

@ -28,8 +28,7 @@ type Tunnel struct {
type TunnelConfig struct {
Forward Forward
HostKeyCallback ssh.HostKeyCallback
NoPTY bool
Shell BoolOrStr
Shell *BoolOrStr
ClientVersion string
FakeRemoteHost bool
KeepAliveInterval uint
@ -38,16 +37,27 @@ type TunnelConfig struct {
type BoolOrStr string
func (b BoolOrStr) IsBool() bool {
return b == "true" || b == "false" || b == "1" || b == "0" || b == ""
func (b *BoolOrStr) IsBool() bool {
if b == nil {
return false
}
v := *b
return v == "true" || v == "false" || v == "1" || v == "0" || v == ""
}
func (b BoolOrStr) Falsy() bool {
return b == "" || b == "0" || b == "false"
func (b *BoolOrStr) Falsy() bool {
if b == nil {
return true
}
v := *b
return v == "" || v == "0" || v == "false"
}
func (b BoolOrStr) String() string {
return string(b)
func (b *BoolOrStr) String() string {
if b == nil {
return ""
}
return string(*b)
}
func New(address, user string, auth []ssh.AuthMethod, sc TunnelConfig, log *zap.SugaredLogger) *Tunnel {
@ -127,17 +137,8 @@ func (t *Tunnel) connect(ctx context.Context,
sessionCb = func(*ssh.Session) {}
}
if !t.tunConfig.NoPTY {
err = sess.RequestPty("xterm", 80, 40, ssh.TerminalModes{
ssh.ECHO: 0,
ssh.IGNCR: 1,
})
if err != nil {
t.log.Warnf("PTY allocation failed: %s", err.Error())
}
}
if !t.tunConfig.Shell.Falsy() {
if t.tunConfig.Shell.IsBool() {
if t.tunConfig.Shell == nil || !t.tunConfig.Shell.Falsy() {
if t.tunConfig.Shell == nil || t.tunConfig.Shell.IsBool() {
if err := sess.Shell(); err != nil {
t.log.Warnf("failed to start empty shell: %s", err.Error())
}