From 9e71a35cd75ebc82f2c2df388d015091faca82b8 Mon Sep 17 00:00:00 2001 From: simonzhangsz Date: Sat, 14 Sep 2024 14:44:02 +0800 Subject: [PATCH] fix: telnet server update --- sshsvc/sshsvc.go | 57 ++-------- sshsvc/telnet/telnet.go | 235 +++++++++++----------------------------- 2 files changed, 72 insertions(+), 220 deletions(-) diff --git a/sshsvc/sshsvc.go b/sshsvc/sshsvc.go index bb7c5130..5964e062 100644 --- a/sshsvc/sshsvc.go +++ b/sshsvc/sshsvc.go @@ -19,7 +19,7 @@ import ( "be.ems/sshsvc/config" "be.ems/sshsvc/logmml" "be.ems/sshsvc/snmp" - telnetOMC "be.ems/sshsvc/telnet" + omctelnet "be.ems/sshsvc/telnet" //"github.com/gliderlabs/ssh" "golang.org/x/crypto/ssh" @@ -126,18 +126,18 @@ func main() { // os.Exit(6) // } - telnetSvc := telnetOMC.TelnetHandler{ - // ListenAddr: conf.TelnetServer.ListenAddr, - // ListenPort: conf.TelnetServer.ListenPort, - // UserName: conf.TelnetServer.UserName, - // Password: conf.TelnetServer.Password, - // AuthType: conf.TelnetServer.AuthType, - // MaxConnNum: conf.TelnetServer.MaxConnNum, - // TagNE: conf.TelnetServer.TagNE, + telnetSvc := omctelnet.TelnetHandler{ + ListenAddr: conf.TelnetServer.ListenAddr, + ListenPort: conf.TelnetServer.ListenPort, + UserName: conf.TelnetServer.UserName, + Password: conf.TelnetServer.Password, + AuthType: conf.TelnetServer.AuthType, + MaxConnNum: conf.TelnetServer.MaxConnNum, + TagNE: conf.TelnetServer.TagNE, ListenHost: conf.TelnetServer.ListenAddr + ":" + strconv.Itoa(int(conf.TelnetServer.ListenPort)), } - // go telnetSvc.StartTelnetServer() - go StartTelnetServer(telnetSvc.ListenHost) + go telnetSvc.StartTelnetServer() + // go StartTelnetServer(telnetSvc.ListenHost) snmpSvc := snmp.SNMPService{ ListenAddr: conf.SNMPServer.ListenAddr, @@ -335,9 +335,6 @@ func HandleCommands(user, tag string, reader *bufio.Reader, writer *bufio.Writer writer.Flush() return case "": - // case "\n": - // case "\r\n": - case "\xff\xfe\x01": default: writer.WriteString("\r\nUnknown command\r\n") writer.Flush() @@ -347,38 +344,6 @@ func HandleCommands(user, tag string, reader *bufio.Reader, writer *bufio.Writer } } -// 处理命令输入 -func HandleCommandsNew(user, tag string, reader *bufio.Reader, writer *bufio.Writer) { - header := fmt.Sprintf("[%s@%s]> ", user, tag) - clearLine := "\033[2K\r" // ANSI 转义序列,用于清除当前行 - for { - writer.WriteString(clearLine + header) - writer.Flush() - - command, err := reader.ReadString('\n') - if err != nil { - return - } - command = strings.TrimSpace(command) - - // Handle other commands - switch command { - case "hello": - writer.WriteString("\r\nHello, world!\r\n") - case "time": - writer.WriteString(fmt.Sprintf("\r\nCurrent time: %s\r\n", time.Now().Format(time.RFC1123))) - case "exit", "quit": - writer.WriteString("\r\nGoodbye!\r\n") - writer.Flush() - return - default: - writer.WriteString("\r\nUnknown command\r\n") - } - - writer.Flush() - } -} - func handleSSHConnection(conn net.Conn, serverConfig *ssh.ServerConfig) { // SSH握手 sshConn, chans, reqs, err := ssh.NewServerConn(conn, serverConfig) diff --git a/sshsvc/telnet/telnet.go b/sshsvc/telnet/telnet.go index fbc4f6bb..28622b44 100644 --- a/sshsvc/telnet/telnet.go +++ b/sshsvc/telnet/telnet.go @@ -1,14 +1,15 @@ -package telnetOMC +package omctelnet import ( "bufio" "fmt" + "io" + "net" "strings" "sync" "time" "be.ems/lib/dborm" - "github.com/reiver/go-telnet" ) type TelnetHandler struct { @@ -25,24 +26,66 @@ type TelnetHandler struct { mu sync.Mutex } -func (t *TelnetHandler) HandleTelnetConnection(w telnet.Writer, r telnet.Reader) { - t.mu.Lock() - if t.connCount >= int(t.MaxConnNum) { - t.mu.Unlock() - w.Write([]byte("Connection limit reached. Try again later.\r\n")) +func (t *TelnetHandler) handleTelnetAuth(authType, userName, password string) bool { + switch authType { + case "local": + if userName == t.UserName && password == t.Password { + return true + } + return false + case "radius", "omc": + exist, err := dborm.XEngDB().Table("OMC_PUB.sysUser").Where("userName=? AND password=md5(?)", userName, password).Exist() + if err != nil { + return false + } + return exist + + default: + } + + return false +} + +func (t *TelnetHandler) StartTelnetServer() { + listener, err := net.Listen("tcp", t.ListenHost) + if err != nil { + fmt.Println("Error starting Telnet server:", err) return } - t.connCount++ - t.mu.Unlock() + defer listener.Close() + fmt.Println("Telnet server started on", t.ListenHost) + for { + conn, err := listener.Accept() + if err != nil { + fmt.Println("Error accepting Telnet connection:", err) + continue + } + + t.mu.Lock() + if t.connCount >= int(t.MaxConnNum) { + t.mu.Unlock() + io.WriteString(conn, "Connection limit reached. Try again later.\r\n") + conn.Close() + continue + } + t.connCount++ + t.mu.Unlock() + + go t.handleTelnetConnection(conn) + } +} + +func (t *TelnetHandler) handleTelnetConnection(conn net.Conn) { defer func() { t.mu.Lock() t.connCount-- t.mu.Unlock() }() + defer conn.Close() - reader := bufio.NewReader(r) - writer := bufio.NewWriter(w) + reader := bufio.NewReader(conn) + writer := bufio.NewWriter(conn) // 发送欢迎信息 writer.WriteString("Welcome to the Telnet server!\r\n") @@ -85,7 +128,7 @@ func (t *TelnetHandler) HandleTelnetConnection(w telnet.Writer, r telnet.Reader) writer.Write([]byte{255, 252, 1}) // IAC WONT ECHO writer.Flush() - if t.HandleAuth(t.AuthType, user, pass) { + if t.handleTelnetAuth(t.AuthType, user, pass) { writer.WriteString("\r\nAuthentication successful!\r\n") writer.Flush() t.HandleCommands(user, t.TagNE, reader, writer) @@ -95,14 +138,11 @@ func (t *TelnetHandler) HandleTelnetConnection(w telnet.Writer, r telnet.Reader) } } -// 处理命令输入 +// 处理命令输 func (t *TelnetHandler) HandleCommands(user, tag string, reader *bufio.Reader, writer *bufio.Writer) { header := fmt.Sprintf("[%s@%s]> ", user, tag) clearLine := "\033[2K\r" // ANSI 转义序列,用于清除当前行 for { - writer.WriteString(clearLine + header) - writer.Flush() - var commandBuilder strings.Builder for { b, err := reader.ReadByte() @@ -112,6 +152,9 @@ func (t *TelnetHandler) HandleCommands(user, tag string, reader *bufio.Reader, w if b == '\n' || b == '\r' { break } + if b == '\xff' || b == '\xfe' || b == '\x01' { + continue + } if b == 127 { // 处理退格键 if commandBuilder.Len() > 0 { // 手动截断字符串 @@ -131,12 +174,6 @@ func (t *TelnetHandler) HandleCommands(user, tag string, reader *bufio.Reader, w } command := strings.TrimSpace(commandBuilder.String()) - // command, err := reader.ReadString('\n') - // if err != nil { - // return - // } - // command = strings.TrimSpace(command) - // 处理其他命令 switch command { case "hello": @@ -148,161 +185,11 @@ func (t *TelnetHandler) HandleCommands(user, tag string, reader *bufio.Reader, w writer.Flush() return case "": - // case "\n": - // case "\r\n": - case "\xff\xfe\x01": default: writer.WriteString("\r\nUnknown command\r\n") + writer.Flush() } - + writer.WriteString(clearLine + header) writer.Flush() } } - -func (t *TelnetHandler) ServeTELNET(ctx telnet.Context, w telnet.Writer, r telnet.Reader) { - t.mu.Lock() - if t.connCount >= int(t.MaxConnNum) { - t.mu.Unlock() - w.Write([]byte("Connection limit reached. Try again later.\r\n")) - return - } - t.connCount++ - t.mu.Unlock() - - defer func() { - t.mu.Lock() - t.connCount-- - t.mu.Unlock() - }() - - writer := bufio.NewWriter(w) - reader := bufio.NewReader(r) - // 发送欢迎信息 - writer.WriteString("Welcome to the Telnet server!\r\n") - writer.Flush() - - // 请求用户名 - writer.WriteString("Username: ") - writer.Flush() - user, _ := reader.ReadString('\n') - user = strings.TrimSpace(user) - - // 关闭回显模式 - writer.Write([]byte{255, 251, 1}) // IAC WILL ECHO - writer.Flush() - - // 请求密码 - writer.WriteString("Password: ") - writer.Flush() - - // 读取密码并清除控制序列 - var passBuilder strings.Builder - for { - b, err := reader.ReadByte() - if err != nil { - return - } - if b == '\n' || b == '\r' { - break - } - if b == 255 { // IAC - reader.ReadByte() // 忽略下一个字节 - reader.ReadByte() // 忽略下一个字节 - } else { - passBuilder.WriteByte(b) - } - } - pass := passBuilder.String() - - // 恢复回显模式 - writer.Write([]byte{255, 252, 1}) // IAC WONT ECHO - writer.Flush() - - // w.Write([]byte("Welcome to the Telnet server!\r\n")) - // w.Write([]byte("Username: ")) - // writer := bufio.NewWriter(w) - // reader := bufio.NewReader(r) - // writer.Flush() - - // user, _ := reader.ReadString('\n') - // user = strings.TrimSpace(user) - - // w.Write([]byte("Password: ")) - // writer.Flush() - - // pass, _ := reader.ReadString('\n') - // pass = strings.TrimSpace(pass) - - if !t.HandleAuth(t.AuthType, user, pass) { - w.Write([]byte("\r\nAuthentication failed!\r\n")) - writer.Flush() - return - } - - w.Write([]byte("\r\nAuthentication successful!\r\n")) - writer.Flush() - - header := fmt.Sprintf("[%s@%s]> ", t.UserName, t.TagNE) - for { - w.Write([]byte(header)) - var command strings.Builder - for { - b := make([]byte, 1) - _, err := r.Read(b) - if err != nil { - return - } - if b[0] == '\r' || b[0] == '\n' { - break - } - command.WriteByte(b[0]) - } - cmd := strings.TrimSpace(command.String()) - switch cmd { - case "hello": - w.Write([]byte("Hello, world!\r\n")) - case "time": - w.Write([]byte(fmt.Sprintf("Current time: %s\r\n", time.Now().Format(time.RFC1123)))) - case "exit", "quit": - w.Write([]byte("Goodbye!\r\n")) - return - default: - w.Write([]byte("Unknown command\r\n")) - } - } -} - -func (t *TelnetHandler) HandleAuth(authType, userName, password string) bool { - switch authType { - case "local": - if userName == t.UserName && password == t.Password { - return true - } - return false - case "radius": - exist, err := dborm.XEngDB().Table("OMC_PUB.sysUser").Where("userName=? AND password=md5(?)", userName, password).Exist() - if err != nil { - return false - } - return exist - case "omc": - - default: - } - - return false -} - -func (t *TelnetHandler) StartTelnetServer() { - // //handle := TelnetHandler{} - // listener, err := net.Listen("tcp", t.ListenHost) - // if err != nil { - // fmt.Println("Error starting Telnet server:", err) - // return - // } - // defer listener.Close() - // fmt.Printf("Telnet server started on %s\n", t.ListenHost) - - // go telnet.Serve(listener, t) - go telnet.ListenAndServe(t.ListenHost, t) -}