Ubuntu 24.04 Apache2 設定手順
1分で読めるサマリー
この手順で達成できること:Ubuntu 24.04 上に、HTTPS 対応の安全な Web サーバーを構築できる。SSL 証明書は無料で取得でき、自動更新されるため運用負荷が低い。
前提条件:
- Ubuntu 24.04 サーバー(root または sudo 権限あり)
- 独自ドメイン(DNS A レコードがサーバー IP を指している)
- ファイアウォールで TCP 80 番と 443 番ポートが開放されている
主要な手順:
- Apache2 をインストールし、基本設定を実施(手順 1〜5)
- Let's Encrypt で無料の SSL 証明書を取得(手順 6〜7)
- HTTPS を有効化し、HTTP からのリダイレクトを設定(手順 8〜10)
- 証明書の自動更新を確認(手順 11)
- 動作確認(手順 12)
- オプション:高速化設定(Gzip 圧縮、KeepAlive、ブラウザキャッシュ)(手順 13〜15)
- オプション:不正アクセス自動遮断(fail2ban)(手順 16〜18)
重要な注意事項:
- 証明書取得前に HTTP でアクセスできることを確認する必要がある(Let's Encrypt の認証に必要)
- 証明書は 90 日間有効で、自動更新される(30日前に更新が試行される)
- 本番環境では、自組織のセキュリティポリシーに従い、追加の対策を検討する
- 定期的なセキュリティアップデートとログ監視を実施する
費用:すべて無料(Let's Encrypt の SSL 証明書は無料で取得でき、更新も無料)
本手順の設定値(例):
- ドメイン名:www.example.jp(各自のドメインに読み替える)
- ドキュメントルート:/www
- ログ形式:common(IP、日時、リクエスト、ステータスを記録)
- ブラウザキャッシュ:画像・CSS・JavaScript・フォントは1時間、HTML はキャッシュしない
目次
- セキュリティに関する注意事項
- 事前に決定しておく事項
- 前提条件
- 用語説明
- 設定手順の流れ
- 1. Apache2 のインストール
- 2. Apache セキュリティ基本設定
- 3. ドキュメントルートの作成
- 4. HTTP 用仮想ホスト設定の作成
- 5. HTTP サイトの有効化
- 6. HTTP アクセスの確認
- 7. Let's Encrypt 証明書の取得
- 8. HTTPS 用仮想ホスト設定の作成
- 9. HTTP 設定をリダイレクトに変更
- 10. 必要なモジュールの有効化と設定の反映
- 11. 証明書自動更新の確認
- 12. 動作確認
- 高速化設定(オプション)
- 13. Gzip 圧縮の有効化
- 14. KeepAlive の最適化
- 15. ブラウザキャッシュの設定
- 不正アクセス自動遮断の設定(オプション)
- 16. fail2ban のインストールと基本設定
- 17. Apache 用フィルターの有効化
- 18. 遮断状況の確認とメンテナンス
- 19. 総合的な動作確認
- 20. トラブルシューティング
- ログファイルの場所
- 運用上の注意事項
セキュリティに関する注意事項
本手順には基本的なセキュリティ設定を含むが、以下の点に留意する必要がある。
- 本番環境で運用する場合、自組織のセキュリティポリシーに従い、追加の対策を検討する
- OS、Apache、certbot のセキュリティアップデートを定期的に適用する
- アクセスログおよびエラーログを定期的に監視し、不審なアクセスの有無を確認する
- Web アプリケーションを配置する場合、アプリケーション側のセキュリティ対策も別途実施する
事前に決定しておく事項
本手順を実施する前に、以下の項目を決定しておく。
| 項目 | 本手順での設定値 | 説明 |
|---|---|---|
| ドメイン名 | www.example.jp | Web サイトの URL に使用するドメイン |
| ドキュメントルート | /www | Web コンテンツを配置するディレクトリ |
| アクセスログのパス | /var/log/apache2/www.example.jp-access.log | アクセス記録の保存先 |
| エラーログのパス | /var/log/apache2/www.example.jp-error.log | エラー記録の保存先 |
| ログ形式 | common | IP、日時、リクエスト、ステータスを記録 |
注意:上記の値は自身の環境に合わせて読み替える。本手順中の www.example.jp は、すべて自身のドメイン名に置き換える。
前提条件
本手順を実施する前に、以下の条件を満たしていることを確認する。
- ドメインの DNS A レコードがサーバーの IP アドレスを指している(DNS 設定後、反映まで数分から数時間かかる場合がある)
- ファイアウォールで TCP 80 番ポート(HTTP)と 443 番ポート(HTTPS)が開放されている
- ファイアウォールで上記以外の不要なポートが閉じられている
- root 権限または sudo 権限を持つユーザーで作業する
補足:ファイアウォール設定は本手順の範囲外である。使用しているファイアウォールソフトウェア(ufw、iptables 等)のマニュアルを参照し、事前に設定を完了させる。
用語説明
| 用語 | 説明 |
|---|---|
| ドキュメントルート | Web サーバーが公開するファイルを配置するディレクトリ |
| 仮想ホスト | 1台のサーバーで複数のドメインを運用するための設定単位 |
| SSL/TLS | 通信を暗号化するプロトコル。HTTPS はこれを使用する |
| Let's Encrypt | 無料で SSL 証明書を発行する認証局。証明書の有効期間は 90 日間 |
| webroot 方式 | 既存の Web サーバーを利用して Let's Encrypt の認証を実施する方式。サーバーを停止せずに証明書を取得できる |
| common 形式 | Apache のログ形式の一つ。IP アドレス、日時、リクエスト内容、ステータスコード、転送バイト数を記録する |
| HSTS | HTTP Strict Transport Security の略。ブラウザに HTTPS 接続を強制する仕組み |
| 暗号スイート | SSL/TLS 通信で使用する暗号化アルゴリズムの組み合わせ。安全性と互換性のバランスを考慮して選択する |
設定手順の流れ
本手順は以下の順序で進める。
| 段階 | 作業内容 | HTTP(80番) | HTTPS(443番) |
|---|---|---|---|
| 手順 1〜5 | Apache 導入と HTTP 設定 | 通常公開 | 未設定 |
| 手順 6 | HTTP 動作確認 | 通常公開 | 未設定 |
| 手順 7 | 証明書取得 | 認証に使用 | 未設定 |
| 手順 8〜10 | HTTPS 設定とリダイレクト | リダイレクト | 公開 |
| 手順 11〜12 | 自動更新確認と動作確認 | リダイレクト | 公開 |
| 手順 13〜15 | 高速化設定(オプション) | リダイレクト | 公開 |
| 手順 16〜18 | 不正アクセス対策(オプション) | リダイレクト | 公開 |
| 手順 19 | 総合的な動作確認 | リダイレクト | 公開 |
この順序で作業する理由:Let's Encrypt は HTTP(80番ポート)経由で認証を実施する。証明書取得前は HTTP で通常公開し、証明書取得後に HTTPS を有効化してリダイレクトを設定する必要がある。
1. Apache2 のインストール
目的:Web サーバーソフトウェアをシステムに導入する。
sudo apt update
sudo apt install -y apache2
確認:
sudo systemctl status apache2
「active (running)」と表示されれば成功。インストール後、Apache は自動的に起動し、OS 起動時にも自動起動する。
2. Apache セキュリティ基本設定
目的:バージョン情報を非表示にし、攻撃者による脆弱性特定を困難にする。
設定ファイルを開く。
sudo nano /etc/apache2/conf-available/security.conf
以下の項目を変更する。
# 変更前:ServerTokens OS
# 変更後:
ServerTokens Prod
# 変更前:ServerSignature On
# 変更後:
ServerSignature Off
設定を有効化する。
sudo a2enconf security
sudo systemctl reload apache2
設定項目の説明:
ServerTokens Prod:レスポンスヘッダーに製品名のみを表示(バージョン番号を非表示)ServerSignature Off:エラーページからバージョン情報を削除
3. ドキュメントルートの作成
目的:Web コンテンツを配置する専用ディレクトリを作成し、適切な権限を設定する。
sudo mkdir -p /www
sudo chown -R www-data:www-data /www
sudo chmod -R 755 /www
権限設定の理由:Apache は www-data という権限の低いユーザーとして動作する。パーミッション 755 は、所有者が読み書き実行可能、その他は読み取りと実行のみ可能な設定である。
確認:
ls -ld /www
「drwxr-xr-x」と表示され、所有者が「www-data」であれば成功。
4. HTTP 用仮想ホスト設定の作成
目的:HTTP(80番ポート)でアクセス可能な Web サイトの基本設定を作成する。この設定は証明書取得に必要である。
重要:この段階ではリダイレクト設定を含めない。Let's Encrypt の証明書取得には HTTP(80番ポート)でのアクセスが必要である。リダイレクト設定は手順 9 で実施する。
sudo nano /etc/apache2/sites-available/www.example.jp.conf
以下を記述する。
<VirtualHost *:80>
ServerName www.example.jp
DocumentRoot /www
<Directory /www>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# .well-knownディレクトリへのアクセスを原則禁止
<Directory "/www/.well-known">
Require all denied
</Directory>
# ACME認証用ディレクトリのみ許可
<Directory "/www/.well-known/acme-challenge">
Require all granted
</Directory>
</VirtualHost>
設定項目の説明:
ServerName:このサイトのドメイン名DocumentRoot:Web コンテンツを配置するディレクトリOptions -Indexes:ディレクトリ一覧表示を無効化(セキュリティ対策)Options +FollowSymLinks:シンボリックリンクの追跡を許可AllowOverride None:.htaccess による設定変更を禁止(パフォーマンス向上)Require all granted:すべてのアクセスを許可
5. HTTP サイトの有効化
目的:作成した設定を有効化し、デフォルト設定を無効化する。
sudo a2dissite 000-default.conf
sudo a2ensite www.example.jp.conf
sudo systemctl reload apache2
デフォルトサイトを無効化する理由:デフォルト設定は、ドメイン名を指定しないアクセスに応答するため、意図しない情報漏洩のリスクがある。
確認:
apache2ctl -S
「www.example.jp.conf」が表示され、「000-default.conf」が表示されなければ成功。
6. HTTP アクセスの確認
目的:証明書取得の前に、HTTP でアクセスできることを確認する。これにより、DNS 設定とファイアウォール設定の正常性を検証できる。
# テスト用ファイルの作成
echo "test" | sudo tee /www/index.html
# アクセス確認
curl -I http://www.example.jp
成功の判定:HTTP/1.1 200 OK が表示されれば成功。
失敗した場合の確認事項:
- DNS 設定が正しいか(
dig www.example.jpでサーバーの IP アドレスが表示されるか) - ファイアウォールで 80 番ポートが開放されているか(
sudo ufw statusまたはsudo iptables -Lで確認) - Apache が起動しているか(
sudo systemctl status apache2で確認)
7. Let's Encrypt 証明書の取得
目的:webroot 方式により、HTTPS 通信に必要な SSL 証明書を取得する。
DNSによる認証の場合は、 sudo certbot certonly --manual --preferred-challenges dns -d www.example.jp を実行
sudo apt install -y certbot
sudo mkdir -p /www/.well-known/acme-challenge
sudo chown www-data:www-data /www/.well-known/acme-challenge
sudo certbot certonly --webroot -w /www -d www.example.jp
webroot 方式の仕組み:certbot は /www/.well-known/acme-challenge/ に認証用ファイルを配置する。Let's Encrypt のサーバーは HTTP 経由でこのファイルにアクセスし、ドメインの所有権を確認する。Web サーバーを停止する必要はない。
成功の判定:以下のディレクトリに証明書ファイルが作成される。
/etc/letsencrypt/live/www.example.jp/
確認:
sudo ls -l /etc/letsencrypt/live/www.example.jp/
「fullchain.pem」と「privkey.pem」が存在すれば成功。
失敗した場合の確認事項:
- 手順 6 で HTTP アクセスが成功しているか
- ドメイン名が正しいか
- ファイアウォールで 80 番ポートが開放されているか
8. HTTPS 用仮想ホスト設定の作成
目的:HTTPS(443番ポート)での安全な通信を有効化し、セキュリティヘッダーとログ記録を設定する。
重要:セキュリティヘッダーの設定には headers モジュールが必要である。このモジュールは手順 10 で有効化する。
sudo nano /etc/apache2/sites-available/www.example.jp-ssl.conf
以下を記述する。
<VirtualHost *:443>
ServerName www.example.jp
DocumentRoot /www
# SSL 設定
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.example.jp/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.jp/privkey.pem
# SSL プロトコル設定(古い脆弱なプロトコルを無効化)
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# 暗号スイート設定
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
# セキュリティヘッダー
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# ドキュメントルート設定
<Directory /www>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# .well-knownディレクトリへのアクセスを原則禁止
<Directory "/www/.well-known">
Require all denied
</Directory>
# ACME認証用ディレクトリのみ許可
<Directory "/www/.well-known/acme-challenge">
Require all granted
</Directory>
# ログ設定
ErrorLog ${APACHE_LOG_DIR}/www.example.jp-error.log
CustomLog ${APACHE_LOG_DIR}/www.example.jp-access.log common
</VirtualHost>
セキュリティ設定の説明
| 設定項目 | 目的 | 詳細 |
|---|---|---|
| SSLProtocol | 安全なプロトコルのみ使用 | SSLv3、TLSv1、TLSv1.1 を無効化し、TLSv1.2 以上のみ許可 |
| SSLCipherSuite | 安全な暗号化方式のみ使用 | ECDHE と GCM を使用した暗号スイートを選択 |
| SSLHonorCipherOrder | 暗号スイート選択の制御 | off に設定し、クライアントの優先順位を尊重 |
| Strict-Transport-Security | HTTPS 接続を強制 | ブラウザに HTTPS 接続を強制(HSTS)。max-age=31536000 は1年間有効 |
| X-Frame-Options | クリックジャッキング攻撃を防止 | 他のサイトから iframe で埋め込まれることを防止 |
| X-Content-Type-Options | MIME タイプスニッフィングを防止 | ブラウザが独自にファイル種別を判定することを防止 |
| Referrer-Policy | リファラー情報の送信を制御 | 同一サイト内ではフルパスを送信、外部サイトへはオリジンのみ送信 |
ログ形式 common の出力例:
192.168.1.100 - - [20/Jan/2026:12:34:56 +0900] "GET /index.html HTTP/1.1" 200 1234
この形式は、IP アドレス、日時、リクエスト内容、ステータスコード、転送バイト数を記録する。
9. HTTP 設定をリダイレクトに変更
目的:HTTP アクセスを HTTPS へ自動転送し、すべての通信を暗号化する。
HTTPS の準備が整ったため、手順 4 で作成した HTTP 設定ファイルを書き換え、HTTPS へリダイレクトするよう変更する。
sudo nano /etc/apache2/sites-available/www.example.jp.conf
内容を以下に変更する。
<VirtualHost *:80>
ServerName www.example.jp
Redirect permanent / https://www.example.jp/
</VirtualHost>
Redirect permanent の意味:HTTP ステータスコード 301(恒久的な移動)を返す。ブラウザと検索エンジンは、このサイトが HTTPS に完全移行したことを認識する。
10. 必要なモジュールの有効化と設定の反映
目的:SSL 通信とセキュリティヘッダーに必要なモジュールを有効化し、HTTPS 設定を反映する。
sudo a2enmod ssl
sudo a2enmod headers
sudo a2ensite www.example.jp-ssl.conf
sudo systemctl reload apache2
各モジュールの役割:
ssl:HTTPS 通信を実現headers:セキュリティヘッダーを設定
確認:
apache2ctl -M | grep -E 'ssl|headers'
「ssl_module」と「headers_module」が表示されれば成功。
11. 証明書自動更新の確認
目的:証明書の自動更新が正常に動作することを検証する。
sudo certbot renew --dry-run
--dry-run オプションの意味:テスト実行であり、実際の更新は実施されない。エラーが出なければ自動更新が正しく機能する。
確認:
sudo systemctl list-timers | grep certbot
「certbot.timer」が表示され、次回実行時刻が表示されれば成功。
証明書自動更新の仕組み
certbot のインストール時に systemd タイマーが設定され、定期的に更新確認が実行される。証明書の有効期限が 30 日以内になると、自動的に更新が試行される。
自動更新が失敗する主な原因:
- ファイアウォール設定の変更により、80番ポートが閉じられた
- Apache の設定ミスにより、認証用ファイルにアクセスできない
- Let's Encrypt のサーバーが一時的に利用できない
定期的な手動確認を推奨する(運用上の注意事項を参照)。
12. 動作確認
目的:すべての設定が正しく機能していることを確認する。
12.1 基本動作の確認
# HTTP から HTTPS へのリダイレクトを確認
curl -I http://www.example.jp
# HTTPS でのアクセスを確認
curl -I https://www.example.jp
成功の判定:
- HTTP:
HTTP/1.1 301 Moved PermanentlyとLocation: https://www.example.jp/が表示される - HTTPS:
HTTP/1.1 200 OKが表示される
12.2 セキュリティヘッダーの確認
curl -I https://www.example.jp
以下のヘッダーが含まれていることを確認する。
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
ヘッダーが表示されない場合:headers モジュールが有効化されているか確認する(手順 10 を再実行)。
12.3 サーバー情報の非表示確認
curl -I https://www.example.jp
レスポンスヘッダーの Server: が Apache のみとなり、バージョン番号が表示されていないことを確認する。
バージョン番号が表示される場合:手順 2 の設定が正しく反映されているか確認する。
高速化設定(オプション)
本セクションでは、Web サーバーのレスポンス速度を向上させる設定を実施する。
13. Deflate 圧縮の有効化
目的:テキストベースのファイル(HTML、CSS、JavaScript 等)を圧縮して転送し、転送量を削減する。
期待される効果:転送量を 60〜80% 削減できる。
sudo a2enmod deflate
sudo systemctl restart apache2
圧縮対象の設定:
sudo cat /etc/apache2/mods-available/deflate.conf
以下の内容であることを確認する(デフォルトで設定済み)。
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/wasm
AddOutputFilterByType DEFLATE application/xml
</IfModule>
確認:
curl -H "Accept-Encoding: gzip" -I https://www.example.jp
「Content-Encoding: gzip」が表示されれば成功。
注意:画像ファイル(JPEG、PNG、GIF)や動画ファイルは既に圧縮されているため、対象に含めない。
14. KeepAlive の最適化
目的:HTTP コネクションを再利用し、接続確立のオーバーヘッドを削減する。
期待される効果:複数のファイルを読み込むページで、読み込み時間を 30〜50% 削減できる。
sudo nano /etc/apache2/apache2.conf
以下の項目を確認する。
# KeepAlive を有効化
KeepAlive On
# 1つのコネクションで処理できるリクエスト数
MaxKeepAliveRequests 100
# KeepAlive タイムアウト(秒)
KeepAliveTimeout 5
設定項目の説明:
KeepAlive On:コネクションの再利用を有効化MaxKeepAliveRequests 100:1つのコネクションで最大100リクエストまで処理KeepAliveTimeout 5:次のリクエストを待つ時間。5秒が推奨値
設定変更を行った場合は、次のコマンドにより反映する。
sudo systemctl restart apache2
確認:
curl -v -I https://www.kkaneko.jp 2>&1 | grep -i "connection"
- Connection #0 to host ... left intact: 接続が維持されている(閉じられていない)。Keep Alive が有効であると確認できる。
15. ブラウザキャッシュの設定
目的:静的ファイルをブラウザにキャッシュさせ、再訪問時の読み込み速度を向上させる。
期待される効果:再訪問時のページ読み込み時間を 30〜60% 削減できる。
本設定のキャッシュポリシー:
- 画像、CSS、JavaScript、フォント:1時間キャッシュ(更新後、最長1時間で全訪問者に反映)
- HTML:キャッシュしない(常に最新の内容を表示)
1時間キャッシュを採用する理由:
- CSS、JavaScript、フォントの更新頻度は低く、1時間キャッシュによる高速化のメリットが大きい
- 緊急時はスーパーリロード(Ctrl+F5)で即座に最新版を表示可能
- ファイル名にバージョン番号を付加(例:style-v2.css)すれば、キャッシュを回避可能
- 設定が単純で理解しやすい(すべての静的ファイルで統一)
sudo a2enmod expires sudo a2enmod headers sudo systemctl restart apache2キャッシュ設定の追加:
sudo nano /etc/apache2/sites-available/www.example.jp-ssl.conf</VirtualHost>の直前に以下を追加する。# ブラウザキャッシュ設定(静的ファイルは1時間キャッシュ) <IfModule mod_expires.c> ExpiresActive On # 画像: 1時間キャッシュ ExpiresByType image/jpeg "access plus 1 hour" ExpiresByType image/png "access plus 1 hour" ExpiresByType image/gif "access plus 1 hour" ExpiresByType image/webp "access plus 1 hour" ExpiresByType image/svg+xml "access plus 1 hour" ExpiresByType image/x-icon "access plus 1 hour" # CSS: 1時間キャッシュ ExpiresByType text/css "access plus 1 hour" # JavaScript: 1時間キャッシュ ExpiresByType application/javascript "access plus 1 hour" ExpiresByType application/x-javascript "access plus 1 hour" ExpiresByType text/javascript "access plus 1 hour" # フォント: 1時間キャッシュ ExpiresByType font/woff2 "access plus 1 hour" ExpiresByType font/woff "access plus 1 hour" ExpiresByType font/ttf "access plus 1 hour" # HTML: キャッシュしない ExpiresByType text/html "access plus 0 seconds" </IfModule> # Cache-Control ヘッダーの設定 <IfModule mod_headers.c> # 画像、CSS、JavaScript、フォント(1時間キャッシュ) <FilesMatch "\.(jpg|jpeg|png|gif|webp|svg|ico|css|js|woff2|woff|ttf|eot)$"> Header set Cache-Control "max-age=3600, public" </FilesMatch> # HTML(キャッシュしない) <FilesMatch "\.(html|htm)$"> Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate" Header set Pragma "no-cache" Header set Expires "0" </FilesMatch> </IfModule>設定を反映する。
sudo systemctl restart apache2キャッシュ設定の説明:
- 画像、CSS、JavaScript、フォント:1時間キャッシュ(3600秒)。更新後、最長1時間で新しいファイルが表示される
- HTML:キャッシュしない。常に最新の内容を表示する
確認:
# 画像、CSS、JavaScript が1時間キャッシュされることを確認 curl -I https://www.example.jp/sample.jpg curl -I https://www.example.jp/style.css curl -I https://www.example.jp/script.js # HTML がキャッシュされないことを確認 curl -I https://www.example.jp期待される出力:
- 画像、CSS、JavaScript:
Cache-Control: max-age=3600, public - HTML:
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
ファイル更新後の反映時間:
- 通常の再読み込み(F5):最長1時間後に新しいファイルが表示される
- スーパーリロード(Ctrl+F5):即座に新しいファイルが表示される
即時更新が必要な場合の対処法:ファイル名にバージョン番号を付加する(例:logo.png → logo-v2.png)ことで、キャッシュを回避できる。
不正アクセス自動遮断の設定(オプション)
本セクションでは、fail2ban を使用して不正アクセスを自動的に検知し、一時的にアクセスを遮断する設定を実施する。
16. fail2ban のインストールと基本設定
目的:ログファイルを監視し、不正なアクセスパターンを検知して自動的にファイアウォールで遮断する。
期待される効果:パスワード総当たり攻撃、スキャン攻撃、DoS 攻撃の初期段階を自動的に防御できる。
sudo apt install -y fail2ban基本設定ファイルの作成:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local sudo nano /etc/fail2ban/jail.local以下の項目を確認し、必要に応じて設定を変更する。
[DEFAULT] # 遮断時間(秒)デフォルトは 10 分 bantime = 600 # 監視期間(秒)デフォルトは 10 分 findtime = 600 # 遮断対象から除外する IP アドレス(自分の IP を追加) ignoreip = 127.0.0.1/8 ::1設定項目の説明:
bantime:遮断時間。600秒(10分)が推奨値findtime:監視期間。この期間内の失敗回数をカウントmaxretry:許容する失敗回数。5回が推奨値ignoreip:管理者の IP アドレスを追加し、誤って遮断されないようにする
17. Apache 用フィルターの有効化
目的:Apache のアクセスログとエラーログを監視し、不正なアクセスを検知する。
同じファイル(
/etc/fail2ban/jail.local)内で、以下のセクションを有効化する。# Apache 認証失敗を検知 [apache-auth] enabled = true port = http,https logpath = /var/log/apache2/*error.log # 存在しないスクリプトへのアクセスを検知(スキャン攻撃対策) [apache-noscript] enabled = true port = http,https logpath = /var/log/apache2/*error.log # .htaccess や .htpasswd へのアクセスを検知 [apache-overflows] enabled = true port = http,https logpath = /var/log/apache2/*error.log各フィルターの説明:
apache-auth:Basic 認証の失敗を検知apache-noscript:存在しない PHP、CGI スクリプトへのアクセスを検知apache-overflows:Apache の設定ファイルへのアクセス試行を検知
fail2ban を再起動して設定を反映する。
sudo systemctl restart fail2ban sudo systemctl enable fail2ban確認:
# fail2ban のステータスを確認 sudo fail2ban-client status # 特定の jail のステータスを確認 sudo fail2ban-client status apache-auth有効化した jail が表示され、「Currently banned」の数値が確認できれば成功。
18. 遮断状況の確認とメンテナンス
目的:fail2ban の動作状況を確認し、必要に応じて設定を調整する。
遮断状況の確認:
# 現在遮断されている IP アドレスを確認 sudo fail2ban-client status apache-auth # すべての jail の統計情報を確認 sudo fail2ban-client status手動での IP アドレス遮断解除:
# 特定の IP アドレスを遮断解除 sudo fail2ban-client set apache-auth unbanip 192.168.1.100ログの確認:
# fail2ban のログを確認 sudo tail -f /var/log/fail2ban.log推奨される運用:
- 週1回程度、遮断状況を確認し、異常なアクセスパターンを把握する
- 誤検知が多い場合、
maxretryやfindtimeを調整する
注意:fail2ban は iptables または nftables を使用してアクセスを遮断する。ファイアウォール設定を手動で変更する場合、fail2ban の動作に影響を与えないよう注意する。
19. 総合的な動作確認
目的:手順13〜18で実施した高速化設定と不正アクセス対策が正常に動作していることを総合的に確認する。
19-1. 高速化設定の動作確認
Gzip 圧縮の確認
curl -H "Accept-Encoding: gzip" -I https://www.example.jp curl -H "Accept-Encoding: gzip" -I https://www.example.jp/style.css期待される出力:すべてのレスポンスに「Content-Encoding: gzip」が含まれている。
KeepAlive の確認
curl -I https://www.example.jp期待される出力:「Connection: Keep-Alive」が含まれている。
ブラウザキャッシュの確認
curl -I https://www.example.jp/sample.jpg curl -I https://www.example.jp/style.css curl -I https://www.example.jp期待される出力:
- 画像、CSS:
Cache-Control: max-age=3600, public - HTML:
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
19-2. ブラウザでの実際の動作確認
開発者ツールでの確認手順(Chrome / Edge)
- ブラウザで https://www.example.jp にアクセスする
- F12 キーを押して開発者ツールを開く
- 「Network」タブを選択する
- ページを再読み込み(F5)する
確認ポイント1:Gzip 圧縮
- 任意のファイルをクリックし、「Headers」タブで「content-encoding: gzip」が表示されていることを確認
- 「Size」列で、転送サイズが元のサイズより小さいことを確認
確認ポイント2:KeepAlive
- 複数のファイルの「Connection ID」が同じ値であることを確認(同じコネクションを再利用している)
確認ポイント3:ブラウザキャッシュ
- 画像、CSS、JavaScript ファイルで「cache-control: max-age=3600, public」が表示されていることを確認
- HTML ファイルで「cache-control: max-age=0, no-cache, no-store, must-revalidate」が表示されていることを確認
ファイル更新の反映確認
確認手順:
- サーバー上で CSS、JavaScript、または画像ファイルを編集する
- ブラウザで通常の再読み込み(F5)を実行する
期待される動作:
- 1時間以内:古いファイルが表示される(キャッシュが有効)
- 1時間経過後:新しいファイルが表示される(キャッシュが切れる)
- スーパーリロード(Ctrl+F5):即座に新しいファイルが表示される
19-3. 不正アクセス対策の動作確認
fail2ban の基本動作確認
# fail2ban のステータスを確認 sudo systemctl status fail2ban # 有効な jail を確認 sudo fail2ban-client status期待される出力:「active (running)」と表示され、以下の jail が表示される。
- Jail list: apache-auth, apache-noscript, apache-overflows, apache-badbots19-4. Apache の総合ステータス確認
設定ファイルの文法チェック
sudo apache2ctl configtest期待される出力:「Syntax OK」と表示される。
有効なモジュールの確認
apache2ctl -M | grep -E 'ssl|headers|deflate|expires'期待される出力:
deflate_module (shared) expires_module (shared) headers_module (shared) ssl_module (shared)有効な仮想ホストの確認
apache2ctl -S期待される出力:
VirtualHost configuration: *:443 www.example.jp (/etc/apache2/sites-enabled/www.example.jp-ssl.conf:1) *:80 www.example.jp (/etc/apache2/sites-enabled/www.example.jp.conf:1)19-5. セキュリティ設定の総合確認
HTTPS リダイレクトの確認
curl -I http://www.example.jp期待される出力:
HTTP/1.1 301 Moved Permanently Location: https://www.example.jp/セキュリティヘッダーの確認
curl -I https://www.example.jp期待される出力:以下のヘッダーがすべて含まれている。
Strict-Transport-Security: max-age=31536000; includeSubDomains X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin Server: ApacheSSL 証明書の確認
sudo certbot certificates期待される出力:
Certificate Name: www.example.jp Domains: www.example.jp Expiry Date: 2026-04-20 12:34:56+00:00 (VALID: 89 days)有効期限が 30 日以上残っていることを確認する。
19-6. 外部ツールによる総合診断
SSL/TLS 設定の診断
使用ツール:SSL Labs(https://www.ssllabs.com/ssltest/)
期待される評価:A 評価以上。
ページ速度の診断
使用ツール:Google PageSpeed Insights(https://pagespeed.web.dev/)
期待されるスコア:パフォーマンス 70点以上、SEO 90点以上。
セキュリティヘッダーの診断
使用ツール:Security Headers(https://securityheaders.com/)
期待される評価:B 評価以上。
19-7. 総合確認チェックリスト
カテゴリ 確認項目 確認方法 期待される結果 高速化設定 Gzip 圧縮 curl -H "Accept-Encoding: gzip" -I https://www.example.jp Content-Encoding: gzip が表示 KeepAlive curl -I https://www.example.jp Connection: Keep-Alive が表示 ブラウザキャッシュ curl -I https://www.example.jp/sample.jpg Cache-Control: max-age=3600 が表示 不正アクセス対策 fail2ban 動作 sudo systemctl status fail2ban active (running) と表示 jail 有効化 sudo fail2ban-client status 4つ以上の jail が表示 セキュリティ設定 HTTPS リダイレクト curl -I http://www.example.jp 301 Moved Permanently が返される HSTS ヘッダー curl -I https://www.example.jp Strict-Transport-Security が表示 バージョン隠蔽 curl -I https://www.example.jp Server: Apache のみが表示 SSL 証明書 sudo certbot certificates 有効期限が 30 日以上 Apache 設定 設定ファイル sudo apache2ctl configtest Syntax OK が表示 モジュール apache2ctl -M | grep -E 'ssl|headers|deflate|expires' 4つのモジュールが表示 仮想ホスト apache2ctl -S ポート 80 と 443 が表示 外部診断 SSL/TLS SSL Labs で診断 A 評価以上 ページ速度 PageSpeed Insights で診断 パフォーマンス 70 点以上 セキュリティヘッダー Security Headers で診断 B 評価以上 すべての項目が期待される結果となっていれば、設定は正常に完了している。
20. トラブルシューティング
本セクションでは、よくある失敗パターンとその対処法をまとめる。問題が発生した場合、該当する項目を参照し、段階的に対処する。
20-1. 証明書取得失敗
症状:
sudo certbot certonly --webroot -w /www -d www.example.jpを実行すると、以下のエラーが表示される。Failed authorization procedure. www.example.jp (http-01): urn:ietf:params:acme:error:unauthorized主な原因と対処法:
原因 確認方法 対処法 DNS 設定が正しくない dig www.example.jpでサーバー IP が表示されるか確認DNS 設定を修正し、反映を待つ(数分〜数時間) 80番ポートが閉じられている sudo ufw statusで80番ポートの状態を確認sudo ufw allow 80/tcpで開放HTTP でアクセスできない curl -I http://www.example.jpで確認手順 6 を再実行し、HTTP アクセスが成功することを確認 ドキュメントルートのパスが間違っている ls -ld /wwwでディレクトリの存在を確認certbot コマンドの -wオプションで指定したパスを確認診断コマンド:
dig www.example.jp curl -I http://www.example.jp sudo systemctl status apache2 sudo tail -n 50 /var/log/letsencrypt/letsencrypt.log20-2. HTTPS 接続エラー
症状:ブラウザで
https://www.example.jpにアクセスすると、「接続がタイムアウトしました」「証明書が無効です」などのエラーが表示される。主な原因と対処法:
原因 確認方法 対処法 443番ポートが閉じられている sudo ufw statusで443番ポートの状態を確認sudo ufw allow 443/tcpで開放SSL モジュールが有効化されていない apache2ctl -M | grep sslで確認sudo a2enmod sslで有効化し、sudo systemctl reload apache2HTTPS 用仮想ホストが有効化されていない apache2ctl -Sで443番ポートの仮想ホストを確認sudo a2ensite www.example.jp-ssl.confで有効化し、sudo systemctl reload apache2設定ファイルに文法エラーがある sudo apache2ctl configtestで確認エラーメッセージに表示されたファイルと行番号を確認し、修正 証明書ファイルのパスが間違っている sudo ls -l /etc/letsencrypt/live/www.example.jp/で確認手順 8 の SSL 設定でパスが正しいか確認 診断コマンド:
curl -I https://www.example.jp apache2ctl -M | grep ssl apache2ctl -S sudo apache2ctl configtest sudo ls -l /etc/letsencrypt/live/www.example.jp/20-3. HTTP から HTTPS へのリダイレクトが動作しない
症状:
http://www.example.jpにアクセスしても、https://www.example.jpにリダイレクトされない。主な原因と対処法:
原因 確認方法 対処法 HTTP 用設定にリダイレクトが記述されていない sudo cat /etc/apache2/sites-available/www.example.jp.confで確認手順 9 を再実行し、 Redirect permanentが記述されているか確認ブラウザのキャッシュが残っている 別のブラウザまたはシークレットモードでアクセス ブラウザのキャッシュをクリアするか、スーパーリロード(Ctrl+F5)を実行 診断コマンド:
curl -I http://www.example.jp # 期待される出力:HTTP/1.1 301 Moved Permanently # 期待される出力:Location: https://www.example.jp/20-4. セキュリティヘッダーが表示されない
症状:
curl -I https://www.example.jpを実行しても、Strict-Transport-Securityなどのセキュリティヘッダーが表示されない。主な原因と対処法:
原因 確認方法 対処法 headers モジュールが有効化されていない apache2ctl -M | grep headersで確認sudo a2enmod headersで有効化し、sudo systemctl reload apache2HTTPS 用設定にヘッダー設定が記述されていない sudo cat /etc/apache2/sites-available/www.example.jp-ssl.conf | grep "Header always set"で確認手順 8 を再実行し、 Header always setの行が記述されているか確認20-5. Gzip 圧縮が動作しない
症状:
curl -H "Accept-Encoding: gzip" -I https://www.example.jpを実行しても、Content-Encoding: gzipが表示されない。主な原因と対処法:
原因 確認方法 対処法 deflate モジュールが有効化されていない apache2ctl -M | grep deflateで確認sudo a2enmod deflateで有効化し、sudo systemctl restart apache2アクセスしているファイルが圧縮対象外 HTML、CSS、JavaScript ファイルでテスト 画像ファイルは既に圧縮されているため、圧縮対象外。HTML または CSS ファイルでテスト 20-6. ブラウザキャッシュが動作しない
症状:
curl -I https://www.example.jp/sample.jpgを実行しても、Cache-Control: max-age=3600が表示されない。主な原因と対処法:
原因 確認方法 対処法 expires/headers モジュールが有効化されていない apache2ctl -M | grep -E 'expires|headers'で確認sudo a2enmod expiresとsudo a2enmod headersで有効化し、sudo systemctl restart apache2HTTPS 用設定にキャッシュ設定が記述されていない sudo cat /etc/apache2/sites-available/www.example.jp-ssl.conf | grep "ExpiresActive"で確認手順 15 を再実行し、 ExpiresActive OnとExpiresByTypeが記述されているか確認20-7. fail2ban が不正アクセスを検知しない
症状:明らかに不正なアクセスがログに記録されているが、
sudo fail2ban-client statusで「Currently banned」が 0 のまま。主な原因と対処法:
原因 確認方法 対処法 fail2ban が起動していない sudo systemctl status fail2banで確認sudo systemctl start fail2banで起動し、sudo systemctl enable fail2banで自動起動を有効化jail が有効化されていない sudo fail2ban-client statusで jail リストを確認/etc/fail2ban/jail.localで該当する jail のenabled = trueを確認ログファイルのパスが間違っている sudo fail2ban-client get apache-auth logpathで確認/etc/fail2ban/jail.localでlogpathが正しいか確認20-8. Apache のパフォーマンスが低い
症状:ページの読み込みが遅い。同時アクセス数が増えるとサーバーが応答しなくなる。
主な原因と対処法:
原因 確認方法 対処法 Gzip 圧縮が有効化されていない curl -H "Accept-Encoding: gzip" -I https://www.example.jpで確認手順 13 を実施 KeepAlive が無効化されている sudo cat /etc/apache2/apache2.conf | grep KeepAliveで確認手順 14 を実施 ブラウザキャッシュが設定されていない curl -I https://www.example.jp/sample.jpgで確認手順 15 を実施 メモリ不足 free -hでメモリ使用状況を確認不要なサービスを停止するか、サーバーのメモリを増設 20-9. Apache が起動しない
症状:
sudo systemctl start apache2を実行しても、Apache が起動しない。sudo systemctl status apache2で「failed」と表示される。主な原因と対処法:
原因 確認方法 対処法 設定ファイルに文法エラーがある sudo apache2ctl configtestで確認エラーメッセージに表示されたファイルと行番号を確認し、修正 80番または443番ポートが既に使用されている sudo lsof -i :80とsudo lsof -i :443で確認他のプロセスが使用している場合、そのプロセスを停止 証明書ファイルが見つからない sudo ls -l /etc/letsencrypt/live/www.example.jp/で確認証明書が存在しない場合、手順 7 を再実行 診断コマンド:
sudo systemctl status apache2 sudo apache2ctl configtest sudo lsof -i :80 sudo lsof -i :443 sudo tail -n 50 /var/log/apache2/error.log20-10. ログファイルが見つからない、またはログが記録されない
症状:
sudo tail -f /var/log/apache2/www.example.jp-access.logを実行しても、「No such file or directory」と表示される。または、アクセスしてもログが記録されない。主な原因と対処法:
原因 確認方法 対処法 ログファイルのパスが間違っている sudo cat /etc/apache2/sites-available/www.example.jp-ssl.conf | grep Logで確認手順 8 で指定したログパスを確認。 ${APACHE_LOG_DIR}は/var/log/apache2に展開される仮想ホスト設定が有効化されていない apache2ctl -Sで仮想ホストの一覧を確認sudo a2ensite www.example.jp-ssl.confで有効化し、sudo systemctl reload apache2トラブルシューティングの一般的な手順
上記の個別の問題に該当しない場合、以下の手順で問題を特定する。
- エラーログを確認:
sudo tail -n 100 /var/log/apache2/error.log - 設定ファイルの文法をチェック:
sudo apache2ctl configtest - Apache の状態を確認:
sudo systemctl status apache2 - 仮想ホストの設定を確認:
apache2ctl -S - モジュールの有効化を確認:
apache2ctl -M - ファイアウォールの設定を確認:
sudo ufw status - DNS 設定を確認:
dig www.example.jp - 再起動を試行:
sudo systemctl restart apache2
それでも解決しない場合:
- Apache の公式ドキュメント(https://httpd.apache.org/docs/2.4/)を参照
- Ubuntu のフォーラム(https://ubuntuforums.org/)やコミュニティで質問
- エラーメッセージで検索し、同様の問題の解決例を探す
ログファイルの場所
ログ種別 パス 用途 アクセスログ /var/log/apache2/www.example.jp-access.log アクセス解析、トラフィック監視、不正アクセスの検知 エラーログ /var/log/apache2/www.example.jp-error.log トラブルシューティング、設定ミスの発見、アプリケーションエラーの検知 ログの確認方法:
# 最新のアクセスログを表示 sudo tail -n 20 /var/log/apache2/www.example.jp-access.log # エラーログをリアルタイムで監視 sudo tail -f /var/log/apache2/www.example.jp-error.log運用上の注意事項
定期的なセキュリティアップデート
目的:セキュリティ脆弱性への対策を適用し、システムの安全性を維持する。
以下のコマンドを定期的に実行し、システムを最新の状態に保つ。
sudo apt update sudo apt upgrade -y推奨頻度:最低でも月1回、可能であれば週1回実施する。セキュリティ上の重大な脆弱性が公表された場合は直ちに実施する。
アップデート後の確認:
sudo systemctl restart apache2 sudo systemctl status apache2Apache が正常に起動することを確認する。
ログの監視
目的:不正アクセスや攻撃の兆候を早期に検知する。
監視すべき項目:
- 404 エラーの多発:スキャン攻撃の可能性
- 特定 IP からの大量アクセス:DoS 攻撃の可能性
- 管理パスへのアクセス試行:不正ログイン試行の可能性
- 異常なユーザーエージェント:自動化ツールによる攻撃の可能性
SSL 設定の検証
目的:SSL/TLS 設定の安全性を第三者の視点で評価し、脆弱性を発見する。
SSL Labs(https://www.ssllabs.com/ssltest/)などの外部サービスを利用して、SSL/TLS 設定の安全性を定期的に検証する。
推奨頻度:初回設定後、および Apache や OpenSSL の大幅なアップデート後に実施する。
目標評価:A 評価以上を目指す。B 評価以下の場合、暗号スイートや SSL プロトコルの設定を見直す必要がある。
証明書の有効期限確認
目的:証明書の自動更新が失敗した場合に備え、手動での確認を実施する。
確認方法:
# 証明書の有効期限を確認 sudo certbot certificates有効期限が 30 日以内の場合、手動で更新を試みる。
sudo certbot renew