原生 ssh 增加 socks 代理功能

This commit is contained in:
dushixiang
2021-11-15 20:01:19 +08:00
parent 569a1ad763
commit 8759365f08
7 changed files with 145 additions and 31 deletions

View File

@ -134,8 +134,18 @@ func SSHEndpoint(c echo.Context) (err error) {
recording = path.Join(config.GlobalCfg.Guacd.Recording, sessionId, "recording.cast")
}
attributes, err := assetRepository.FindAssetAttrMapByAssetId(s.AssetId)
if err != nil {
return WriteMessage(ws, NewMessage(Closed, "获取资产属性失败:"+err.Error()))
}
var xterm = "xterm-256color"
nextTerminal, err := term.NewNextTerminal(ip, port, username, password, privateKey, passphrase, rows, cols, recording, xterm, true)
var nextTerminal *term.NextTerminal
if "true" == attributes[constant.SocksProxyEnable] {
nextTerminal, err = term.NewNextTerminalUseSocks(ip, port, username, password, privateKey, passphrase, rows, cols, recording, xterm, true, attributes[constant.SocksProxyHost], attributes[constant.SocksProxyPort], attributes[constant.SocksProxyUsername], attributes[constant.SocksProxyPassword])
} else {
nextTerminal, err = term.NewNextTerminal(ip, port, username, password, privateKey, passphrase, rows, cols, recording, xterm, true)
}
if err != nil {
return WriteMessage(ws, NewMessage(Closed, "创建SSH客户端失败"+err.Error()))

View File

@ -59,9 +59,15 @@ const (
StatusEnabled = "enabled"
StatusDisabled = "disabled"
SocksProxyEnable = "socks-proxy-enable"
SocksProxyHost = "socks-proxy-host"
SocksProxyPort = "socks-proxy-port"
SocksProxyUsername = "socks-proxy-username"
SocksProxyPassword = "socks-proxy-password"
)
var SSHParameterNames = []string{guacd.FontName, guacd.FontSize, guacd.ColorScheme, guacd.Backspace, guacd.TerminalType, SshMode}
var SSHParameterNames = []string{guacd.FontName, guacd.FontSize, guacd.ColorScheme, guacd.Backspace, guacd.TerminalType, SshMode, SocksProxyEnable, SocksProxyHost, SocksProxyPort, SocksProxyUsername, SocksProxyPassword}
var RDPParameterNames = []string{guacd.Domain, guacd.RemoteApp, guacd.RemoteAppDir, guacd.RemoteAppArgs, guacd.EnableDrive, guacd.DrivePath}
var VNCParameterNames = []string{guacd.ColorDepth, guacd.Cursor, guacd.SwapRedBlue, guacd.DestHost, guacd.DestPort}
var TelnetParameterNames = []string{guacd.FontName, guacd.FontSize, guacd.ColorScheme, guacd.Backspace, guacd.TerminalType, guacd.UsernameRegex, guacd.PasswordRegex, guacd.LoginSuccessRegex, guacd.LoginFailureRegex}

View File

@ -229,7 +229,7 @@ func (opt *Tunnel) WriteInstructionAndFlush(instruction Instruction) error {
}
func (opt *Tunnel) WriteAndFlush(p []byte) (int, error) {
//fmt.Printf("-> %v\n", string(p))
fmt.Printf("-> %v\n", string(p))
nn, err := opt.writer.Write(p)
if err != nil {
return nn, err
@ -257,7 +257,7 @@ func (opt *Tunnel) Read() (p []byte, err error) {
}
buffer = buffer[0:read]
s := string(buffer)
//fmt.Printf("<- %v \n", s)
fmt.Printf("<- %v \n", s)
if s == "rate=44100,channels=2;" {
return make([]byte, 0), nil
}

View File

@ -22,7 +22,18 @@ func NewNextTerminal(ip string, port int, username, password, privateKey, passph
if err != nil {
return nil, err
}
return newNT(err, sshClient, pipe, recording, term, rows, cols)
}
func NewNextTerminalUseSocks(ip string, port int, username, password, privateKey, passphrase string, rows, cols int, recording, term string, pipe bool, socksProxyHost, socksProxyPort, socksProxyUsername, socksProxyPassword string) (*NextTerminal, error) {
sshClient, err := NewSshClientUseSocks(ip, port, username, password, privateKey, passphrase, socksProxyHost, socksProxyPort, socksProxyUsername, socksProxyPassword)
if err != nil {
return nil, err
}
return newNT(err, sshClient, pipe, recording, term, rows, cols)
}
func newNT(err error, sshClient *ssh.Client, pipe bool, recording string, term string, rows int, cols int) (*NextTerminal, error) {
sshSession, err := sshClient.NewSession()
if err != nil {
return nil, err

View File

@ -2,6 +2,8 @@ package term
import (
"fmt"
"golang.org/x/net/proxy"
"net"
"time"
"golang.org/x/crypto/ssh"
@ -49,29 +51,73 @@ func NewSshClient(ip string, port int, username, password, privateKey, passphras
}
addr := fmt.Sprintf("%s:%d", ip, port)
//
//socks5, err := proxy.SOCKS5("tcp", "",
// &proxy.Auth{User: "username", Password: "password"},
// &net.Dialer{
// Timeout: 30 * time.Second,
// KeepAlive: 30 * time.Second,
// },
//)
//if err != nil {
// return nil, err
//}
//
//conn, err := socks5.Dial("tcp", addr)
//if err != nil {
// return nil, err
//}
//
//clientConn, channels, requests, err := ssh.NewClientConn(conn, addr, config)
//if err != nil {
// return nil, err
//}
//
//ssh.NewClient(clientConn, channels, requests)
return ssh.Dial("tcp", addr, config)
}
func NewSshClientUseSocks(ip string, port int, username, password, privateKey, passphrase string, socksProxyHost, socksProxyPort, socksProxyUsername, socksProxyPassword string) (*ssh.Client, error) {
var authMethod ssh.AuthMethod
if username == "-" || username == "" {
username = "root"
}
if password == "-" {
password = ""
}
if privateKey == "-" {
privateKey = ""
}
if passphrase == "-" {
passphrase = ""
}
var err error
if privateKey != "" {
var key ssh.Signer
if len(passphrase) > 0 {
key, err = ssh.ParsePrivateKeyWithPassphrase([]byte(privateKey), []byte(passphrase))
if err != nil {
return nil, err
}
} else {
key, err = ssh.ParsePrivateKey([]byte(privateKey))
if err != nil {
return nil, err
}
}
authMethod = ssh.PublicKeys(key)
} else {
authMethod = ssh.Password(password)
}
config := &ssh.ClientConfig{
Timeout: 3 * time.Second,
User: username,
Auth: []ssh.AuthMethod{authMethod},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
socksProxyAddr := fmt.Sprintf("%s:%s", socksProxyHost, socksProxyPort)
socks5, err := proxy.SOCKS5("tcp", socksProxyAddr,
&proxy.Auth{User: socksProxyUsername, Password: socksProxyPassword},
&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
},
)
if err != nil {
return nil, err
}
addr := fmt.Sprintf("%s:%d", ip, port)
conn, err := socks5.Dial("tcp", addr)
if err != nil {
return nil, err
}
clientConn, channels, requests, err := ssh.NewClientConn(conn, addr, config)
if err != nil {
return nil, err
}
return ssh.NewClient(clientConn, channels, requests), nil
}