2026年5月24日
2026年5月24日
ufw / iptables で接続元IPを絞ってアクセス制御する方法
サーバーへのアクセスを接続元IPで制御するときの基本は、「受信は既定で拒否し、必要な通信だけを、必要な相手からだけ許可する」ことです。この記事では、ufw と iptables のそれぞれで、既定ポリシーの設定、接続元IPによる許可・拒否、ルールの順番、締め出しを防ぐ手順、設定の永続化までを説明します。
ポートを開ける手順そのもの(待ち受け確認やクラウド側の設定)は別記事で扱う内容なので、ここでは「誰に何を許すか」を設計して設定する部分に絞っています。
ufw と iptables の関係を押さえる
ufw(Uncomplicated Firewall)は、Linux カーネルのパケットフィルター(netfilter)を操作するための、扱いやすい前段ツールです。内部では iptables 形式のルールを生成しています。近年の Ubuntu や Debian では iptables コマンド自体が nftables をバックエンドに使う構成(iptables-nft)になっていることが多く、どちらで書いても最終的にはカーネルの同じ仕組みで処理されます(2026年10月現在、構成はディストリビューションやバージョンで異なります)。
ここで大切なのは、1台のサーバーで管理方法を1つに決めることです。ufw で管理しているサーバーに手で iptables ルールを足したり、firewalld と ufw を同時に動かしたりすると、どのルールが効いているのか追えなくなります。普段の運用は ufw、細かい制御が必要な場面だけ ufw の設定ファイル(/etc/ufw/before.rules など)に書く、というように役割を分けるのが現実的です。
アクセス制御を設計する
設定を始める前に、次のような表を紙やメモに書き出しておくと、ルールの漏れや重複を防げます。
- 22/tcp(SSH):管理者の固定IPやVPNの出口IPからだけ許可
- 80/tcp・443/tcp(Web):全世界に公開
- 3306/tcp(MySQL):同じネットワーク内のアプリサーバーからだけ許可。外部には出さない
- それ以外の受信:拒否
管理者の自宅回線のようにIPアドレスが変わる環境から接続している場合、IP制限だけに頼ると、アドレスが変わった日に締め出されます。VPNや踏み台サーバーを経由する構成にして、そこの固定IPを許可するほうが運用は安定します。
ufw で設定する
既定ポリシーと許可ルール
# 既定ポリシー:受信は拒否、送信は許可
sudo ufw default deny incoming
sudo ufw default allow outgoing
# SSHは管理用IPからだけ許可(有効化より前に追加しておく)
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
# ネットワーク範囲で許可する例
sudo ufw allow from 192.0.2.0/24 to any port 3306 proto tcp
# Webは全体に公開
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
既定ポリシーを deny incoming にしてから有効化すると、許可していない受信はすべて止まります。SSHを許可するルールが入っていない状態で有効化すると、その時点で接続が切れるので、有効化の前に sudo ufw show added で追加済みのルールを確認してください。
ルールの順番に注意する
ufw は上から順にルールを評価し、最初に一致したルールで処理を決めます。たとえば「443を全体に許可」のあとに「特定IPからの443を拒否」を追加しても、先に許可ルールに一致するため拒否は効きません。特定IPを遮断したいときは、insert で先頭側に入れます。
sudo ufw status numbered
# 1番目の位置に拒否ルールを挿入
sudo ufw insert 1 deny from 198.51.100.25
拒否には deny(黙って破棄)と reject(拒否したことを相手に返す)があります。外部に対しては deny が一般的ですが、社内ネットワーク内では reject にしておくと、接続できない理由がすぐ分かり切り分けが楽になります。
接続回数の制限
ufw には、同じIPから短時間に多数の接続があった場合に拒否する limit があります。ufw のマニュアルでは、30秒以内に6回以上の接続を試みたIPを拒否する動作と説明されています。
sudo ufw limit 22/tcp
これはパスワード総当たりの勢いを弱める程度のもので、本格的な対策にはなりません。SSHはパスワード認証を無効にして鍵認証にし、ログを見て自動で遮断する fail2ban などと組み合わせるのが一般的です。
IPv6 も対象にする
サーバーにIPv6アドレスがある場合、IPv4だけを制限してもIPv6側から接続できてしまいます。/etc/default/ufw の IPV6=yes を確認しておけば、ufw のルールはIPv4とIPv6の両方に作られます。
iptables で設定する
ufw を使わず iptables を直接扱う場合は、ルールを追加する順番がそのまま安全性に関わります。既定ポリシーを DROP にするのは、許可ルールを入れ終えた最後にします。
# ループバックと、確立済みの通信の戻りを許可
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# SSHは管理用IPからだけ
sudo iptables -A INPUT -p tcp -s 203.0.113.10 --dport 22 -j ACCEPT
# Webは全体に公開
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# 最後に既定ポリシーを拒否へ
sudo iptables -P INPUT DROP
# 番号付きで確認
sudo iptables -L INPUT -n -v --line-numbers
ESTABLISHED,RELATED の許可を忘れると、サーバーから外へ出た通信(パッケージ更新やAPI呼び出し)の戻りが止まり、「外に出られない」という症状になります。IPv6 は ip6tables で別に設定が必要です。
再起動後も残す
iptables コマンドで追加したルールは、そのままでは再起動で消えます。Debian / Ubuntu では iptables-persistent(netfilter-persistent)パッケージを使って保存する方法がよく使われます。
sudo apt install iptables-persistent
sudo netfilter-persistent save
# 保存先の例:/etc/iptables/rules.v4 と rules.v6
締め出しを防ぐ工夫
リモートからファイアウォールを変更するときは、失敗しても元に戻れる仕組みを用意してから作業します。
- SSHのセッションを2つ開き、片方は作業用、もう片方は変更後に新しい接続が通るかの確認用にする
atコマンドで、一定時間後にファイアウォールを無効化する予約を入れておき、問題がなければ予約を取り消す- VPSやクラウドの管理画面のコンソールから操作できることを、作業前に確かめておく
# 5分後に ufw を無効化する予約(問題なければ atrm で取り消す)
echo "ufw disable" | sudo at now + 5 minutes
sudo atq
iptables には、適用後に確認の入力がなければ元に戻す iptables-apply というスクリプトが用意されているディストリビューションもあります。
Docker を使っている場合の落とし穴
Docker は公開ポート(-p オプション)のために独自の iptables ルールを追加し、その通信は ufw の INPUT ルールより前に処理されます。このため「ufw で拒否しているのに、コンテナのポートには外からつながる」という状態が起こります。対策としては、コンテナのポートを 127.0.0.1 に限定して公開し、手前のリバースプロキシで制御する方法や、Docker が用意している DOCKER-USER チェーンに制限ルールを書く方法があります。
ネットワーク層とWebサーバー層の使い分け
ufw や iptables はポート単位の制御なので、「443番は公開しつつ、WordPress の管理画面だけ社内IPに限定したい」といった要件には向きません。この場合は Nginx の allow / deny や Apache の Require ip で、URLのパス単位に制限します。ネットワーク層では「そもそも外に出す必要のないポートを閉じる」、Webサーバー層では「公開しているサイトの一部を絞る」と役割を分けると、設定が整理しやすくなります。
設定後の確認とログ
設定後は、外部のマシンから許可したIP・許可していないIPの両方で接続を試し、意図どおりに通る・止まるかを確認します。ufw のログは sudo ufw logging on で有効にでき、Ubuntu では多くの場合 /var/log/ufw.log やカーネルログ(journalctl -k)に記録されます。拒否の記録を見れば、正規の利用者を誤って止めていないかの確認にも使えます。
まとめ
- 受信は既定で拒否し、必要なポートを必要な相手からだけ許可するのが基本です
- ufw も iptables も上から順に評価されるため、特定IPの拒否は許可ルールより前に置きます
- iptables では既定ポリシーの DROP を最後に設定し、確立済み通信の戻りを許可します。再起動後も残るよう保存します
- 作業前に締め出し対策(別セッション、時間差の無効化予約、管理画面のコンソール)を用意します
- Docker の公開ポートは ufw を迂回することがあり、管理画面だけの制限はWebサーバー側で行います