add: sshsvc support telnet server and local auth
This commit is contained in:
@@ -48,8 +48,25 @@ type YamlConfig struct {
|
|||||||
Timeout uint16 `yaml:"timeout"`
|
Timeout uint16 `yaml:"timeout"`
|
||||||
Session string `yaml:"session"`
|
Session string `yaml:"session"`
|
||||||
MmlHome string `yaml:"mmlHome"`
|
MmlHome string `yaml:"mmlHome"`
|
||||||
|
UserName string `yaml:"userName"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
AuthType string `yaml:"authType"`
|
||||||
|
OMCUrl string `yaml:"omcUrl"`
|
||||||
} `yaml:"sshd"`
|
} `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"`
|
Database DbConfig `yaml:"database"`
|
||||||
|
|
||||||
OMC struct {
|
OMC struct {
|
||||||
|
|||||||
@@ -21,14 +21,32 @@ logmml:
|
|||||||
# ssh service listen ipv4/v6 and port, support multiple routines
|
# ssh service listen ipv4/v6 and port, support multiple routines
|
||||||
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
||||||
# session: single/multiple session for one user
|
# session: single/multiple session for one user
|
||||||
|
# authType: local/omc
|
||||||
sshd:
|
sshd:
|
||||||
listenAddr: 0.0.0.0
|
listenAddr: 0.0.0.0
|
||||||
listenPort: 2222
|
listenPort: 2222
|
||||||
privateKey: ./.ssh/id_rsa
|
privateKey: ./.ssh/id_rsa
|
||||||
maxConnNum: 20
|
maxConnNum: 2
|
||||||
timeout: 1800
|
timeout: 1800
|
||||||
session: multiple
|
session: multiple
|
||||||
mmlHome: ./mmlhome
|
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:
|
database:
|
||||||
type: mysql
|
type: mysql
|
||||||
|
|||||||
161
sshsvc/sshsvc.go
161
sshsvc/sshsvc.go
@@ -1,13 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"be.ems/lib/dborm"
|
"be.ems/lib/dborm"
|
||||||
"be.ems/lib/global"
|
"be.ems/lib/global"
|
||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
var connNum int = 0
|
|
||||||
var conf *config.YamlConfig
|
var conf *config.YamlConfig
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -57,33 +56,32 @@ func main() {
|
|||||||
serverConfig := &ssh.ServerConfig{
|
serverConfig := &ssh.ServerConfig{
|
||||||
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
|
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
|
||||||
// 这里可以进行密码验证逻辑,例如检查用户名和密码是否匹配
|
// 这里可以进行密码验证逻辑,例如检查用户名和密码是否匹配
|
||||||
validUser, _, err := dborm.XormCheckLoginUser(conn.User(), string(password), conf.OMC.UserCrypt)
|
// validUser, _, err := dborm.XormCheckLoginUser(conn.User(), string(password), conf.OMC.UserCrypt)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
if validUser == true {
|
// if validUser == true {
|
||||||
sessionToken := fmt.Sprintf("%x", conn.SessionID()) // Generate new token to session ID
|
// sessionToken := fmt.Sprintf("%x", conn.SessionID()) // Generate new token to session ID
|
||||||
sourceAddr := conn.RemoteAddr().String()
|
// sourceAddr := conn.RemoteAddr().String()
|
||||||
timeOut := uint32(conf.Sshd.Timeout)
|
// timeOut := uint32(conf.Sshd.Timeout)
|
||||||
sessionMode := conf.Sshd.Session
|
// sessionMode := conf.Sshd.Session
|
||||||
log.Debugf("token:%s sourceAddr:%s", sessionToken, sourceAddr)
|
// log.Debugf("token:%s sourceAddr:%s", sessionToken, sourceAddr)
|
||||||
affected, err := dborm.XormInsertSession(conn.User(), sourceAddr, sessionToken, timeOut, sessionMode)
|
// affected, err := dborm.XormInsertSession(conn.User(), sourceAddr, sessionToken, timeOut, sessionMode)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Error("Failed to insert Session table:", err)
|
// log.Error("Failed to insert Session table:", err)
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
if affected == -1 {
|
// if affected == -1 {
|
||||||
err := errors.New("Failed to get session")
|
// err := errors.New("Failed to get session")
|
||||||
log.Error(err)
|
// log.Error(err)
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// if conn.User() == "admin" && string(password) == "123456" {
|
|
||||||
// return nil, nil
|
// return nil, nil
|
||||||
// }
|
// }
|
||||||
|
if handleAuth(conf.Sshd.AuthType, conn.User(), string(password)) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, fmt.Errorf("invalid user or password")
|
return nil, fmt.Errorf("invalid user or password")
|
||||||
},
|
},
|
||||||
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
||||||
@@ -101,8 +99,22 @@ func main() {
|
|||||||
log.Fatal("Failed to Listen: ", err)
|
log.Fatal("Failed to Listen: ", err)
|
||||||
os.Exit(4)
|
os.Exit(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("MML SSH server startup, listen port:%d\n", conf.Sshd.ListenPort)
|
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 {
|
for {
|
||||||
conn, err := listener.Accept()
|
conn, err := listener.Accept()
|
||||||
@@ -112,6 +124,90 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go handleSSHConnection(conn, serverConfig)
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
connNum++
|
sshMu.Lock()
|
||||||
if connNum > int(conf.Sshd.MaxConnNum) {
|
sshCC++
|
||||||
|
if sshCC > int(conf.Sshd.MaxConnNum) {
|
||||||
|
sshMu.Unlock()
|
||||||
log.Error("Maximum number of connections exceeded")
|
log.Error("Maximum number of connections exceeded")
|
||||||
//conn.Write([]byte("Reach max connections"))
|
//conn.Write([]byte("Reach max connections"))
|
||||||
conn.Close()
|
conn.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
sshMu.Unlock()
|
||||||
|
|
||||||
go handleSSHChannel(conn, sshConn, channel, requests)
|
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) {
|
func closeConnection(conn net.Conn) {
|
||||||
|
sshMu.Lock()
|
||||||
conn.Close()
|
conn.Close()
|
||||||
connNum--
|
sshCC--
|
||||||
|
sshMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSSHShell(sshConn *ssh.ServerConn, channel ssh.Channel) {
|
func handleSSHShell(sshConn *ssh.ServerConn, channel ssh.Channel) {
|
||||||
|
|||||||
Reference in New Issue
Block a user