Quantcast
Channel: Active questions tagged ubuntu - Stack Overflow
Viewing all articles
Browse latest Browse all 7072

SSH-bound Go CLI Daemon – SSH Connects Successfully, but No Input Accepted

$
0
0

I'm building a custom CLI daemon in Go for Ubuntu.When I run the CLI locally (without SSH), everything works correctly — for example:

admin@admin> whoami

responds as expected.

However, after binding the CLI loop to an SSH session and running it as a server, I can successfully SSH into it and see the banner and prompt, but no keyboard input is accepted. The session displays output, but I cannot type anything — not even a single character.

So the issue is:🟢 Local CLI → input works normally🟢 SSH connection → connects and shows prompt🔴 SSH session → no input is received inside my Go program

Below is my code, for the daemon:

package mainimport ("bufio""database/sql""fmt""log""os""os/exec""strconv""strings""time""github.com/gliderlabs/ssh"    _ "github.com/mattn/go-sqlite3""golang.org/x/crypto/bcrypt")const dbPath = "/opt/ngfw/auth/db/admins.db"// ---------------- AUTH --------------------func authUser(username, password string) bool {    db, err := sql.Open("sqlite3", dbPath)    if err != nil {        log.Println("DB error:", err)        return false    }    defer db.Close()    var hash string    err = db.QueryRow("SELECT password FROM users WHERE username=?", username).Scan(&hash)    if err != nil {        return false    }    return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil}// ---------------- SYSTEM INFO --------------------func showSystem(s ssh.Session) {    hostname, _ := os.Hostname()    uptimeBytes, _ := os.ReadFile("/proc/uptime")    uptimeParts := strings.Fields(string(uptimeBytes))    uptimeSec, _ := strconv.ParseFloat(uptimeParts[0], 64)    uptime := time.Duration(uptimeSec) * time.Second    kernelBytes, _ := exec.Command("uname", "-r").Output()    kernel := strings.TrimSpace(string(kernelBytes))    fmt.Fprintf(s, "\nSystem Information\n")    fmt.Fprintf(s, "-------------------\n")    fmt.Fprintf(s, "Hostname:       %s\n", hostname)    fmt.Fprintf(s, "Version:        0.1-dev\n")    fmt.Fprintf(s, "Kernel:         %s\n", kernel)    fmt.Fprintf(s, "Uptime:         %s\n\n", uptime.Truncate(time.Second))}// ---------------- CLI LOOP --------------------func cliSession(s ssh.Session) {    hostname, _ := os.Hostname()    user := s.User()    pty, _, ok := s.Pty()    fmt.Fprintf(s, "\n[DEBUG] PTY OK=%v TERM=%s\n", ok, pty.Term)    reader := bufio.NewReader(s)    fmt.Fprintf(s, "DEBUG READ TEST...\n")    b, err := reader.Peek(1)    fmt.Fprintf(s, "PEEK=%v ERR=%v\n", b, err)    fmt.Fprintf(s, "\n🔥 Welcome to CLI 🔥\nLogged in as: %s\n\n", user)    for {        fmt.Fprintf(s, "%s@%s> ", user, hostname)        line, err := reader.ReadString('\n')        if err != nil {            fmt.Fprintln(s, "\n🛑 Lost input stream — disconnecting")            return        }        cmd := strings.TrimSpace(line)        switch cmd {        case "whoami":            fmt.Fprintln(s, user)        case "show ?":            fmt.Fprintln(s, "\nAvailable SHOW commands:")            fmt.Fprintln(s, "  system")            fmt.Fprintln(s, "  interfaces (coming soon)")            fmt.Fprintln(s, "  users (coming soon)")        case "show system":            showSystem(s)        case "exit":            fmt.Fprintln(s, "🫡 Logging out…")            return        default:            if cmd != "" {                fmt.Fprintf(s, "%s: command not found\n", cmd)            }        }    }}// ---------------- SSH SERVER --------------------func main() {    fmt.Println("🔥 SSH CLI STARTED on port 2222")    ssh.Handle(cliSession)    log.Fatal(ssh.ListenAndServe(":2222",        nil,        ssh.PasswordAuth(func(ctx ssh.Context, pass string) bool {            return authUser(ctx.User(), pass)        }),    ))}

Help is appreciated


Viewing all articles
Browse latest Browse all 7072

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>