fix: telnet server update

This commit is contained in:
2024-09-14 14:44:02 +08:00
parent a0ad5fbd53
commit 9e71a35cd7
2 changed files with 72 additions and 220 deletions

View File

@@ -19,7 +19,7 @@ import (
"be.ems/sshsvc/config" "be.ems/sshsvc/config"
"be.ems/sshsvc/logmml" "be.ems/sshsvc/logmml"
"be.ems/sshsvc/snmp" "be.ems/sshsvc/snmp"
telnetOMC "be.ems/sshsvc/telnet" omctelnet "be.ems/sshsvc/telnet"
//"github.com/gliderlabs/ssh" //"github.com/gliderlabs/ssh"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
@@ -126,18 +126,18 @@ func main() {
// os.Exit(6) // os.Exit(6)
// } // }
telnetSvc := telnetOMC.TelnetHandler{ telnetSvc := omctelnet.TelnetHandler{
// ListenAddr: conf.TelnetServer.ListenAddr, ListenAddr: conf.TelnetServer.ListenAddr,
// ListenPort: conf.TelnetServer.ListenPort, ListenPort: conf.TelnetServer.ListenPort,
// UserName: conf.TelnetServer.UserName, UserName: conf.TelnetServer.UserName,
// Password: conf.TelnetServer.Password, Password: conf.TelnetServer.Password,
// AuthType: conf.TelnetServer.AuthType, AuthType: conf.TelnetServer.AuthType,
// MaxConnNum: conf.TelnetServer.MaxConnNum, MaxConnNum: conf.TelnetServer.MaxConnNum,
// TagNE: conf.TelnetServer.TagNE, TagNE: conf.TelnetServer.TagNE,
ListenHost: conf.TelnetServer.ListenAddr + ":" + strconv.Itoa(int(conf.TelnetServer.ListenPort)), ListenHost: conf.TelnetServer.ListenAddr + ":" + strconv.Itoa(int(conf.TelnetServer.ListenPort)),
} }
// go telnetSvc.StartTelnetServer() go telnetSvc.StartTelnetServer()
go StartTelnetServer(telnetSvc.ListenHost) // go StartTelnetServer(telnetSvc.ListenHost)
snmpSvc := snmp.SNMPService{ snmpSvc := snmp.SNMPService{
ListenAddr: conf.SNMPServer.ListenAddr, ListenAddr: conf.SNMPServer.ListenAddr,
@@ -335,9 +335,6 @@ func HandleCommands(user, tag string, reader *bufio.Reader, writer *bufio.Writer
writer.Flush() writer.Flush()
return return
case "": case "":
// case "\n":
// case "\r\n":
case "\xff\xfe\x01":
default: default:
writer.WriteString("\r\nUnknown command\r\n") writer.WriteString("\r\nUnknown command\r\n")
writer.Flush() 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) { func handleSSHConnection(conn net.Conn, serverConfig *ssh.ServerConfig) {
// SSH握手 // SSH握手
sshConn, chans, reqs, err := ssh.NewServerConn(conn, serverConfig) sshConn, chans, reqs, err := ssh.NewServerConn(conn, serverConfig)

View File

@@ -1,14 +1,15 @@
package telnetOMC package omctelnet
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"io"
"net"
"strings" "strings"
"sync" "sync"
"time" "time"
"be.ems/lib/dborm" "be.ems/lib/dborm"
"github.com/reiver/go-telnet"
) )
type TelnetHandler struct { type TelnetHandler struct {
@@ -25,24 +26,66 @@ type TelnetHandler struct {
mu sync.Mutex mu sync.Mutex
} }
func (t *TelnetHandler) HandleTelnetConnection(w telnet.Writer, r telnet.Reader) { func (t *TelnetHandler) handleTelnetAuth(authType, userName, password string) bool {
t.mu.Lock() switch authType {
if t.connCount >= int(t.MaxConnNum) { case "local":
t.mu.Unlock() if userName == t.UserName && password == t.Password {
w.Write([]byte("Connection limit reached. Try again later.\r\n")) 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 return
} }
t.connCount++ defer listener.Close()
t.mu.Unlock() 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() { defer func() {
t.mu.Lock() t.mu.Lock()
t.connCount-- t.connCount--
t.mu.Unlock() t.mu.Unlock()
}() }()
defer conn.Close()
reader := bufio.NewReader(r) reader := bufio.NewReader(conn)
writer := bufio.NewWriter(w) writer := bufio.NewWriter(conn)
// 发送欢迎信息 // 发送欢迎信息
writer.WriteString("Welcome to the Telnet server!\r\n") 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.Write([]byte{255, 252, 1}) // IAC WONT ECHO
writer.Flush() writer.Flush()
if t.HandleAuth(t.AuthType, user, pass) { if t.handleTelnetAuth(t.AuthType, user, pass) {
writer.WriteString("\r\nAuthentication successful!\r\n") writer.WriteString("\r\nAuthentication successful!\r\n")
writer.Flush() writer.Flush()
t.HandleCommands(user, t.TagNE, reader, writer) 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) { func (t *TelnetHandler) HandleCommands(user, tag string, reader *bufio.Reader, writer *bufio.Writer) {
header := fmt.Sprintf("[%s@%s]> ", user, tag) header := fmt.Sprintf("[%s@%s]> ", user, tag)
clearLine := "\033[2K\r" // ANSI 转义序列,用于清除当前行 clearLine := "\033[2K\r" // ANSI 转义序列,用于清除当前行
for { for {
writer.WriteString(clearLine + header)
writer.Flush()
var commandBuilder strings.Builder var commandBuilder strings.Builder
for { for {
b, err := reader.ReadByte() b, err := reader.ReadByte()
@@ -112,6 +152,9 @@ func (t *TelnetHandler) HandleCommands(user, tag string, reader *bufio.Reader, w
if b == '\n' || b == '\r' { if b == '\n' || b == '\r' {
break break
} }
if b == '\xff' || b == '\xfe' || b == '\x01' {
continue
}
if b == 127 { // 处理退格键 if b == 127 { // 处理退格键
if commandBuilder.Len() > 0 { 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 := strings.TrimSpace(commandBuilder.String())
// command, err := reader.ReadString('\n')
// if err != nil {
// return
// }
// command = strings.TrimSpace(command)
// 处理其他命令 // 处理其他命令
switch command { switch command {
case "hello": case "hello":
@@ -148,161 +185,11 @@ func (t *TelnetHandler) HandleCommands(user, tag string, reader *bufio.Reader, w
writer.Flush() writer.Flush()
return return
case "": case "":
// case "\n":
// case "\r\n":
case "\xff\xfe\x01":
default: default:
writer.WriteString("\r\nUnknown command\r\n") writer.WriteString("\r\nUnknown command\r\n")
writer.Flush()
} }
writer.WriteString(clearLine + header)
writer.Flush() 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)
}