コンテンツにスキップ

Ubuntuでssh接続のセキュリティを向上

一般ユーザーの$HOME/.ssh/authorized_keysに、クライアントの公開鍵を登録済みであることを前提としています。

Terminal window
cat "${HOME}/.ssh/authorized_keys" # ssh-ed25519 AAAA...
rootにssh接続している場合

一般ユーザーを作成・ログイン(su - USERNAME)し、/root/.ssh/authorized_keys$HOME/.ssh/authorized_keysにコピーします。

Terminal window
mkdir -p "${HOME}/.ssh"
chmod 700 "${HOME}/.ssh"
sudo cp /root/.ssh/authorized_keys "${HOME}/.ssh/authorized_keys"
sudo chmod 600 "${HOME}/.ssh/authorized_keys"
sudo chown -R "${USER}":"${USER}" "${HOME}/.ssh"

一度切断し、一般ユーザーで ssh 接続します。

Terminal window
ssh USERNAME@xxx.xxx.xxx.xxx

openssh-serverをインストール

Terminal window
sudo apt-get update
sudo apt-get install openssh-server -y
# 自動で起動するはずですが念のため有効化
sudo systemctl enable --now ssh

SSH 設定のカスタマイズ

メインの設定ファイルを直接編集するのではなく、/etc/ssh/sshd_config.d/下に設定ファイルを作成して管理します。

設定ファイルの作成

パスワード認証の禁止や root ログインの拒否を含む設定を作成します。

Terminal window
sudo mkdir -p /etc/ssh/sshd_config.d
# ポート番号を指定(一般的には22)
SSH_PORT="22"
sudo tee /etc/ssh/sshd_config.d/99-secure-ssh.conf >/dev/null <<EOF
# ルートログインの禁止
PermitRootLogin no
# 公開鍵認証のみ許可(パスワード/対話認証を禁止)
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
# SSHポートの変更
Port ${SSH_PORT}
# 認証試行回数の制限
MaxAuthTries 3
# セッション維持(無通信での切断調整)
ClientAliveInterval 300
ClientAliveCountMax 2
# 許可するユーザーを指定(必要に応じて複数指定可能)
AllowUsers ${USER}
EOF

メイン設定への反映確認

/etc/ssh/sshd_config の先頭付近で設定ディレクトリが読み込まれているか確認し、構文チェックを行います。

Terminal window
# Ubuntuでは通常最初から Include が設定されていますが、なければ追加します。
if ! sudo grep -qE '^\s*Include\s+/etc/ssh/sshd_config\.d/\*\.conf' /etc/ssh/sshd_config; then
sudo sed -i '1s/^/Include \/etc\/ssh\/sshd_config.d\/\*\.conf\n/' /etc/ssh/sshd_config
fi
# 構文チェック
sudo sshd -t
# 反映後の設定を確認
sudo sshd -T | sed -n 's/^port /port /p; s/^permitrootlogin /permitrootlogin /p; s/^passwordauthentication /passwordauthentication /p; s/^kbdinteractiveauthentication /kbdinteractiveauthentication /p; s/^allowusers /allowusers /p'

問題がなければ、SSH サービスを再起動(またはリロード)します。

Terminal window
# Ubuntuのサービス名は通常 ssh です(sshd ではない点に注意)
sudo systemctl reload ssh || sudo systemctl restart ssh

ポートを変更した場合、以後の接続はssh -p ${SSH_PORT} USERNAME@...が必要です。

ファイアウォール(UFW)の設定

不要なポートを閉じ、SSH ポートに対しては接続試行回数に制限をかけます。

SSH ポートを変更した場合、設定適用前に新ポートを許可してください(締め出し防止)。

Terminal window
sudo apt-get install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
SSH_PORT="22"
# SSHポートを制限付きで許可
sudo ufw limit ${SSH_PORT}/tcp
# Webサーバー用(必要なら)
sudo ufw allow http
sudo ufw allow https
# 有効化
sudo ufw enable
# 確認
sudo ufw status numbered
実行結果
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp LIMIT IN Anywhere
[ 2] 80/tcp ALLOW IN Anywhere
[ 3] 443 ALLOW IN Anywhere
[ 4] 22/tcp (v6) LIMIT IN Anywhere (v6)
[ 5] 80/tcp (v6) ALLOW IN Anywhere (v6)
[ 6] 443 (v6) ALLOW IN Anywhere (v6)
Dockerとの競合

https://docs.docker.com/engine/network/packet-filtering-firewalls/#docker-and-ufw

Docker で公開されたポートは、ufw のルール関係なく、外部からアクセス可能になります。

この問題を防ぐために、外部に公開する必要がない場合、Docker のコマンドでローカルホストのみに制限します。

Terminal window
# NG
# docker run -p 8080:80 nginx
# OK
docker run -p 127.0.0.1:8080:80 nginx

また、Docker Compose であれば

OK
1
services:
2
app:
3
ports:
4
- '127.0.0.1:8080:80'

Fail2Ban による不正アクセス遮断

ログを監視し、短時間に何度もログインに失敗した IP アドレスを自動的に一定期間(または永久に)BAN します。

Fail2Ban のインストール

Terminal window
sudo apt-get install fail2ban -y

監獄(Jail)の設定

SSH 用の監視ルールをjail.localに記述します。

Terminal window
sudo tee /etc/fail2ban/jail.local >/dev/null <<JAIL_LOCAL
[sshd]
enabled = true
backend = systemd
bantime = -1
findtime = 600
maxretry = 3
JAIL_LOCAL

サービスの起動

Terminal window
sudo systemctl enable --now fail2ban

設定が完了したら、(必要に応じて)システムを再起動して正しく接続できるか確認してください。

Terminal window
sudo reboot

再起動後、BAN されたログなどは/var/log/fail2ban.logで確認できます。

Terminal window
sudo tail -f /var/log/fail2ban.log

以下で、どの程度 BAN されているか確認できます。

Terminal window
sudo fail2ban-client status sshd
Terminal window
Status for the jail: sshd
|- Filter
| |- Currently failed: 3
| |- Total failed: 18
| `- Journal matches: _SYSTEMD_UNIT=ssh.service + _COMM=sshd
`- Actions
|- Currently banned: 2
|- Total banned: 2
`- Banned IP list: xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy