add: sshsvc support telnet server and local auth

This commit is contained in:
2024-09-07 16:48:34 +08:00
parent f323f5fcb9
commit f2696a9868
3 changed files with 167 additions and 31 deletions

View File

@@ -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 {

View File

@@ -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

View File

@@ -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) {