Linux: ファイアウォールとセキュリティ基礎 — ufw / SSH硬化 / fail2ban

新しいLinuxサーバーをインターネットに接続して数分で、スキャンと攻撃の標的にされます。セキュリティ硬化はオプションではなく必須です。

📋 前提条件:まず以下を完了していること

1. このレッスンで学ぶこと


2. 攻撃された実話

(1) 悩み:2日目でブルートフォース攻撃

小明はブログをホストするためにクラウドサーバーを借りました。2日目にログを確認すると恐ろしい結果が:

BASH
grep "Failed password" /var/log/auth.log | wc -l
# 1234 attempts!

世界中の自動スキャナーがSSHポート22へのログインを絶えず試行していました。

(2) 3層の硬化

彼は3つのことをしました:

BASH
# 1. Switch to key authentication
ssh-keygen -t ed25519
ssh-copy-id user@server

# 2. Disable password login
sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

# 3. Install fail2ban: 5 failures → 24-hour ban
sudo apt install fail2ban
sudo systemctl enable fail2ban

(3) 得られるもの:攻撃がゼロに

硬化後、auth.logの失敗試行は1日1000件以上から0に減りました。


3. 知識ポイント

(1) ufw — Uncomplicated Firewall

BASH
# Basic operations
sudo ufw status                   # View status
sudo ufw enable                   # Enable firewall
sudo ufw disable                  # Disable firewall
sudo ufw reload                   # Reload rules

# Rule management
sudo ufw allow 22/tcp             # Allow SSH
sudo ufw allow 80/tcp             # Allow HTTP
sudo ufw allow 443/tcp            # Allow HTTPS
sudo ufw deny 23/tcp              # Deny Telnet
sudo ufw deny from 10.0.0.100     # Block specific IP

# Application profiles
sudo ufw app list                 # List applications
sudo ufw allow "Nginx Full"       # Allow Nginx (80+443)
sudo ufw allow "OpenSSH"          # Allow SSH

# Rule management
sudo ufw status numbered          # Show rules with numbers
sudo ufw delete 2                 # Delete rule 2
⚠️ 警告:ufw/iptablesのルールは順序通りにマッチします — 最初にマッチしたルールが有効になります。allow from 0.0.0.0/0deny from malicious_ipの前に書くと、denyは永遠にトリガーされません — allowが既にマッチしているため。ルールの順序に注意し、ufw status numberedでルールリストを確認してください。

⚠️ 警告ufw allow fromで信頼できるIPを指定する際、0.0.0.0/0(全IPを許可)は絶対に使用しないでください — これは制限なしと同義でファイアウォールの意味がありません。常に具体的なIPまたはCIDRレンジを指定してください(例:ufw allow from 192.168.1.0/24)。

新サーバーのセキュリティポリシー:

⚠️ 警告ufw default deny incomingは全受信接続をデフォルトで拒否 — 明示的にallowされたポートのみアクセス可能なホワイトリストアプローチ。これが最も安全なデフォルトポリシーですが、有効化する前に必ずSSH(22/tcp)を許可してください。そうしないとサーバーから締め出されます。

BASH
# Default deny all incoming
sudo ufw default deny incoming
# Default allow all outgoing
sudo ufw default allow outgoing

# Only open needed ports
sudo ufw allow 22/tcp    # SSH
sudo ufw allow 80/tcp    # HTTP
sudo ufw allow 443/tcp   # HTTPS

sudo ufw enable

(2) SSH鍵認証

BASH
# Generate key pair (Ed25519 recommended)
ssh-keygen -t ed25519 -C "your_email@example.com"

# Traditional RSA (4096-bit)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

# Copy public key to server
ssh-copy-id user@server-ip

# Or add manually
cat ~/.ssh/id_ed25519.pub | ssh user@server-ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# Verify key login
ssh user@server-ip

(3) SSHセキュリティ硬化

⚠️ 警告:SSHポートの変更(例:2222へ)前に、代替アクセス手段を確保してください。クラウドプロバイダーがVNCコンソールを提供している場合はバックアップとして使用します。ポート変更後、新しいポートをufwで許可(ufw allow 2222/tcp)することを忘れないでください。変更前に既存のSSHセッションを開いたままにして安全策としてください。

/etc/ssh/sshd_configを編集:

TEXT
Port 2222                      # Change default port (evade automated scans)
PermitRootLogin no             # Disable direct root login
PasswordAuthentication no      # Disable password login
PubkeyAuthentication yes       # Enable key login
AllowUsers alice bob           # Only allow specified users
MaxAuthTries 3                 # Maximum authentication attempts
ClientAliveInterval 60         # Client keepalive interval (seconds)
ClientAliveCountMax 3         # Maximum keepalive failures

