golang SSH客戶端三件套 - 1遠(yuǎn)程連接 shell

golang SSH客戶端系列文章目錄

  1. 遠(yuǎn)程登錄
  2. 端口映射
  3. 文件傳輸

SSH(Secure Shell)協(xié)議在遠(yuǎn)程登錄時(shí)比較常用,但是除此之外還有一些其它的功能也很好用,比如端口映射,X11轉(zhuǎn)發(fā),sftp文件傳輸?shù)取?/p>

以下三篇文章將介紹golang版SSH的遠(yuǎn)程登錄功能,端口映射功能及sftp文件傳輸功能。X11包含GUI的一些操作,沒有找到相關(guān)的包,故不做介紹

通過golang自帶的ssh包 golang.org/x/crypto/ssh 可以實(shí)現(xiàn)遠(yuǎn)程登錄功能,默認(rèn)是不支持tab鍵和上下箭頭的,
通過導(dǎo)入golang.org/x/crypto/ssh/terminal來創(chuàng)建VT100終端可以支持tab等功能,讓golang版本的ssh客戶端體驗(yàn)和平時(shí)用的其它客戶端差不多。

package main

import (
    "golang.org/x/crypto/ssh"
    "golang.org/x/crypto/ssh/terminal"
    "log"
    "os"
    "time"
)

/**
golang版本的SSH客戶端
SSH協(xié)議RFC文檔
https://tools.ietf.org/html/rfc4254

一個(gè)ssh連接可以打開多個(gè)會(huì)話session
linux tty和pty區(qū)別
開機(jī)后登錄系統(tǒng)的終端稱為tty
遠(yuǎn)程登錄的終端稱為pty
pts是pty的實(shí)現(xiàn)方式
w命令可以顯示當(dāng)前系統(tǒng)登錄的終端列表
針對(duì)交互式會(huì)話的操作
1.請(qǐng)求偽終端 pty-req
2.X11轉(zhuǎn)發(fā) x11-req
3.X11通道 x11
4.環(huán)境變量 env
5.啟動(dòng)shell或命令 shell/exec/subsystem

默認(rèn)不支持上下鍵和tab鍵,還不支持clear清屏指令
通過VT100終端支持tab和clear指令
VT100終端包括一些控制符,可以在終端中顯示不同顏色,支持光標(biāo)控制,清屏指令等
http://www.termsys.demon.co.uk/vtansi.htm
*/
func main() {
    sshConfig := &ssh.ClientConfig{
        User: "user",
        Auth: []ssh.AuthMethod{
            ssh.Password("123456"),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
        ClientVersion:   "",
        Timeout:         10 * time.Second,
    }
    //建立與SSH服務(wù)器的連接
    sshClient, err := ssh.Dial("tcp", "192.168.1.8:22", sshConfig)
    if err != nil {
        log.Fatalln(err.Error())
    }
    defer sshClient.Close()
    log.Println("sessionId: ", sshClient.SessionID())
    log.Println("user: ", sshClient.User())
    log.Println("ssh server version: ", string(sshClient.ServerVersion()))
    log.Println("ssh client version: ", string(sshClient.ClientVersion()))

    //打開交互式會(huì)話(A session is a remote execution of a program.)
    //https://tools.ietf.org/html/rfc4254#page-10
    session, err := sshClient.NewSession()
    if err != nil {
        log.Fatalln("Failed to create ssh session", err)
    }

    defer session.Close()

    modes := ssh.TerminalModes{
        ssh.ECHO:          1,     //打開回顯
        ssh.TTY_OP_ISPEED: 14400, //輸入速率 14.4kbaud
        ssh.TTY_OP_OSPEED: 14400, //輸出速率 14.4kbaud
        ssh.VSTATUS:       1,
    }

    //使用VT100終端來實(shí)現(xiàn)tab鍵提示,上下鍵查看歷史命令,clear鍵清屏等操作
    //VT100 start
    //windows下不支持VT100
    fd := int(os.Stdin.Fd())
    oldState, err := terminal.MakeRaw(fd)
    if err != nil {
        log.Fatalln(err.Error())
    }
    defer terminal.Restore(fd, oldState)
    //VT100 end

    termWidth, termHeight, err := terminal.GetSize(fd)

    session.Stdin = os.Stdin
    session.Stdout = os.Stdout
    session.Stderr = os.Stderr

    //打開偽終端
    //https://tools.ietf.org/html/rfc4254#page-11
    err = session.RequestPty("xterm", termHeight, termWidth, modes)
    if err != nil {
        log.Fatalln(err.Error())
    }

    //啟動(dòng)一個(gè)遠(yuǎn)程shell
    //https://tools.ietf.org/html/rfc4254#page-13
    err = session.Shell()
    if err != nil {
        log.Fatalln(err.Error())
    }

    //等待遠(yuǎn)程命令結(jié)束或遠(yuǎn)程shell退出
    err = session.Wait()
    if err != nil {
        log.Fatalln(err.Error())
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容