外部に公開するWebサーバを構築する ~セキュリティ関連~

外部に公開するWebサーバを構築する ~セキュリティ関連~

はじめに

以前の記事で、自宅サーバ用に VLAN を構築したことを記事にしました。

今回は実際に公開するサーバをセキュリティを意識して設定していったことを備忘録として記述していこうと思います。

最終的な目標として、Docker コンテナで構築した Web サーバを公開できるところまでを目指します。

また、ローカルからの SSH 接続は既に設定済みであることを前提に進めていきます。

1. パッケージの更新

まずシステムのパッケージを最新の状態に保ちます。

$ sudo apt update && sudo apt upgrade -y

2.新しい管理者ユーザーの追加(必要に応じて)

最初に作成していたデフォルトユーザーが推測されやすいと思ったので、新たに管理者用のユーザーを作成します。作成後、古い管理者ユーザー無効化します。

2-1. 新規ユーザーの作成と sudo 権限の付与

$ sudo useradd -m -s /bin/bash -G sudo [new_admin_user] # 任意のユーザー名を指定

$ id [new_admin_user]
uid=1002([new_admin_user]) gid=1002([new_admin_user]) groups=1002([new_admin_user]),27(sudo),998(docker)

今回実行したuseraddコマンドのオプション一覧です。

オプション意味詳細説明
-mホームディレクトリ自動作成ユーザー作成時に /home/ユーザー名 ディレクトリを自動作成し、初期ファイル(.bashrc、.profile 等)をコピー/home/[new_admin_user] が作成される
-s /bin/bashデフォルトシェル指定ユーザーがログインした際に使用するシェルを指定/bin/bash/bin/sh/bin/zsh など
-G sudo追加グループ指定ユーザーを指定したグループに所属させ、該当する権限を付与sudo(管理者権限)、dockerwww-data など
[new_admin_user]ユーザー名システム内で一意のユーザー名を指定英数字、ハイフン、アンダースコアが使用可能

2-2. SSH公開鍵のコピー

現在のユーザーの公開鍵を新しいユーザーにコピーし、SSHでログインできるようにします。

$ sudo mkdir /home/[new_admin_user]/.ssh
$ sudo cp /home/user01/.ssh/authorized_keys /home/[new_admin_user]/.ssh/authorized_keys

2-3. パーミッションの設定

コピーした.sshディレクトリとauthorized_keysファイルに適切な権限を設定します。

$ sudo chown -R [new_admin_user]:[new_admin_user] /home/[new_admin_user]/.ssh
$ sudo chmod 700 /home/[new_admin_user]/.ssh
$ sudo chmod 600 /home/[new_admin_user]/.ssh/authorized_keys

$ ls -ld /home/[new_admin_user]/.ssh/
drwx------ 2 [new_admin_user] [new_admin_user] 4096  83 08:05 /home/[new_admin_user]/.ssh/

$ ls -l /home/[new_admin_user]/.ssh/authorized_keys
-rw------- 1 [new_admin_user] [new_admin_user] 105  627 11:25 /home/[new_admin_user]/.ssh/authorized_keys

3.古いユーザーロック作業

新しく管理用のユーザーを作成したので、古いユーザーを無効化します。

3-1. パスワードのロック

パスワードをロックし、パスワード認証を無効化します。

$ sudo passwd -l [旧ユーザー]
passwd: パスワード期限切れ情報を変更しました

$ sudo cat /etc/shadow | grep [旧ユーザー]
[旧ユーザー]:!$6$Id...:19576:0:99999:7:::
# パスワードハッシュの前に!が付くことでパスワード認証が無効になる

3-2. ログインシェルの無効化

ログインシェルを /sbin/nologin に変更し、対話的ログインを禁止します。

$ sudo usermod -s /sbin/nologin [旧ユーザー]

# 設定確認
$ grep "[旧ユーザー]" /etc/passwd
[旧ユーザー]:x:1000:1000:[旧ユーザー],,,:/home/[旧ユーザー]:/sbin/nologin

4. SSH 設定の強化(ファイアウォール有効化前)

