package omctelnet import ( "bufio" "fmt" "io" "net" "strings" "sync" "time" "be.ems/lib/dborm" ) type TelnetHandler struct { ListenAddr string ListenPort uint16 UserName string Password string AuthType string MaxConnNum int TagNE string ListenHost string connCount int mu sync.Mutex } 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 } 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() msg := fmt.Sprintf("Connection limit reached (limit=%d). Try again later.\r\n", t.MaxConnNum) io.WriteString(conn, msg) 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(conn) writer := bufio.NewWriter(conn) // 发送欢迎信息 writer.WriteString(fmt.Sprintf("\r\nWelcome to the %s server!\r\n", strings.ToUpper(t.TagNE))) 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() if t.handleTelnetAuth(t.AuthType, user, pass) { msg := fmt.Sprintf("\r\n\r\nLast login: %s from %s \r\n\r\n", time.Now().Format(time.RFC1123), conn.RemoteAddr()) writer.WriteString(msg) writer.Flush() t.HandleCommands(user, t.TagNE, reader, writer) } else { writer.WriteString("\r\nAuthentication failed!\r\n") writer.Flush() } } // 处理命令输 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 { var commandBuilder strings.Builder for { b, err := reader.ReadByte() if err != nil { return } if b == '\n' || b == '\r' { break } if b == '\xff' || b == '\xfe' || b == '\x01' { continue } if b == 127 { // 处理退格键 if commandBuilder.Len() > 0 { // 手动截断字符串 command := commandBuilder.String() command = command[:len(command)-1] commandBuilder.Reset() commandBuilder.WriteString(command) writer.WriteString("\b \b") // 回显退格 writer.Flush() } } else { // 回显用户输入的字符 writer.WriteByte(b) writer.Flush() commandBuilder.WriteByte(b) } } command := strings.TrimSpace(commandBuilder.String()) // 处理其他命令 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\n\r\nGoodbye!\r\n") writer.Flush() return case "": default: writer.WriteString("\r\nUnknown command\r\n") writer.Flush() } writer.WriteString(clearLine + header) writer.Flush() } }