fix: telnet server enhancement...
This commit is contained in:
308
sshsvc/telnet/telnet.go
Normal file
308
sshsvc/telnet/telnet.go
Normal file
@@ -0,0 +1,308 @@
|
||||
package telnetOMC
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"github.com/reiver/go-telnet"
|
||||
)
|
||||
|
||||
type TelnetHandler struct {
|
||||
ListenAddr string
|
||||
ListenPort uint16
|
||||
UserName string
|
||||
Password string
|
||||
AuthType string
|
||||
MaxConnNum uint8
|
||||
TagNE string
|
||||
ListenHost string
|
||||
|
||||
connCount int
|
||||
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"))
|
||||
return
|
||||
}
|
||||
t.connCount++
|
||||
t.mu.Unlock()
|
||||
|
||||
defer func() {
|
||||
t.mu.Lock()
|
||||
t.connCount--
|
||||
t.mu.Unlock()
|
||||
}()
|
||||
|
||||
reader := bufio.NewReader(r)
|
||||
writer := bufio.NewWriter(w)
|
||||
|
||||
// 发送欢迎信息
|
||||
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()
|
||||
|
||||
if t.HandleAuth(t.AuthType, user, pass) {
|
||||
writer.WriteString("\r\nAuthentication successful!\r\n")
|
||||
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 {
|
||||
writer.WriteString(clearLine + header)
|
||||
writer.Flush()
|
||||
|
||||
var commandBuilder strings.Builder
|
||||
for {
|
||||
b, err := reader.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if b == '\n' || b == '\r' {
|
||||
break
|
||||
}
|
||||
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())
|
||||
|
||||
// command, err := reader.ReadString('\n')
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// command = strings.TrimSpace(command)
|
||||
|
||||
// 处理其他命令
|
||||
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
|
||||
case "":
|
||||
// case "\n":
|
||||
// case "\r\n":
|
||||
case "\xff\xfe\x01":
|
||||
default:
|
||||
writer.WriteString("\r\nUnknown command\r\n")
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user