Linux: ファイアウォールとセキュリティ基礎 — ufw / SSH硬化 / fail2ban
新しいLinuxサーバーをインターネットに接続して数分で、スキャンと攻撃の標的にされます。セキュリティ硬化はオプションではなく必須です。
📋 前提条件:まず以下を完了していること
- レッスン23:ネットワーク基礎
1. このレッスンで学ぶこと
- ufw基本ルール設定
- SSH鍵認証
- SSHセキュリティ硬化
- fail2banブルートフォース防御
- システムセキュリティ更新
2. 攻撃された実話
(1) 悩み:2日目でブルートフォース攻撃
小明はブログをホストするためにクラウドサーバーを借りました。2日目にログを確認すると恐ろしい結果が:
grep "Failed password" /var/log/auth.log | wc -l
# 1234 attempts!
世界中の自動スキャナーがSSHポート22へのログインを絶えず試行していました。
(2) 3層の硬化
彼は3つのことをしました:
# 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
# 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
allow from 0.0.0.0/0をdeny 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)を許可してください。そうしないとサーバーから締め出されます。
# 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鍵認証
# 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セキュリティ硬化
ufw allow 2222/tcp)することを忘れないでください。変更前に既存のSSHセッションを開いたままにして安全策としてください。
/etc/ssh/sshd_configを編集:
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
設定を確認して再起動:
sudo sshd -t # Test config syntax
sudo systemctl restart sshd # Restart SSH service
(4) fail2ban
jail.confはパッケージ提供で、アップグレード時に上書きされる可能性があります。カスタム設定はjail.localまたは/etc/fail2ban/jail.d/ディレクトリに配置してください — これらのファイルはアップグレードで上書きされず、優先度も高くなります。
# 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設定
# 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
出力:
TEXTRule 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鍵の作成と使用
# 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
出力:
TEXTGenerating 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硬化の実践
# 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設定
# 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
出力:
TEXTStatus 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) ▶ サンプル:自動セキュリティ更新
# 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
出力:
TEXTReading 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) ▶ 総合例:新サーバーワンクリックセキュリティ硬化
#!/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/tcpをsudo 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/configにPort 2222を設定。
Q: しばらくパスワードログインを有効にしておく理由は? A: フォールバックとして。鍵を紛失または破損した場合、パスワードログインが唯一のアクセス手段です。鍵認証が確実に動作することを確認した後にのみ無効化してください。常にバックアップアクセス手段(クラウドプロバイダーのVNCコンソールなど)を確保してください。
📖 まとめ
- ufw:
allow 22/tcp→default deny incoming→enable - SSH鍵:
ssh-keygen -t ed25519→ssh-copy-id user@host→ パスワードログイン無効化 - SSH硬化:ポート変更、root無効化、パスワード無効化、ユーザー制限
- fail2ban:
maxretry=3、bantime=86400、findtime=600 unattended-upgradesで自動セキュリティパッチ
📝 練習問題
- 基本(難易度 ⭐):現在のufwステータスを確認し、ポートを開閉し、ローカルでEd25519 SSH鍵ペアを生成する
- 中級(難易度 ⭐⭐):テストサーバー(またはlocalhostテスト)にSSH鍵ログインを設定し、fail2banをインストールしてSSH jailステータスを確認する
- 上級(難易度 ⭐⭐⭐):上記全ステップ(ufw設定、SSH鍵、SSH硬化、fail2ban)を含むセキュリティ硬化スクリプトを書き、各ステップで成功を確認してから次に進み、失敗時はロールバックする