Docker上でSSHによるアクセスが可能なシリアルコンソールサーバーを作成します。ネットワーク機器等を操作するためにシリアルコンソールサーバーがあると便利ですが、安価ではないため手作りしたいと思います。
シリアルコンソールへのアクセス
今回はUSBシリアルコンソールを使います。ベースイメージはalpineです。ホストはUbuntu 22.04を使用しています。
docker run -d -p 2001:22 --device=/dev/ttyUSB0:/dev/ttyUSB alpine:3.18
とりあえずコンテナを立ち上げます。--device
でホスト上の/dev/ttyUSB0
をコンテナ上の/dev/ttyUSB
にマウントさせます。ポートも開放しておきます。
microcom -s 9600 /dev/ttyUSB0
busyboxのmicrocomを使用してシリアルコンソールを操作します。ctrl + x
で終了できます。
SSHサーバーの設定
SSHサーバーをインストールします。
apk add openssh-server
コンソールサーバーとして使用するため、/etc/ssh/sshd_config
を編集してSFTPやポートフォワード機能等は無効化しておきます。
Port 22
PasswordAuthentication yes
PermitRootLogin no
AllowAgentForwarding no
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
#Subsystem sftp internal-sftp
SSHログイン時に/etc/motd
の内容が表示されるため、コンソールサーバーらしい文面に書き換えます。
#-----------------------
# Serial Console Server
#-----------------------
ssh-keygen -A
で事前にホスト鍵を生成しおく必要があります。sshd
は-D
オプションによりデーモン化せずに起動可能です。-e
はログを標準出力に出力をするオプションです。
/usr/bin/ssh-keygen -A
/usr/sbin/sshd -D -e
ログインシェルの作成
コンソールサーバーとしてのみ使用可能とするため、SSHでログインするとシリアルコンソールターミナルが直接表示されるようにし、Linuxコマンドを実行できないようにします。アクセス用のユーザーを作成し、ログインシェルをmicrocomにすることで実現します。
#!/bin/sh
BUSY=`ps | grep microcom | wc -l`
if [ ! $BUSY -eq 1 ]; then
echo "This console is occupied."
exit 1
fi
/bin/busybox microcom -s 9600 /dev/ttyUSB
microcomを起動するためのスクリプトを作成します。シリアルコンソールは同時利用できないため、同時起動しようとすると終了する処理を入れています。(かなり適当です…)
chmod a+x /usr/local/bin/console.sh
echo "/usr/local/bin/console.sh" >> /etc/shells
実行権限を付与を忘れずに行います。/etc/shells
にパスを記載することで、ログインシェルとして使用可能になります。
ユーザーの作成
ログイン用のユーザーを作成します。
adduser -S user -s /usr/local/bin/console.sh -G dialout
echo user:user | chpasswd
adduser
コマンドでユーザーを追加できます。-S
でユーザー名を指定します。-s
でログインシェルに先ほど作成したスクリプトを指定します。/dev/ttyUSBにアクセスするために-G
でdialout
グループに所属させます。
echo <ユーザー名>:<パスワード> | chpasswd
でパスワードを設定します。
動作テスト
試しにホストからコンテナにSSHでアクセスしてみます。
$ ssh user@localhost -p 2001
user@localhost's password:
#-----------------------
# Serial Console Server
#-----------------------
(コンソールの内容)
上手くいけば、ログインするとそのままシリアルコンソールを使えるはずです。
Dockerfile
さきほどの内容をDockerfileに書き起こしました。
https://github.com/caribouHY/docker-serial-console-server/
FROM alpine:3.18
ENV USER="user"
ENV PASSWORD="password"
ENV SPEED="9600"
ENV TTY_DEVICE_PATH="/dev/ttyUSB"
RUN apk add --no-cache openssh-server
COPY ./login_text.txt /etc/motd
COPY ./entrypoint.sh /entrypoint.sh
COPY ./console.sh /usr/local/bin/console.sh
COPY ./sshd_config /etc/ssh/sshd_config
RUN chmod u+x /entrypoint.sh && \
echo /bin/busybox microcom -s $SPEED $TTY_DEVICE_PATH >> /usr/local/bin/console.sh && \
chmod a+x /usr/local/bin/console.sh && \
echo "/usr/local/bin/console.sh" >> /etc/shells
EXPOSE 22/tcp
ENTRYPOINT [ "/entrypoint.sh" ]
環境変数でユーザー名/パスワードやシリアルの速度を設定できるようにしてあります。
docker build -t console-server .
docker run -d -p 2001:22 --device=/dev/ttyUSB0:/dev/ttyUSB \
-e USER:user -e PASSWORD:user console-server
とりあえず動作はしていますが、そのうちもう少し作り込みたいなと考えています。