設定を確認して再起動:

BASH
sudo sshd -t                   # Test config syntax
sudo systemctl restart sshd    # Restart SSH service

(4) fail2ban

💡 ヒント:fail2banのjail.confはパッケージ提供で、アップグレード時に上書きされる可能性があります。カスタム設定はjail.localまたは/etc/fail2ban/jail.d/ディレクトリに配置してください — これらのファイルはアップグレードで上書きされず、優先度も高くなります。

BASH
# Install
sudo apt install fail2ban

# View status
sudo fail2ban-client status
sudo fail2ban-client status sshd

# Default config (/etc/fail2ban/jail.conf), usually no need to change
# [sshd]
# enabled = true
# port = ssh
# filter = sshd
# logpath = /var/log/auth.log
# maxretry = 5
# bantime = 3600

# Create local override
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo systemctl restart fail2ban

# View banned IPs
sudo iptables -L f2b-sshd -n

(5) ▶ サンプル:完全なufw設定

BASH
# If SSH is connected, allow SSH first
sudo ufw allow 22/tcp

# Configure default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Open service ports
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 2222/tcp     # If SSH port was changed

# Enable
sudo ufw enable
sudo ufw status verbose

出力:

TEXT
Rule added
Rule added
Default incoming policy changed to 'deny'
Default outgoing policy changed to 'allow'
Rule added
Rule added
Rule added
Firewall is active and enabled on system startup
Status: active
Logging: on (low)
To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
2222/tcp                   ALLOW IN    Anywhere

(6) ▶ サンプル:SSH鍵の作成と使用

BASH
# 1. Generate key pair on local machine
ssh-keygen -t ed25519

# 2. Copy to server
ssh-copy-id -i ~/.ssh/id_ed25519.pub alice@192.168.1.100

# 3. Test passwordless login
ssh alice@192.168.1.100

# 4. Use SSH config file for simplified login
cat >> ~/.ssh/config << 'EOF'
Host myserver
    HostName 192.168.1.100
    User alice
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
EOF

# Now you can use the shorthand
ssh myserver

出力:

TEXT
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/alice/.ssh/id_ed25519):
Your identification has been saved in /home/alice/.ssh/id_ed25519
Your public key has been saved in /home/alice/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:abc123def456 alice@workstation
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/alice/.ssh/id_ed25519.pub"
Number of key(s) added: 1
Now try logging into the machine:   ssh alice@192.168.1.100
Welcome to Ubuntu 22.04.3 LTS
Last login: Tue Jul  7 10:23:45 2026

(7) ▶ サンプル:SSH硬化の実践

BASH
# Back up original config
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# Modify configuration
sudo sed -i 's/^#Port 22/Port 2222/' /etc/ssh/sshd_config
sudo sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config

# Verify configuration
sudo sshd -t

# Restart SSH
sudo systemctl restart sshd

出力:

TEXT
(no output from sshd -t means config is valid)

(8) ▶ サンプル:fail2ban設定

BASH
# View fail2ban status
sudo fail2ban-client status

# View SSH jail status
sudo fail2ban-client status sshd
# Status for the jail: sshd
# |- Filter
# |  |- Currently failed: 3
# |  |- Total failed: 45
# |  `- File list: /var/log/auth.log
# `- Actions
#    |- Currently banned: 5
#    |- Total banned: 12
#    `- Banned IP list: 192.168.1.100 10.0.0.50

# Manually unban an IP
sudo fail2ban-client set sshd unbanip 192.168.1.100

# Custom ban duration
sudo tee /etc/fail2ban/jail.d/custom-sshd.conf << 'EOF'
[sshd]
enabled = true
maxretry = 3
bantime = 86400    # 24 hours
findtime = 600     # within 10 minutes
EOF

sudo systemctl restart fail2ban

出力:

