皆さんこんにちは!新人のアナサピです!
今回はPFとfirewalldとApacheでIP制御の比較を行いました!
皆さんは「IP制限」と聞くと、何を思い浮かべますか?
- さくらのクラウドのパケットフィルタ(PF)
- OS(firewalld)
- アプリ(Apache)
- WAF
等々、色々な方法があります。
ただ、どれも「アクセスを拒否する」という点では同じように見える一方で、「どこで通信を止めているのか」はかなり違います。
実際、制御する場所によって、サーバ負荷やログの残り方、防げる内容まで変わってきます。
今回は、「結局どこでIP制限をするのが良いのか?」をイメージしやすくするために、今回は実際 AlmaLinux + Apache + PHP の環境をさくらのクラウドで用意し、
- どこで通信が止まるのか
- CPU負荷はどう変わるのか
- ログは残るのか
を実際に検証してみました。
結論としては、「どれが正解」というより、“何をどこまで到達させたくないか”などの目的によって使い分けるものだと感じました。
今回はその違いを、実際の負荷テスト結果と一緒に整理していきます。
「そもそもパケットフィルタってなに?」
弊社の社員が分かり易い記事を公開しておりますので、こちらの記事をご覧ください!

今回のポイント
単純な「制限できる / 制限できない」だけでは、今回の3つどれでも制御できますので、比較にはなりません。
そのため今回は、実際に負荷をかけながら、サーバ内部で何が起きているのかも合わせて確認していきます。
今回特に確認したのは以下のポイントです。
- top
- tcpdump
- ログ(access_log)
今回の検証はCPU使用率などが分かりやすくする為に、意図的に重いPHPを設置しております。
あくまでも検証であり、実際はコンテンツの造り方などの環境次第で変わっていきますので、参考程度にご覧ください。
また、今回のポイントを画像にまとめましたので、検証内容をスキップしたい方は こちらから今回のまとめ までスキップできます。
今回の検証環境
スペック
メモリ:2 GB
CPU:2 コア
OS
AlmaLinux 9.7 を使用。
使用したもの
- Apache(httpd)
- php-fpm
- firewalld
- tcpdump
検証用PHP
今回の検証に必須ではないのですが、CPU負荷を分かりやすくするため、意図的に重いPHPを配置しております。
負荷テスト方法
実際に別のサーバから大量のアクセスを実施しております。
方法については今回の記事とは逸れる為、省略させていただきます。
① 制限なし(ノーガード)
まずは何も制限しない状態です。
※ポートを全開放してしまうと、他のIPからもアクセスできてしまうので、実際はアクセス元のIPのみ許可している状態です。
結果
CPU
%Cpu0 : 99.3 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
%Cpu1 : 99.7 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st
topコマンド結果全文
[root@web01 ~]# top
top - 18:11:31 up 53 min, 3 users, load average: 4.20, 1.79, 0.69
Tasks: 167 total, 10 running, 157 sleeping, 0 stopped, 0 zombie
%Cpu0 : 99.3 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
%Cpu1 : 99.7 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st
MiB Mem : 1963.1 total, 585.2 free, 467.9 used, 1088.8 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1495.1 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
45410 apache 20 0 178072 15700 9184 R 20.3 0.8 0:12.27 php-fpm
45813 apache 20 0 178104 15072 8544 R 19.6 0.7 0:11.34 php-fpm
45809 apache 20 0 178072 15064 8544 R 18.9 0.7 0:10.78 php-fpm
45816 apache 20 0 178104 15072 8544 R 18.6 0.7 0:08.24 php-fpm
45808 apache 20 0 178072 15064 8548 R 16.6 0.7 0:11.02 php-fpm
45811 apache 20 0 178072 15700 9184 R 16.6 0.8 0:08.94 php-fpm
45826 apache 20 0 178104 15072 8544 R 16.6 0.7 0:01.32 php-fpm
45815 apache 20 0 178104 15076 8548 R 16.3 0.7 0:10.34 php-fpm
45814 apache 20 0 178104 15072 8544 R 15.9 0.7 0:10.55 php-fpm
45408 apache 20 0 178072 15056 8540 S 6.6 0.7 0:11.88 php-fpm
45409 apache 20 0 178072 15056 8540 S 6.0 0.7 0:09.69 php-fpm
45812 apache 20 0 178104 15072 8548 S 6.0 0.7 0:11.15 php-fpm
45407 apache 20 0 178072 15056 8540 S 5.3 0.7 0:11.83 php-fpm
45810 apache 20 0 178072 15060 8544 S 5.3 0.7 0:11.11 php-fpm
45598 apache 20 0 178072 15700 9184 S 5.0 0.8 0:11.85 php-fpm
45411 apache 20 0 178072 15700 9184 S 4.7 0.8 0:09.91 php-fpm
45615 apache 20 0 1441756 11928 6832 S 0.3 0.6 0:00.13 httpd
45825 root 20 0 7672 3988 3128 R 0.3 0.2 0:00.04 top
1 root 20 0 175908 18780 11432 S 0.0 0.9 0:03.22 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 pool_workqueue_
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-rcu_g
5 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-sync_
6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-slub_
7 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-netns
10 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/u8:0-events_unbound
11 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-mm_pe
12 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/u8:1-netns
13 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_kthre
14 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_rude_
15 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_trace
16 root 20 0 0 0 0 S 0.0 0.0 0:00.08 ksoftirqd/0
17 root 0 -20 0 0 0 S 0.0 0.0 0:00.30 pr/ttyS0
18 root 20 0 0 0 0 I 0.0 0.0 0:00.31 rcu_preempt
19 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_exp_par_gp_
20 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_exp_gp_kthr
21 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
22 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/0
24 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0
25 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/1
26 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/1
27 root rt 0 0 0 0 S 0.0 0.0 0:00.05 migration/1
28 root 20 0 0 0 0 S 0.0 0.0 0:00.07 ksoftirqd/1
30 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/1:0H-events_highpri
34 root 20 0 0 0 0 I 0.0 0.0 0:00.13 kworker/u10:1-events_unbound
35 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
36 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-inet_
37 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kauditd
38 root 20 0 0 0 0 S 0.0 0.0 0:00.00 khungtaskd
40 root 20 0 0 0 0 I 0.0 0.0 0:00.13 kworker/u9:2-events_unbound
41 root 20 0 0 0 0 S 0.0 0.0 0:00.00 oom_reaper
42 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-write
43 root 20 0 0 0 0 S 0.0 0.0 0:00.02 kcompactd0
[root@web01 ~]#
CPUは2コア両方でほぼ100%まで上昇しました。
特に使用率上位に php-fpm が来ております。
意図的に重いPHPを設置しておりますので、当然ではありますが、実際に
HTTP到達
↓
Apache
↓
PHP実行
↓
CPU消費
まで完全に処理が進んでいるのが分かります。
各種確認まとめ
| 項目 | 状態 |
|---|---|
| CPU | 非常に高い |
| tcpdump | 見える |
| access_log | ステータスコード 200 |
これを基準に各制御方法を確認していきましょう!
IP制限② ApacheでIP制限
次は Apache 側で制御します。
設定
/etc/httpd/conf.d/ipdeny.conf
<Directory "/var/www/html">
Require ip 127.0.0.1
</Directory>
結果
CPU
%Cpu0 : 6.7 us, 16.7 sy, 0.0 ni, 71.3 id, 0.0 wa, 0.7 hi, 4.7 si, 0.0 st
%Cpu1 : 5.8 us, 13.6 sy, 0.0 ni, 74.9 id, 0.0 wa, 1.0 hi, 4.7 si, 0.0 st
topコマンド詳細
[root@web01 ~]# top
top - 18:56:12 up 14:38, 3 users, load average: 0.00, 0.00, 0.00
Tasks: 166 total, 1 running, 165 sleeping, 0 stopped, 0 zombie
%Cpu0 : 6.7 us, 16.7 sy, 0.0 ni, 71.3 id, 0.0 wa, 0.7 hi, 4.7 si, 0.0 st
%Cpu1 : 5.8 us, 13.6 sy, 0.0 ni, 74.9 id, 0.0 wa, 1.0 hi, 4.7 si, 0.0 st
MiB Mem : 1963.1 total, 586.0 free, 469.5 used, 1086.4 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1493.6 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
47008 tcpdump 20 0 19552 10208 8420 S 9.3 0.5 0:00.56 tcpdump
46682 almalin+ 20 0 22360 9360 5696 S 8.0 0.5 0:00.47 sshd
46829 apache 20 0 1442032 14172 6528 S 5.0 0.7 0:00.31 httpd
46827 apache 20 0 1441896 14588 6528 S 4.3 0.7 0:00.30 httpd
47012 apache 20 0 1441896 13960 6532 S 4.3 0.7 0:00.16 httpd
46828 apache 20 0 1573032 14088 6548 S 4.0 0.7 0:00.28 httpd
46715 almalin+ 20 0 21144 7900 5696 S 2.7 0.4 0:00.12 sshd
46364 root 20 0 0 0 0 I 2.0 0.0 0:00.26 kworker/u9:1-events_unbound
46569 root 20 0 0 0 0 I 2.0 0.0 0:00.10 kworker/u9:2-events_unbound
47009 root 20 0 2692 1676 1560 S 1.7 0.1 0:00.07 tail
46526 root 20 0 0 0 0 I 0.3 0.0 0:00.05 kworker/u10:2-events_unbound
46554 root 20 0 0 0 0 I 0.3 0.0 0:00.04 kworker/u10:1-events_unbound
47067 root 20 0 7668 3944 3080 R 0.3 0.2 0:00.03 top
1 root 20 0 175908 18780 11432 S 0.0 0.9 0:05.83 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 pool_workqueue_
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-rcu_g
5 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-sync_
6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-slub_
7 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-netns
10 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/u8:0-events_unbound
11 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-mm_pe
12 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/u8:1-netns
13 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_kthre
14 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_rude_
15 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_trace
16 root 20 0 0 0 0 S 0.0 0.0 0:00.11 ksoftirqd/0
17 root 0 -20 0 0 0 S 0.0 0.0 0:00.30 pr/ttyS0
18 root 20 0 0 0 0 I 0.0 0.0 0:02.77 rcu_preempt
19 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_exp_par_gp_
20 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_exp_gp_kthr
21 root rt 0 0 0 0 S 0.0 0.0 0:00.03 migration/0
22 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/0
24 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0
25 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/1
26 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/1
27 root rt 0 0 0 0 S 0.0 0.0 0:00.09 migration/1
28 root 20 0 0 0 0 S 0.0 0.0 0:00.08 ksoftirqd/1
30 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/1:0H-events_highpri
35 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
36 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-inet_
37 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kauditd
38 root 20 0 0 0 0 S 0.0 0.0 0:00.03 khungtaskd
41 root 20 0 0 0 0 S 0.0 0.0 0:00.00 oom_reaper
42 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-write
43 root 20 0 0 0 0 S 0.0 0.0 0:00.45 kcompactd0
44 root 25 5 0 0 0 S 0.0 0.0 0:00.00 ksmd
45 root 39 19 0 0 0 S 0.0 0.0 0:02.33 khugepaged
46 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-crypt
47 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-kinte
48 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-kbloc
49 root -51 0 0 0 0 S 0.0 0.0 0:00.00 irq/9-acpi
51 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-tpm_d
[root@web01 ~]#
先ほどと比べると、かなりユーザー処理が下がっています。
これはApache側で403を返しているため、PHPまで処理がとどいていないことが分かります。
しかし、アクセス自体はApacheまで到達しています。
そのため、access_log にはステータスコード403が記録されています。
"GET /index.php HTTP/1.0" 403
つまり、
HTTP到達
↓
Apache
↓
ステータスコード403返却
PHPは実行されない
という状態であることが分かります。
各種確認まとめ
| 項目 | 状態 |
|---|---|
| CPU | 少し上昇(30%前後) |
| tcpdump | 見える |
| access_log | ステータスコード 403 |
Apache制御のポイント
IP制限③ firewalld(OS)でDROP
次はOSレベルです。
今回は firewalld で明示的に DROP しました。
firewalld設定内容
[root@web01 ~]# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port port="80" protocol="tcp" drop'
success
[root@web01 ~]# firewall-cmd --reload
success
[root@web01 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: cockpit dhcpv6-client
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
rule family="ipv4" port port="80" protocol="tcp" drop
[root@web01 ~]#
結果
ここでかなり挙動が変わりました。
CPU
%Cpu0 : 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
これまでの2つの検証と違い、ほとんど0%です。
NIC
↓
Kernel(サーバ)
↓
DROP
Apacheは実行されない
という状態になっていることが分かります。
また、Apacheまで到達していない為、Apacheのアクセスログにも記録されていません。
tcpdumpで確認
Apacheのアクセスログに記録がされないため、tcpdumpというサーバの通信を確認するコマンドで確認します。
[root@web01 ~]# tcpdump -nn port 80
19:09:57.899570 IP "アクセス元のIP".46792 > "検証サーバのIP".80: Flags [S], seq 3334012566, win 64240, options [mss 1460,sackOK,TS val 2117990033 ecr 0,nop,wscale 7], length 0
実際に記録はされていたので、通信自体が届いていることが確認できます。
各種確認まとめ
| 項目 | 状態 |
|---|---|
| CPU | ほぼ使わない |
| tcpdump | 記録あり |
| access_log | 残らない |
IP制限④ さくらのクラウド パケットフィルタ(PF)
最後はクラウド側です。
今回はさくらのクラウドのパケットフィルタで TCP/80 を deny しました。
今回初めて設定したのですが、下記の記事を参考に設定してみました!

結果
CPU
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
firewalldの時点で、ほぼ使用率0でしたがパケットフィルタはサーバーの外で制御しているため、使用率の変化は見られませんでした。
tcpdumpで確認
[root@web01 ~]# tcpdump -nn port 80
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel
[root@web01 ~]#
先ほどとは異なり、0 packets captured となっております。
つまり、サーバのNICまでHTTP通信が来ていない ということがわかります。
IP制限まとめ
| 制御箇所 | Apache到達 | アクセスログ | tcpdump | CPU |
|---|---|---|---|---|
| ノーガード | ○ | ○(200) | ○ | 非常に高い |
| Apache | ○ | ○(403) | ○ | 少し高い |
| firewalld | × | × | ○ | かなり低い |
| PF | × | × | × | 影響無 |
今回の検証は比較がしやすいように、IP制限に絞ってCPU使用率を中心に見てきました。
そのため、今回の結果だけを見るとパケットフィルタが一番いいように見えますが、実際は【制御できる範囲】が異なるため、目的にあった用途を選択する必要があります。
特にApacheでの制御は、
「/admin だけ制限したい」
「Basic認証と組み合わせたい」
など、アプリ寄りの細かい制御が得意です。
一方で、DDoSのような大量アクセスや、そもそも通信を通したくないケースでは、より手前で落とせるPFやfirewalldの方が有利になります。
実際の運用されているサーバだと、複数組み合わせて利用することも珍しくありません。

次回の記事について
今回登場した、パケットフィルタ(PF)、firewalld、Apacheの三つは、どちらかというと“サーバに近い層”の話であり、CPU使用率という数字での比較がやりやすかったです。
次回は、今回は敢えて触れてこなかった「制御範囲」という視点から、
「どこで通信を止めると、どこまで到達するのか?」
「WAFとPFは何が違うのか?」
「GSLBやDNSは“防御”なのか?」
といった部分も含めて、外側から内側までのレイヤー構造を整理しながら解説していきたいと思います!


