世の中には
シリアルコンソールサーバーが必要な理由
世の中のネットワーク機器をはじめとする組み込み製品は、普段使っているPCのようなリッチなインターフェースを持っているとは限りません。LAN経由で操作できればまだいいほうです。大抵の場合はD-Sub 9ピン

よってこれらの機器を操作するためには、シリアルコンソールが必要になります[2]。しかしながら最近のPCには、D-Sub 9ピンのポートはありません。そこでよく使うのが、シリアルポートが搭載されたPCIeカードや、USBシリアル変換ケーブルです。しかしながら、ミニPCだとPCIeカードスロットがないことも多いですし、USBの場合はたくさんの機器をつなぐとなると十分な数のUSBポートが必要になります。また、どのポートがどの機器に繋がっているかの管理も必要です[3]。
安価なシリアルケーブルはノイズに弱く、距離を稼げません。つまりターゲット機材から手元のマシンまでコンソールケーブルをひけないことも多々あります。よしんばひけたとしても、使う人が変わる度にケーブルをひきなおすのは面倒です。このケーブルはどのデバイスに繋がっているのか、クロスとストレートどっちだっけ、ジェンダーチェンジャーどこやったーなど、きちんと管理できていないと悲惨です。
そこで出てくるのがシリアルコンソールサーバーです。とりあえずコンソールケーブルをつなぐマシンを用意しておき、あとはネットワークを経由してそのサーバーにアクセスしましょうという仕組みです。きちんとした品質・
それで事足りるのであれば今回の話は終了です。次週のRecipeにご期待ください。ありがとうございました。
さて、単にSSHサーバーを用意するだけでなく、もう少しコンソールポートの管理っぽいものも導入したいことがあるでしょう。たとえば次のような状況を考えてみます。
- シリアルポートごとにボーレートなどの設定が異なり、アクセスするたびに正しい速度を確認するのが面倒
- 誰かが使っていても同時に接続したいもしくは使用しているユーザーをキックしたい
- シリアルコンソールの操作履歴をログとして常に残しておきたい
- 踏み台となるSSHサーバーのアカウント管理をしたくない、使用者全員をdialoutグループに入れたくない
いずれも踏み台サーバーでも実現できるけれども、若干面倒な対応が必要となります。これを実現するのが今回紹介する
ser2netはYAML形式でシリアルコンソール設定を管理でき、なおかつ上記のような機能を実現できます。具体的には次のような機能を備えています。
- 一般的なtelnetコマンドでシリアルコンソールにアクセスできる
- 複数ユーザーの同時接続のサポート
- 新規ユーザーが接続した場合に、古いユーザーを排除する機能
- IPMI SOLのサポート
- YAMLベースの柔軟な設定ファイルフォーマット
- 操作ログのファイルへの保存機能
- 無操作時の自動タイムアウト機能
- アクセス時のバナー表記のカスタマイズ
- mDNSによるシリアルコンソールごとの名前の公開
- SSL/
TLS証明書を利用したユーザー認証 - RFC 2217に準拠したコンソール接続オプションの変更
端的にいうと、ser2netはネットワーク経由でシリアルコンソールにつなげるプロキシサーバーです。また、ser2netはgensioをベースに作られています。よってgensioがサポートしているストリームであれば、たとえば音声なども同じ仕組みでやりとりできたりします。
基本的にtelnetプロトコルを使うため、経路は暗号化されない点に注意してください。もし暗号化したい場合は、SSL/
ちなみに似たような機能を持ったソフトウェアとしてConManが存在します。こちらもser2netでできることはたいていできます。ser2netはどこでもインストールされている可能性が高いtelnetコマンドを使えるのが利点で、ConManのほうはconmanプログラムを使って接続することになっています。それ以外の部分はConManのほうが高機能な印象です。ser2netでは管理が大変と感じるようになったら、ConManも試してみると良いでしょう。
Ubuntuにser2netをインストールする
前置きが長くなってしまいましたが、Ubuntuにser2netをインストールしましょう。
$ sudo apt install ser2net
一緒にALSAやAvahi関連のライブラリも入ってしまいます。これはser2netがlibgensioを使っており、libgensioがオーディオストリームの転送やmDNSによるサービス名の公開に対応しているためです。
次に/etc/
」
%YAML 1.1
---
define: &banner \r\nser2net port \p device \d [\B] (Ubuntu)\r\n\r\n
connection: &con1
accepter: telnet,2000
enable: on
options:
banner: *banner
kickolduser: true
connector: serialdev,
/dev/ttyUSB0,
115200n81,local
最初の2行はYAMLのメタデータです。
3行目は、YAMLのアンカーを定義しています。ここでは&banner
」*banner
」
\r\n
:CRLF\p
:accepterで指定しているポート番号を含む文字列(今回の例だと telnet,2000
)\d
:connectorで指定しているデバイス情報(今回の例だと serialdev,/dev/
)ttyUSB0,115200n81,local \B
:実際に使われているシリアルポートの情報(たとえば 115200N81,CLOCAL,HANGUP_
など)WHEN_ DONE
他に使えるエスケープシーケンスはmanページの
「connection: &con
」
accepter
:外部から接続するために必要なプロトコル、ポート番号などを指定する(今回の例だとtelnetプロトコルで2000番ポートを使う) enable
:この接続情報を有効化するかどうか。設定はするけれども一時的に使えなくしたい場合はoffを指定するoptions
:各種オプションbanner
:接続時に表示するバナー文字列。どのデバイスへと接続したかを明示したい場合に便利kickolduser
:新規接続時に古いユーザーを切断させるかどうかを指定するconnector
:シリアルポートに接続するオプション等を指定する(今回の例だと /dev/
に対して115200n81で接続する)ttyUSB0
おおよそ上記の説明を把握すれば、最低限の設定方法は想像できるでしょう。
accepter
とconnector
はgensioのオプションがそのまま使えます。たとえばaccepter
にtelnet(rfc2217)
」telnet,::1,2000
」
connector
はtelnet
を指定するとtelnetプロトコルでカスケード接続できますし、ipmisol
でIPMI SOLに接続できます。ちなみに上記の
設定を変更したら、ser2netを再起動しましょう。
$ sudo systemctl restart ser2net.service
ちなみに既に誰かがser2netに接続している場合は、すべて切断されてしまう点に注意してください。これで準備完了です。ser2netをインストールしたマシンもしくはその外からアクセスしてみます。
$ telnet 192.0.2.1 2000 Trying 192.0.2.1... Connected to 192.0.2.1. Escape character is '^]'. ser2net port telnet,2000 device serialdev, /dev/ttyUSB0, 115200n81,local [115200N81,CLOCAL,HANGUP_WHEN_DONE] (Ubuntu) ubuntu login:
無事にシリアルコンソールに接続し、ログインプロンプトが表示されました。あとはシリアルポートごとに設定connection
ブロック)
複数人が同時に接続できるようにする
ser2netの初期設定では、誰かが接続中の状態で別のユーザーが接続しようとしても、接続できないようになっています。これはoptions
ブロックの次の設定で変更可能です。
kickolduser
:新しい接続が優先され、古い接続は切断されるmax-connections
:同時接続可能な数を設定する
options:
kickolduser: false
max-connections: 3
たとえば上記のように設定した場合、新しいユーザーが接続しようとしても古い接続は維持されます。さらに最大3コネクションまでは同じポートで接続できるのです。
ちなみに同時接続した場合、あるコネクションで入力した文字列は、別のコネクションでもエコーバックされます。複数人が同時に接続して状態を操作手順を確認したい場合に便利です。
無操作時に自動でタイムアウトする
timeout
で、無操作時にconnector
が何も受信しないときに)
timeout: 30
前述のkickolduser
を使わない場合に、ずっとシリアルポートを握り続けることがないようにできます。
ロギング機能で常時ログを残すようにする
trace
機能を使うと、ユーザーがaccepter
に接続した間の操作ログをファイルに記録できます。
options:
trace-read: /var/log/con1.log
trace-timestamp: true
ここでtrace-read
」trace-read
」trace-write
」trace-both
」trace-{read,write,both}
は同時に指定することで、それぞれ別のファイルに保存できます。
ファイル名にはbanner
と同じエスケープシーケンスが使えます。ポート名にあわせたファイル名を指定したい場合に便利です。
trace-timestamp
はタイムスタンプを残してくれる機能なのですが、上記の設定だと接続時と切断時しか残してくれません。1行ごとに残したい場合は、trace-hexdump
オプションを使う必要があります。これは受信したデータのバイト列を十六進数で表示する仕組みです。何か変なバイト列が含まれていないかを確認する場合に便利です。
ちなみにtrace機能で記録できるのはユーザーがアクセスしている間のログだけです。常時保存されるわけではありません。たとえばカーネルのpanicのようにいつ起こるかわからないものを記録にとりたい場合は、常時接続する必要があります。前項の複数同時接続と組み合わせて使うことになるでしょう。
IPMI SOLに接続する
connector
にはシリアルコンソールデバイスだけでなく、IPMIのSerial Over Lan
connector: ipmisol,lan -U USER -P PASSWORD -p 9001 ipmi.example.org,115200
IPMIパスワードの指定が必要になります。たとえば-P *{パスワードファイル名}
」
一般的なPCを使う上でシリアルコンソールが必要になることはそこまでありません。そもそも最近のPCだとシリアルコンソール出力はもちろんのこと、シリアルポート自体がないことも普通です。
しかしながらサーバースペックなマシンに触れたり、ネットワーク装置や何らかの制御装置を使ってみると、シリアルコンソールの便利さが身にしみます。だってネットワークの設定を間違えても、まだリモートマシンを操作できる可能性が残るのですから。あと変なデバイスがいるせいで、NICデバイスをうまく認識できない場合もなんとかなりますし。ディスプレイがない環境でもGRUBを操作できるのもうれしいですよね。
このように何かあったときのための安心感を得る上で、シリアルコンソールは大変便利な仕組みです。ぜひご家庭の1Uサーバーやネットワークスイッチ、制御機器、Raspberry Piなどのシリアルコンソールの運用も、ser2netを使って見直してみてはいかがでしょうか。