TEXT
Status for the jail: sshd
|- Filter
|  |- Currently failed: 3
|  |- Total failed: 45
|  `- File list: /var/log/auth.log
`- Actions
   |- Currently banned: 5
   |- Total banned: 12
   `- Banned IP list: 192.168.1.100 10.0.0.50
1 unbanned

[sshd]
enabled = true
maxretry = 3
bantime = 86400
findtime = 600

(9) ▶ サンプル:自動セキュリティ更新

BASH
# Install unattended-upgrades
sudo apt install unattended-upgrades

# Configure
sudo dpkg-reconfigure --priority=low unattended-upgrades

# Or manually edit config
sudo tee /etc/apt/apt.conf.d/50unattended-upgrades << 'EOF'
Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}-security";
    "${distro_id}:${distro_codename}-updates";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
EOF

出力:

TEXT
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  unattended-upgrades
0 upgraded, 1 newly installed, 0 to remove

(10) ▶ 総合例:新サーバーワンクリックセキュリティ硬化

BASH
#!/bin/bash
# secure-server.sh - New server security hardening script
# Instructions: Run immediately after first SSH login
# Note: Make sure you have another SSH session open in a separate terminal as a backup!

set -euo pipefail

SSH_PORT="${1:-2222}"

echo "========================================"
echo "    Server Security Hardening"
echo "    Time: $(date)"
echo "========================================"

# 1. Update system
echo ">>> 1/6 Updating system..."
sudo apt update && sudo apt upgrade -y

# 2. Configure firewall
echo ">>> 2/6 Configuring firewall..."
sudo ufw --force disable
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow "$SSH_PORT/tcp" comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw --force enable
echo "Firewall configured (SSH port: $SSH_PORT)"

# 3. Configure SSH keys
echo ">>> 3/6 Configuring SSH keys..."
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# 4. SSH hardening
echo ">>> 4/6 SSH security hardening..."
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

sudo sed -i "s/^#Port 22/Port $SSH_PORT/" /etc/ssh/sshd_config
sudo sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sudo sed -i 's/^#MaxAuthTries 6/MaxAuthTries 3/' /etc/ssh/sshd_config

sudo sshd -t && sudo systemctl restart sshd
echo "SSH hardening complete"

# 5. Install fail2ban
echo ">>> 5/6 Installing fail2ban..."
sudo apt install -y fail2ban
sudo tee /etc/fail2ban/jail.d/sshd.conf << EOF
[sshd]
enabled = true
port = $SSH_PORT
maxretry = 3
bantime = 86400
findtime = 600
EOF
sudo systemctl enable --now fail2ban

# 6. Automatic security updates
echo ">>> 6/6 Configuring automatic updates..."
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades -y

echo ""
echo "========================================"
echo "✅ Security hardening complete!"
echo ""
echo "Important notes:"
echo "  1. SSH port changed to $SSH_PORT"
echo "  2. Root login disabled"
echo "  3. Password login disabled"
echo "  4. Ensure your public key is added to ~/.ssh/authorized_keys"
echo "  5. Before closing this SSH session, test connection in a new terminal:"
echo "     ssh -p $SSH_PORT ${USER}@$(curl -s ifconfig.me)"
echo "========================================"

❓ よくある質問

Q: ufw enableで締め出される? A: SSHを先に許可していないとその可能性があります。必ずsudo ufw allow 22/tcpsudo ufw enableの前に実行してください。既存のSSHセッションを開いたままにして安全策とし、古いセッションを閉じる前に新しいターミナルでテストしてください。

Q: SSH鍵とパスワードどちらが安全? A: 鍵認証はパスワードよりはるかに安全です。鍵は4096ビットRSAまたはEd25519の非対称暗号を使用し、理論上ブルートフォース不可能。パスワードは推測、辞書攻撃、フィッシングの対象になります。

Q: fail2banのBANは永続的? A: いいえ、デフォルトでは一時的(通常1時間)です。bantimeで期間をカスタマイズできます。永続BANは推奨されません — 攻撃者のIPは頻繁に変わり、BANリストが無限に増加します。

Q: SSHポート変更後の接続方法は? A: ssh -p 2222 user@host。または~/.ssh/configPort 2222を設定。

Q: しばらくパスワードログインを有効にしておく理由は? A: フォールバックとして。鍵を紛失または破損した場合、パスワードログインが唯一のアクセス手段です。鍵認証が確実に動作することを確認した後にのみ無効化してください。常にバックアップアクセス手段(クラウドプロバイダーのVNCコンソールなど)を確保してください。


📖 まとめ


📝 練習問題

  1. 基本(難易度 ⭐):現在のufwステータスを確認し、ポートを開閉し、ローカルでEd25519 SSH鍵ペアを生成する
  2. 中級(難易度 ⭐⭐):テストサーバー(またはlocalhostテスト)にSSH鍵ログインを設定し、fail2banをインストールしてSSH jailステータスを確認する
  3. 上級(難易度 ⭐⭐⭐):上記全ステップ(ufw設定、SSH鍵、SSH硬化、fail2ban)を含むセキュリティ硬化スクリプトを書き、各ステップで成功を確認してから次に進み、失敗時はロールバックする
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%