Go言語でtelnet通信 (reiver/go-telnetを使ってみた)

golang でtelnetサーバーとクライアントを用意してみました。

github.com/reiver/go-telnet というライブラリがあるので、
こちらを使えば好きなtelnetサーバーを簡単に用意できるみたいです。

telnetとは

telnetは、リモートサーバーを操作する為のコマンドでしたが、
平文をそのまま送信する為に盗聴される危険性があるため、暗号化通信が出来るsshに取って代わられたものです。

なので、サーバー操作を目的として、telnetサーバーをわざわざ外部に公開しているところはないでしょう。

今では、そういったコマンドなどのソフトフェアとしての意味よりも、
アプリケーション層プロトコルとして
単純に平文での通信プロトコル自体をtelnetと呼ぶ事の方が多いようです。

用途としては、ローカルマシン内での通信テストや
安全なLAN内でのみ通信する場合に使えるのかなと。

go-telnet

Go言語で実装されたTelnetプロトコルの実装ライブラリ
https://github.com/reiver/go-telnet

go get -v -u github.com/reiver/go-telnet

サンプルに記載のサーバーソースと、クライアントソースを使えば、簡単にエコーしてくれるものが出来上がります。
また、SSL認証をおこなう。TELNETSもサポートしているようです。

Serverサンプル

go-telnetを使った、サーバー側のサンプルです。

ServeTELNETメソッドをもった構造体をHandlerとして、
telnet.ListenAndServeメソッドに渡せば良いだけです。

telnet接続されると、ServeTELNETメソッド内で、Readerから読み取り待機し続けます。
接続が切れると、errを返す為、ループから抜けるようになってます。

func server() error {
    return telnet.ListenAndServe(fmt.Sprintf(":%d", 5555), handler{})
}

type handler struct{}

func (h handler) ServeTELNET(ctx telnet.Context, w telnet.Writer, r telnet.Reader) {
    println("-- connect --")

    var buffer [1]byte
    p := buffer[:]

    for {
        n, err := r.Read(p)
        if n > 0 {
            bytes := p[:n]
            print(string(bytes))
        }

        if nil != err {
            break
        }
    }

    println("-- disconnect --")
}

Clientサンプル

クライアント側のサンプルです。

こちらも似たようなもので、CallTELNETメソッドを実装した構造体をCallerとして
telnet.DialToAndCallメソッドに渡すだけです。

指定の接続先に接続が成功すると、CallTELNETメソッドがコールされます。
Writerに対して、バイト配列を送信する事ができます。

Readerから、サーバーから来たデータを読み取る事ができます。

今回は、標準入力を一方的に送信するようなサンプルです。

func client() error {
    return telnet.DialToAndCall("localhost:5555", caller{})
}

type caller struct{}

func (c caller) CallTELNET(ctx telnet.Context, w telnet.Writer, r telnet.Reader) {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        oi.LongWrite(w, scanner.Bytes())
        oi.LongWrite(w, []byte("\n"))
    }
}

起動デモ

サーバーを立ち上げてみて、クライアントで接続してみるデモです。

もちろん、telnetコマンドでも接続して、メッセージを送ることが出来ます。

simple-telnetコマンド

あと、上記のサンプルを元に、telnetでサーバーとクライアントを用意するコマンドを作成しました。

https://gitlab.com/tyabuta/go-simple-telnet

shellscriptで 、telnet接続してメッセージ送るだけの時に、代わりに使えるかと思います。

echo "送りたいメッセージ" | simple-telnet -H localhost -P 5555

おしまい

telnetについて、多少イメージできるようになりました。

コマンドとしてのtelnetと、プロトコルとしてのtelnet。
どちらの話をしているのか、認識が違うと会話できないなと思いました。

コメントを残す