3
0

More than 3 years have passed since last update.

Docker Alpineコンテナを利用したSSHサーバーの構築

Posted at

はじめに

最終的にはKubernetesでの利用を考えているrsyncバックアップ用のサーバーを構築するために、AlpineコンテナでSSHサーバーを稼動するテストを行ないました。

その際に、パスワード認証はできるものの、公開鍵を利用したログインができなかったため事象が発生しました。

Ubuntuベースで作成したプロトタイプを元にしていますが、Alpineに移行したのでそのDockerfileなどをメモしておくことにしました。

参考資料

コンテナの構築

Dockerファイルはだいたい次のような内容になっています。
Alpineイメージで/etc/init.d/のスクリプトを起動させるには、openrcパッケージを利用しますが、今回は直接起動するためインストールしていません。

Dockerfile
FROM alpine:3.13.5

RUN apk --no-cache add tzdata bash ca-certificates make openssh rsync openssl

ENV SSHD_CONFIG_FILEPATH /etc/ssh/sshd_config
ENV SSH_PUBKEY_FILEPATH /conf/id_key.pub
ENV SSH_AUTHKEYS_FILEPATH /root/.ssh/authorized_keys

COPY run.sh /run.sh
RUN chmod +x /run.sh

EXPOSE 22

ENTRYPOINT ["/run.sh"] 

最後に呼んでいるrun.shの中では次のような操作を行なっています。

run.sh
#!/bin/bash -x

SSHD_CONFIG_FILEPATH="${SSHD_CONFIG_FILEPATH:-/etc/ssh/sshd_config}"
SSH_SERVERKEYS_FILEPATH="${SSH_SERVERKEYS_FILEPATH_LIST:-/etc/ssh/ssh_host_rsa_key}"

## update the sshd_config file
echo "HostKey ${SSH_SERVERKEYS_FILEPATH}" >> "${SSHD_CONFIG_FILEPATH}"
echo "PubkeyAuthentication yes" >> "${SSHD_CONFIG_FILEPATH}"
echo "PasswordAuthentication no" >> "${SSHD_CONFIG_FILEPATH}"
echo "PermitRootLogin yes" >> "${SSHD_CONFIG_FILEPATH}"
echo "StrictModes yes" >> "${SSHD_CONFIG_FILEPATH}"

## prepare the ~/.ssh/authorized_keys
SSH_PUBKEY_FILEPATH="${SSH_PUBKEY_FILEPATH:-/conf/id_key.pub}"
SSH_AUTHKEYS_FILEPATH="${SSH_AUTHKEYS_FILEPATH:-/root/.ssh/authorized_keys}"
SSH_AUTHKEYS_BASEDIR="$(dirname ${SSH_AUTHKEYS_FILEPATH})"
mkdir -p "${SSH_AUTHKEYS_BASEDIR}"
chmod 700 "${SSH_AUTHKEYS_BASEDIR}"
cp "${SSH_PUBKEY_FILEPATH}" "${SSH_AUTHKEYS_FILEPATH}"
chmod 0600 "${ROOK_SSH_AUTHKEYS_FILEPATH}"

## change the root password
echo "root:$(openssl rand -hex 12)" | chpasswd

exec /usr/sbin/sshd -D

次に必要な秘密鍵・公開鍵を準備します。

ssh-keygenの利用
$ ssh-keygen -t ed25519 -f id_ed25519
$ ssh-keygen -t ed25519 -f ssh_host_ed25519_key

最終的に次のようなファイルを準備したことになります。

$ ls
Dockerfile  id_ed25519  id_ed25519.pub  run.sh  ssh_host_ed25519_key  ssh_host_ed25519_key.pub

Dockerコンテナのビルドと実行

準備したファイルを利用してDockerコンテナをビルドし、再現するかテストを行ないます。

buildとrun
$ sudo docker build . --tag sshd
$ sudo docker run -it --rm -v `pwd`/id_ed25519.pub:/conf/id_key.pub \
    -v `pwd`/ssh_host_ed25519_key:/etc/ssh/ssh_host_rsa_key \
    -p 2222:22 --name sshd sshd:latest

既存のsshdと競合しないように、2222番ポートを利用しています。環境に応じて変更してください。
無事に起動したら別のshellから接続を試みます。

あらかじめid_ed25519ファイルのあるディレクトリに移動してから進めます。

sshコマンドによる接続テスト
$ ls
Dockerfile  id_ed25519  id_ed25519.pub  run.sh  ssh_host_ed25519_key  ssh_host_ed25519_key.pub

$ ssh -i id_ed25519 -p 2222 root@localhost

エラーの原因について

遭遇したエラーについてまとめておきます。

エラーメッセージ

次のようなエラーメッセージが表示されています。

ログイン失敗時のログ
ssh -i conf/id_ed25519 -p 2222 root@localhost
root@localhost: Permission denied (publickey,keyboard-interactive).

次のようなメッセージが表示されるかもしれません。

ssh -i conf/id_ed25519 -p 2222 root@localhost
Received disconnect from 127.0.0.1 port 2222:2: Too many authentication failures
Disconnected from 127.0.0.1 port 2222

エラー発生の可能性と原因

このような事象が発生しているのには、いつくかの理由が考えられます。

  • 接続しようとしているユーザーID(root)にパスワードが設定されていない
  • sshコマンドがpublickey認証に対応していない

前者はrun.shの中で強制的にランダムなパスワードを実行時に指定するようになっています。

後者の原因は、/etc/ssh/ssh_configや~/.ssh/ssh_configに、PreferredAuthentications passwordのような設定を入れている場合に発生します。

Dockerコンテナ側の/etc/passwdで該当ユーザーのログイン・シェルが設定されている必要もあります。
alpineの場合、ユーザーIDをadduserコマンドでDockerfileで作成しただけでは、ログイン・シェルが/sbin/nologinなどに設定されていまいます。

一般ユーザーを追加する際の考慮点

chshコマンドはshadowパッケージから導入できますが、非対話的に設定することができないようなので、次のように一般ユーザーを作成しています。

test01ユーザーを作成する例
RUN adduser -S test01 && echo "test01:secret-password" | chpasswd
RUN sed -i -e '/test01/s/sbin\/nologin/bin\/bash/' /etc/passwd

一応chpasswdコマンドを実行していますが、実際にはrootユーザーと同様に実行時にランダムなパスワードを設定する方法がお勧めです。

また、sedコマンドはbusybox版なので、デリミタに'/'文字以外を指定することはできません。

以上

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0