Commit 2d6891c2 authored by ibuler's avatar ibuler

[Update] 修改config

parent ce97e4e6
package proxy
import "context"
type Conn interface {
ReceiveRequest(context.Context, <-chan []byte, chan<- []byte)
SendResponse(context.Context, chan<- []byte)
}
package proxy
import (
"fmt"
"net"
"time"
gossh "golang.org/x/crypto/ssh"
)
type ServerConnection interface {
SendChannel() chan<- []byte
RecvChannel() <-chan []byte
Protocol() string
Connect() error
Close()
}
type SSHConnection struct {
Host string
Port string
User string
Password string
PrivateKey string
PrivateKeyPath string
Timeout time.Duration
Proxy *SSHConnection
client *gossh.Client
proxyConn gossh.Conn
}
func (s *SSHConnection) Protocol() string {
return "ssh"
}
func (s *SSHConnection) Config() (config *gossh.ClientConfig, err error) {
auths := make([]gossh.AuthMethod, 0)
if s.Password != "" {
auths = append(auths, gossh.Password(s.Password))
}
if s.PrivateKeyPath != "" {
if pubkey, err := GetPubKeyFromFile(s.PrivateKeyPath); err != nil {
err = fmt.Errorf("parse private key from file error: %s", err)
return config, err
} else {
auths = append(auths, gossh.PublicKeys(pubkey))
}
}
if s.PrivateKey != "" {
if signer, err := gossh.ParsePrivateKey([]byte(s.PrivateKey)); err != nil {
err = fmt.Errorf("parse private key error: %s", err)
return config, err
} else {
auths = append(auths, gossh.PublicKeys(signer))
}
}
config = &gossh.ClientConfig{
User: s.User,
Auth: auths,
HostKeyCallback: gossh.InsecureIgnoreHostKey(),
Timeout: s.Timeout,
}
return config, nil
}
func (s *SSHConnection) Connect() (client *gossh.Client, err error) {
config, err := s.Config()
if err != nil {
return
}
if s.Proxy != nil {
proxyClient, err := s.Proxy.Connect()
if err != nil {
return client, err
}
proxySock, err := proxyClient.Dial("tcp", net.JoinHostPort(s.Host, s.Port))
if err != nil {
return client, err
}
proxyConn, chans, reqs, err := gossh.NewClientConn(proxySock, net.JoinHostPort(s.Host, s.Port), config)
if err != nil {
return client, err
}
s.proxyConn = proxyConn
client = gossh.NewClient(proxyConn, chans, reqs)
} else {
client, err = gossh.Dial("tcp", net.JoinHostPort(s.Host, s.Port), config)
if err != nil {
err = fmt.Errorf("connect host %s error: %s", s.Host, err)
return
}
}
s.client = client
return client, nil
}
func (s *SSHConnection) Close() error {
err := s.client.Close()
if err != nil {
return err
}
if s.proxyConn != nil {
err = s.proxyConn.Close()
}
return err
}
package proxy
import (
"fmt"
"testing"
)
var testConnection = SSHConnection{
Host: "127.0.0.1",
Port: "22",
User: "root",
Password: "redhat",
Proxy: &SSHConnection{Host: "192.168.244.185", Port: "22", User: "root", Password: "redhat"},
}
func TestSSHConnection_Config(t *testing.T) {
config, err := testConnection.Config()
if err != nil {
t.Errorf("Get config error %s", err)
}
fmt.Println(config.User)
}
func TestSSHConnection_Connect(t *testing.T) {
client, err := testConnection.Connect()
if err != nil {
t.Errorf("Connect error %s", err)
}
fmt.Println(string(client.ServerVersion()))
}
package proxy
import (
"cocogo/pkg/logger"
"cocogo/pkg/service"
"github.com/gliderlabs/ssh"
"cocogo/pkg/sdk"
)
type ProxyServer struct {
sess ssh.Session
User *sdk.User
Asset *sdk.Asset
SystemUser *sdk.SystemUser
}
func (p *ProxyServer) getSystemUserAuthOrManualSet() {
info := service.GetSystemUserAssetAuthInfo(p.SystemUser.Id, p.Asset.Id)
if p.SystemUser.LoginMode == sdk.LoginModeManual ||
(p.SystemUser.Password == "" && p.SystemUser.PrivateKey == "") {
logger.Info("Get password fom user input")
}
p.SystemUser.Password = info.Password
p.SystemUser.PrivateKey = info.PrivateKey
}
func (p *ProxyServer) checkProtocol() bool {
return true
}
func (p *ProxyServer) getSystemUserUsernameIfNeed() {
}
func (p *ProxyServer) validatePermission() bool {
return true
}
func (p *ProxyServer) getServerConn() {
}
func (p *ProxyServer) sendConnectingMsg() {
}
func (p *ProxyServer) Proxy() {
if !p.checkProtocol() {
return
}
}
package proxy
import (
"golang.org/x/crypto/ssh"
"io/ioutil"
)
func GetPubKeyFromFile(keypath string) (ssh.Signer, error) {
buf, err := ioutil.ReadFile(keypath)
if err != nil {
return nil, err
}
pubkey, err := ssh.ParsePrivateKey(buf)
if err != nil {
return nil, err
}
return pubkey, nil
}
package proxybak
import (
"context"
"fmt"
"io"
"time"
"github.com/gliderlabs/ssh"
gossh "golang.org/x/crypto/ssh"
"cocogo/pkg/logger"
"cocogo/pkg/parser"
"cocogo/pkg/record"
)
const maxBufferSize = 1024 * 4
type ServerAuth struct {
SessionID string
IP string
Port int
UserName string
Password string
PublicKey gossh.Signer
}
type Conn interface {
ReceiveRequest(context.Context, <-chan []byte, chan<- []byte)
SendResponse(context.Context, chan<- []byte)
}
func CreateNodeSession(authInfo ServerAuth) (c *gossh.Client, s *gossh.Session, err error) {
config := &gossh.ClientConfig{
User: authInfo.UserName,
Auth: []gossh.AuthMethod{
gossh.Password(authInfo.Password),
gossh.PublicKeys(authInfo.PublicKey),
},
HostKeyCallback: gossh.InsecureIgnoreHostKey(),
}
client, err := gossh.Dial("tcp", fmt.Sprintf("%s:%d", authInfo.IP, authInfo.Port), config)
if err != nil {
logger.Error(err)
return c, s, err
}
s, err = client.NewSession()
if err != nil {
logger.Error(err)
return c, s, err
}
return client, s, nil
}
func NewNodeConn(ctx context.Context, authInfo ServerAuth, ptyReq ssh.Pty, winCh <-chan ssh.Window) (*NodeConn, error) {
c, s, err := CreateNodeSession(authInfo)
if err != nil {
return nil, err
}
err = s.RequestPty(ptyReq.Term, ptyReq.Window.Height, ptyReq.Window.Width, gossh.TerminalModes{})
if err != nil {
return nil, err
}
nodeStdin, err := s.StdinPipe()
if err != nil {
return nil, err
}
nodeStdout, err := s.StdoutPipe()
if err != nil {
return nil, err
}
err = s.Shell()
if err != nil {
return nil, err
}
subCtx, cancelFunc := context.WithCancel(ctx)
replyRecord := record.NewReplyRecord(authInfo.SessionID)
replyRecord.StartRecord()
go replyRecord.EndRecord(subCtx)
nConn := &NodeConn{
SessionID: authInfo.SessionID,
client: c,
conn: s,
ctx: subCtx,
ctxCancelFunc: cancelFunc,
stdin: nodeStdin,
stdout: nodeStdout,
tParser: parser.NewTerminalParser(),
replyRecord: replyRecord,
StartTime: time.Now().UTC(),
}
go nConn.windowChangeHandler(winCh)
return nConn, nil
}
// coco连接远程Node的连接
type NodeConn struct {
SessionID string
client *gossh.Client
conn *gossh.Session
stdin io.Writer
stdout io.Reader
tParser *parser.TerminalParser
currentCommandInput string
currentCommandResult string
rulerFilters []parser.RuleFilter
specialCommands []parser.SpecialRuler
inSpecialStatus bool
ctx context.Context
ctxCancelFunc context.CancelFunc
replyRecord *record.Reply
cmdRecord *record.Command
StartTime time.Time
}
func (n *NodeConn) Wait() error {
return n.conn.Wait()
}
func (n *NodeConn) FilterSpecialCommand(b []byte) {
for _, specialCommand := range n.specialCommands {
if matched := specialCommand.MatchRule(b); matched {
switch {
case specialCommand.EnterStatus():
n.inSpecialStatus = true
case specialCommand.ExitStatus():
n.inSpecialStatus = false
}
}
}
}
func (n *NodeConn) FilterWhiteBlackRule(cmd string) bool {
for _, rule := range n.rulerFilters {
if rule.Match(cmd) {
return rule.BlockCommand()
}
}
return false
}
func (n *NodeConn) windowChangeHandler(winCH <-chan ssh.Window) {
for {
select {
case <-n.ctx.Done():
logger.Info("windowChangeHandler done")
return
case win, ok := <-winCH:
if !ok {
return
}
err := n.conn.WindowChange(win.Height, win.Width)
if err != nil {
logger.Error("windowChange err: ", win)
return
}
logger.Info("windowChange: ", win)
}
}
}
func (n *NodeConn) Close() {
select {
case <-n.ctx.Done():
return
default:
_ = n.conn.Close()
_ = n.client.Close()
n.ctxCancelFunc()
logger.Info("Close conn")
}
}
func (n *NodeConn) SendResponse(ctx context.Context, outChan chan<- []byte) {
buf := make([]byte, maxBufferSize)
defer close(outChan)
for {
nr, err := n.stdout.Read(buf)
if err != nil {
logger.Error("read conn err:", err)
return
}
if n.tParser.Started && nr > 0 {
n.FilterSpecialCommand(buf[:nr])
switch {
case n.inSpecialStatus:
// 进入特殊命令状态,
case n.tParser.InputStatus:
n.tParser.CmdInputBuf.Write(buf[:nr])
case n.tParser.OutputStatus:
n.tParser.CmdOutputBuf.Write(buf[:nr])
default:
}
}
select {
case <-ctx.Done():
logger.Info("SendResponse finish by context done")
return
default:
copyBuf := make([]byte, len(buf[:nr]))
copy(copyBuf, buf[:nr])
outChan <- copyBuf
n.replyRecord.Record(buf[:nr])
}
}
}
func (n *NodeConn) ReceiveRequest(ctx context.Context, inChan <-chan []byte, outChan chan<- []byte) {
defer n.Close()
for {
select {
case <-ctx.Done():
logger.Error("ReceiveRequest finish by context done")
return
case buf, ok := <-inChan:
if !ok {
logger.Error("ReceiveRequest finish by inChan close")
return
}
n.tParser.Once.Do(
func() {
n.tParser.Started = true
})
switch {
case n.inSpecialStatus:
// 特殊的命令 vim 或者 rz
case n.tParser.IsEnterKey(buf):
n.currentCommandInput = n.tParser.ParseCommandInput()
if n.FilterWhiteBlackRule(n.currentCommandInput) {
msg := fmt.Sprintf("\r\n cmd '%s' is forbidden \r\n", n.currentCommandInput)
outChan <- []byte(msg)
n.replyRecord.Record([]byte(msg))
ctrU := []byte{21, 13} // 清除行并换行
_, err := n.stdin.Write(ctrU)
if err != nil {
logger.Error(err)
}
n.tParser.InputStatus = false
n.tParser.OutputStatus = false
continue
}
n.tParser.InputStatus = false
n.tParser.OutputStatus = true
default:
// 1. 是否是一个命令的完整周期 是则解析命令,记录结果 并重置
// 2. 重置用户输入状态
if len(n.tParser.CmdOutputBuf.Bytes()) > 0 && n.currentCommandInput != "" {
n.currentCommandResult = n.tParser.ParseCommandResult()
n.tParser.Reset()
n.currentCommandInput = ""
n.currentCommandResult = ""
}
n.tParser.InputStatus = true
}
_, err := n.stdin.Write(buf)
if err != nil {
logger.Error("write conn err:", err)
return
}
}
}
}
package proxy package proxybak
import ( import (
"cocogo/pkg/parser" "cocogo/pkg/parser"
...@@ -28,6 +28,11 @@ type ServerAuth struct { ...@@ -28,6 +28,11 @@ type ServerAuth struct {
PublicKey gossh.Signer PublicKey gossh.Signer
} }
type Conn interface {
ReceiveRequest(context.Context, <-chan []byte, chan<- []byte)
SendResponse(context.Context, chan<- []byte)
}
func CreateNodeSession(authInfo ServerAuth) (c *gossh.Client, s *gossh.Session, err error) { func CreateNodeSession(authInfo ServerAuth) (c *gossh.Client, s *gossh.Session, err error) {
config := &gossh.ClientConfig{ config := &gossh.ClientConfig{
User: authInfo.UserName, User: authInfo.UserName,
......
package proxy package proxybak
import ( import (
"cocogo/pkg/userhome"
"context" "context"
"sync" "sync"
"github.com/gliderlabs/ssh"
"cocogo/pkg/logger" "cocogo/pkg/logger"
"cocogo/pkg/sdk"
"cocogo/pkg/userhome"
) )
type Switch struct { type UserSessionEndpoint struct {
UserSessions []ssh.Session
Transport Transport
}
type ServerSessionEndpoint struct {
ServerSession []ssh.Session
Transport Transport
}
type Switcher struct {
User sdk.User
Asset sdk.Asset
PrimarySession *ssh.Session
ShareSessions []*ssh.Session
WatcherSessions []*ssh.Session
ServerConn ServerSessionEndpoint
} }
var Manager = &manager{ var Manager = &manager{
......
package proxy package proxybak
import ( import (
"context" "context"
...@@ -6,6 +6,11 @@ import ( ...@@ -6,6 +6,11 @@ import (
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
) )
type Transport interface {
ReceiveChannel(ctx context.Context) chan<- []byte
SendChannel(ctx context.Context) <-chan []byte
}
type Agent interface { type Agent interface {
ReceiveRequestChannel(ctx context.Context) chan<- []byte ReceiveRequestChannel(ctx context.Context) chan<- []byte
......
package proxy package proxybak
import ( import (
"context" "context"
......
package proxybak
type Slot interface {
Chan() chan<- []byte
Send([]byte)
}
...@@ -91,14 +91,18 @@ func SortAssetNodesByKey(assetNodes []Node) { ...@@ -91,14 +91,18 @@ func SortAssetNodesByKey(assetNodes []Node) {
nodeSortBy(keySort).Sort(assetNodes) nodeSortBy(keySort).Sort(assetNodes)
} }
const LoginModeManual = "manual"
type SystemUser struct { type SystemUser struct {
Id string `json:"id"` Id string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
UserName string `json:"username"` UserName string `json:"username"`
Priority int `json:"priority"` Priority int `json:"priority"`
Protocol string `json:"protocol"` Protocol string `json:"protocol"`
Comment string `json:"comment"` Comment string `json:"comment"`
LoginMode string `json:"login_mode"` LoginMode string `json:"login_mode"`
Password string `json:"password"`
PrivateKey string `json:"private_key"`
} }
type SystemUserAuthInfo struct { type SystemUserAuthInfo struct {
......
package handler package handler
import ( import (
"cocogo/pkg/proxybak"
"context" "context"
//"context" //"context"
//"strconv" //"strconv"
...@@ -26,7 +27,6 @@ import ( ...@@ -26,7 +27,6 @@ import (
"cocogo/pkg/cctx" "cocogo/pkg/cctx"
"cocogo/pkg/logger" "cocogo/pkg/logger"
"cocogo/pkg/model" "cocogo/pkg/model"
"cocogo/pkg/proxy"
"cocogo/pkg/sdk" "cocogo/pkg/sdk"
"cocogo/pkg/service" "cocogo/pkg/service"
"cocogo/pkg/userhome" "cocogo/pkg/userhome"
...@@ -282,7 +282,7 @@ func (i *InteractiveHandler) JoinShareRoom(roomID string) { ...@@ -282,7 +282,7 @@ func (i *InteractiveHandler) JoinShareRoom(roomID string) {
} }
} }
}() }()
proxy.Manager.JoinShareRoom(roomID, sshConn) proxybak.Manager.JoinShareRoom(roomID, sshConn)
logger.Info("exit room id:", roomID) logger.Info("exit room id:", roomID)
cancelFuc() cancelFuc()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment