diff --git a/sshsvc/config/config.go b/sshsvc/config/config.go index 411d6758..29419cd7 100644 --- a/sshsvc/config/config.go +++ b/sshsvc/config/config.go @@ -48,8 +48,25 @@ type YamlConfig struct { Timeout uint16 `yaml:"timeout"` Session string `yaml:"session"` MmlHome string `yaml:"mmlHome"` + UserName string `yaml:"userName"` + Password string `yaml:"password"` + AuthType string `yaml:"authType"` + OMCUrl string `yaml:"omcUrl"` } `yaml:"sshd"` + TelnetServer struct { + ListenAddr string `yaml:"listenAddr"` + ListenPort uint16 `yaml:"listenPort"` + MaxConnNum uint8 `yaml:"maxConnNum"` + Timeout uint16 `yaml:"timeout"` + Session string `yaml:"session"` + MmlHome string `yaml:"mmlHome"` + UserName string `yaml:"userName"` + Password string `yaml:"password"` + AuthType string `yaml:"authType"` + OMCUrl string `yaml:"omcUrl"` + } `yaml:"telnetServer"` + Database DbConfig `yaml:"database"` OMC struct { diff --git a/sshsvc/etc/sshsvc.yaml b/sshsvc/etc/sshsvc.yaml index 5e8cb358..650d4428 100644 --- a/sshsvc/etc/sshsvc.yaml +++ b/sshsvc/etc/sshsvc.yaml @@ -21,14 +21,32 @@ logmml: # ssh service listen ipv4/v6 and port, support multiple routines # ip: 0.0.0.0 or ::0, support IPv4/v6 # session: single/multiple session for one user +# authType: local/omc sshd: listenAddr: 0.0.0.0 listenPort: 2222 privateKey: ./.ssh/id_rsa - maxConnNum: 20 + maxConnNum: 2 timeout: 1800 session: multiple mmlHome: ./mmlhome + userName: manager + password: admin123 + authType: local + omcUrl: + +# authType: local/omc +telnetServer: + listenAddr: 0.0.0.0 + listenPort: 2323 + maxConnNum: 2 + timeout: 1800 + session: multiple + mmlHome: ./mmlhome + userName: manager + password: admin123 + authType: local + omcUrl: database: type: mysql diff --git a/sshsvc/sshsvc.go b/sshsvc/sshsvc.go index 9dab6ca2..e9198576 100644 --- a/sshsvc/sshsvc.go +++ b/sshsvc/sshsvc.go @@ -1,13 +1,13 @@ package main import ( - "errors" "fmt" "io" "net" "os" "os/exec" "strings" + "sync" "be.ems/lib/dborm" "be.ems/lib/global" @@ -21,7 +21,6 @@ import ( "golang.org/x/term" ) -var connNum int = 0 var conf *config.YamlConfig func init() { @@ -57,33 +56,32 @@ func main() { serverConfig := &ssh.ServerConfig{ PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { // 这里可以进行密码验证逻辑,例如检查用户名和密码是否匹配 - validUser, _, err := dborm.XormCheckLoginUser(conn.User(), string(password), conf.OMC.UserCrypt) - if err != nil { - return nil, err - } - if validUser == true { - sessionToken := fmt.Sprintf("%x", conn.SessionID()) // Generate new token to session ID - sourceAddr := conn.RemoteAddr().String() - timeOut := uint32(conf.Sshd.Timeout) - sessionMode := conf.Sshd.Session - log.Debugf("token:%s sourceAddr:%s", sessionToken, sourceAddr) - affected, err := dborm.XormInsertSession(conn.User(), sourceAddr, sessionToken, timeOut, sessionMode) - if err != nil { - log.Error("Failed to insert Session table:", err) - return nil, err - } - if affected == -1 { - err := errors.New("Failed to get session") - log.Error(err) - return nil, err - } + // validUser, _, err := dborm.XormCheckLoginUser(conn.User(), string(password), conf.OMC.UserCrypt) + // if err != nil { + // return nil, err + // } + // if validUser == true { + // sessionToken := fmt.Sprintf("%x", conn.SessionID()) // Generate new token to session ID + // sourceAddr := conn.RemoteAddr().String() + // timeOut := uint32(conf.Sshd.Timeout) + // sessionMode := conf.Sshd.Session + // log.Debugf("token:%s sourceAddr:%s", sessionToken, sourceAddr) + // affected, err := dborm.XormInsertSession(conn.User(), sourceAddr, sessionToken, timeOut, sessionMode) + // if err != nil { + // log.Error("Failed to insert Session table:", err) + // return nil, err + // } + // if affected == -1 { + // err := errors.New("Failed to get session") + // log.Error(err) + // return nil, err + // } - return nil, nil - } - - // if conn.User() == "admin" && string(password) == "123456" { // return nil, nil // } + if handleAuth(conf.Sshd.AuthType, conn.User(), string(password)) { + return nil, nil + } return nil, fmt.Errorf("invalid user or password") }, PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { @@ -101,8 +99,22 @@ func main() { log.Fatal("Failed to Listen: ", err) os.Exit(4) } - fmt.Printf("MML SSH server startup, listen port:%d\n", conf.Sshd.ListenPort) + // 启动telnet服务器 + telnetUri := fmt.Sprintf("%s:%d", conf.TelnetServer.ListenAddr, conf.TelnetServer.ListenPort) + // telnetListener, err := net.Listen("tcp", telnetUri) + // if err != nil { + // log.Fatal("Failed to Listen: ", err) + // os.Exit(4) + // } + fmt.Printf("MML Telnet server startup, listen port:%d\n", conf.TelnetServer.ListenPort) + // telnetconn, err := telnetListener.Accept() + // if err != nil { + // log.Fatal("Failed to accept telnet connection: ", err) + // os.Exit(6) + // } + + go startTelnetServer(telnetUri) for { conn, err := listener.Accept() @@ -112,6 +124,90 @@ func main() { } go handleSSHConnection(conn, serverConfig) + + } +} + +func handleAuth(authType, userName, password string) bool { + switch authType { + case "local": + if userName == conf.Sshd.UserName && password == conf.Sshd.Password { + return true + } + return false + case "omc": + default: + } + + return false +} + +// const ( +// // 定义用户名和密码 +// validUsername = "user" +// validPassword = "password" +// maxConnections = 5 +// ) + +var ( + telnetCC int + sshCC int + telnetMu sync.Mutex + sshMu sync.Mutex +) + +func startTelnetServer(addr string) { + listener, err := net.Listen("tcp", addr) + if err != nil { + fmt.Println("Error starting Telnet server:", err) + return + } + defer listener.Close() + fmt.Println("Telnet server started on", addr) + + for { + conn, err := listener.Accept() + if err != nil { + fmt.Println("Error accepting Telnet connection:", err) + continue + } + + telnetMu.Lock() + if telnetCC >= int(conf.TelnetServer.MaxConnNum) { + telnetMu.Unlock() + io.WriteString(conn, "Connection limit reached. Try again later.\n") + conn.Close() + continue + } + telnetCC++ + telnetMu.Unlock() + + go handleTelnetConnection(conn) + } +} + +func handleTelnetConnection(conn net.Conn) { + defer func() { + telnetMu.Lock() + telnetCC-- + telnetMu.Unlock() + }() + defer conn.Close() + io.WriteString(conn, "Welcome to the Telnet server!\n") + io.WriteString(conn, "Please enter username: ") + + var username string + fmt.Fscanln(conn, &username) + + io.WriteString(conn, "Please enter password: ") + var password string + fmt.Fscanln(conn, &password) + + if handleAuth(conf.TelnetServer.AuthType, username, password) { + io.WriteString(conn, "Login successful!\n") + io.Copy(conn, conn) // Echo back whatever is received + } else { + io.WriteString(conn, "Login failed!\n") } } @@ -141,13 +237,16 @@ func handleSSHConnection(conn net.Conn, serverConfig *ssh.ServerConfig) { continue } - connNum++ - if connNum > int(conf.Sshd.MaxConnNum) { + sshMu.Lock() + sshCC++ + if sshCC > int(conf.Sshd.MaxConnNum) { + sshMu.Unlock() log.Error("Maximum number of connections exceeded") //conn.Write([]byte("Reach max connections")) conn.Close() continue } + sshMu.Unlock() go handleSSHChannel(conn, sshConn, channel, requests) } @@ -196,8 +295,10 @@ func handleSSHChannel(conn net.Conn, sshConn *ssh.ServerConn, channel ssh.Channe } func closeConnection(conn net.Conn) { + sshMu.Lock() conn.Close() - connNum-- + sshCC-- + sshMu.Unlock() } func handleSSHShell(sshConn *ssh.ServerConn, channel ssh.Channel) {