# 設定ファイルのバックアップ
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# SSH設定を末尾に追加(既存設定を保持しつつ上書き)
sudo sh -c 'cat >> /etc/ssh/sshd_config' << 'EOF'
Port xxxxxx # 任意のポートに変更
PermitRootLogin no # rootユーザーでログインを禁止する
MaxAuthTries 3 # 一つのセッションで認証試行を最大3回までに制限する
PasswordAuthentication no # パスワードによるログインを無効にする
PermitEmptyPasswords no # 空のパスワードを持つユーザーがSSH接続出来ないようにする
ChallengeResponseAuthentication no
# ローカルネットワークからのアクセスのみ許可
# 特定のIPアドレスからのアクセスのみ許可(オプション)
AllowUsers h-nishihara@192.168.10.0/24
EOF

# 設定の確認
grep -E 'Port|PermitRootLogin|PasswordAuthentication|ChallengeResponseAuthentication|AllowUsers|ListenAddress' /etc/ssh/sshd_config
#Port 22
#ListenAddress 0.0.0.0
#ListenAddress ::
#PermitRootLogin prohibit-password
#PasswordAuthentication yes
# PasswordAuthentication.  Depending on your PAM configuration,
# the setting of "PermitRootLogin without-password".
# PAM authentication, then enable this but set PasswordAuthentication
#GatewayPorts no
Port xxxxxx # 任意のポートに変更
PermitRootLogin no # rootユーザーでログインを禁止する
MaxAuthTries 3 # 一つのセッションで認証試行を最大3回までに制限する
PasswordAuthentication no # パスワードによるログインを無効にする
PermitEmptyPasswords no # 空のパスワードを持つユーザーがSSH接続出来ないようにする
ChallengeResponseAuthentication no
# ローカルネットワークからのアクセスのみ許可
# 特定のIPアドレスからのアクセスのみ許可(オプション)
AllowUsers h-nishihara@192.168.10.0/24

# SSHサービスの再起動
sudo systemctl restart sshd

# 新しいポートでの接続テスト(別ターミナルで実行)
# ssh -p [設定したポート] user@server

別のターミナルを開いてSSH接続が出来るか確認します。

設定が間違っていれば接続できなくなるので、開いているターミナルは閉じないように注意してください。

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

ポート番号を直接指定して、ファイアウォールルールを再設定します。

$ sudo ufw allow [SSHの任意のポート]/tcp
$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp

# ファイヤーウォールの有効化
$ sudo ufw enable

# 設定内容を確認
$ sudo ufw status
80/tcp                       ALLOW       Anywhere
443/tcp                      ALLOW       Anywhere
[SSHの任意のポート]/tcp      ALLOW       Anywhere
80/tcp (v6)                  ALLOW       Anywhere (v6)
443/tcp (v6)                 ALLOW       Anywhere (v6)
[SSHの任意のポート]/tcp (v6) ALLOW       Anywhere (v6)

6. Fail2Ban の導入

ssh接続はローカルネットワークからの接続しか許可しない設定にしましたが、念の為ブルートフォース攻撃を防ぐため、Fail2Ban をインストール・設定します。

# Fail2Banのインストール
$ sudo apt install -y fail2ban

# 設定ファイルの作成
# jail.d方式でサービス単位の設定ファイルを作成(推奨)
$ sudo mkdir -p /etc/fail2ban/jail.d

# SSH用のFail2Ban設定
$ sudo sh -c 'cat > /etc/fail2ban/jail.d/ssh.conf' << 'EOF'
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 1h
findtime = 10m
EOF

# Fail2Banサービスの再起動
$ sudo systemctl restart fail2ban

# Fail2Banのステータス確認
$ sudo systemctl status fail2ban
$ sudo fail2ban-client status sshd

Fail2Ban設定で指定したパラメーターの内容は下記のとおりです。

maxretry = 3 # 3回失敗
bantime = 1h # 1時間ブロック
findtime = 10m # 10分間で監視

7. 自動アップデートの設定

セキュリティアップデートを自動化する unattended-upgrades を設定します。

実際のアップデートは行わず、apt update相当の処理を日次と自動実行するようにします。

# パッケージリストの更新のみ自動化
APT::Periodic::Update-Package-Lists "1";
# 自動更新を完全に無効化
APT::Periodic::Unattended-Upgrade "0";
# 古いパッケージ削除間隔(日)
APT::Periodic::AutocleanInterval "7";
sudo tee -a /etc/apt/apt.conf.d/50unattended-upgrades << 'EOF'

// === 追加のセキュリティ設定 ===
// 自動再起動を無効化(Webサーバでは重要)
Unattended-Upgrade::Automatic-Reboot "false";
EOF

最後に

突貫で公開しました。追々修正します。