0 はじめに
旧記事(「DockerやKubernetesはiptablesをどのように使っているのか?(継続調査中)」)は、
記事を追加し続けていった結果、良くわからない構成になってしまったので、
ここ(private)に移動しました。
改めて、iptablesの使い方、というタイトルで再出発します。
1 環境
VMware Workstation 12 Player上の仮想マシンを使っています。
仮想マシンはサーバとクライアントの2台構成です。
サーバ、クライアントともに下記設定です。
[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
[root@server ~]# uname -r
3.10.0-514.el7.x86_64
[root@server ~]# cat /etc/hosts
192.168.0.10 server
192.168.0.110 client
2 構成
クライアント、サーバの2台構成です。
192.168.0.0/24
client --------------------- server
.110 .10
3 チェインとは?
チェインは、ルールの集合です。
ルールは、ある条件にマッチしたらパケットを廃棄する、といった規則のことです。
チェインは、OS内に5箇所あります。5つのチェインは、組み込みチェインと呼ばれています。
・PREROUTING
・INPUT
・OUTPUT
・POSTROUTING
・FORWARD
なお、チェインはiptables利用者が独自に定義することも可能です(ユーザ定義チェイン)。
4 ルールの表示方法(-L)
4.1 INPUTチェインのルールの表示方法
[root@server ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
INPUT_direct all -- anywhere anywhere
INPUT_ZONES_SOURCE all -- anywhere anywhere
INPUT_ZONES all -- anywhere anywhere
DROP all -- anywhere anywhere ctstate INVALID
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
4.2 OUTPUTチェインのルールの表示方法
[root@server ~]# iptables -L OUTPUT
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
OUTPUT_direct all -- anywhere anywhere
4.3 FORWARDチェインのルールの表示方法
[root@server ~]# iptables -L FORWARD
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
FORWARD_direct all -- anywhere anywhere
FORWARD_IN_ZONES_SOURCE all -- anywhere anywhere
FORWARD_IN_ZONES all -- anywhere anywhere
FORWARD_OUT_ZONES_SOURCE all -- anywhere anywhere
FORWARD_OUT_ZONES all -- anywhere anywhere
DROP all -- anywhere anywhere ctstate INVALID
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
4.4 PREROUTINGチェインのルールの表示方法
PREROUTINGチェインは、-t natオプションを付けてルールを表示します。
[root@server ~]# iptables -t nat -L PREROUTING
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
PREROUTING_direct all -- anywhere anywhere
PREROUTING_ZONES_SOURCE all -- anywhere anywhere
PREROUTING_ZONES all -- anywhere anywhere
4.5 POSTROUTINGチェインのルールの表示方法
POSTROUTINGチェインは、-t natオプションを付けてルールを表示します。
[root@server ~]# iptables -t nat -L POSTROUTING
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
POSTROUTING_direct all -- anywhere anywhere
POSTROUTING_ZONES_SOURCE all -- anywhere anywhere
POSTROUTING_ZONES all -- anywhere anywhere
4.6 RAWチェインのルールの表示方法
RAWチェインは、-t natオプションを付けてルールを表示します。
[root@server ~]# iptables -t nat -nvL RAW
iptables: No chain/target/match by that name.
5 ルールの詳細を表示する方法
5.1 数値で表示する方法(-n)
アドレスを文字列ではなく数値で表示します。
OUTPUTチェインのルールを数値で表示してみます。
nオプションを付けて、iptablesを実行する。アドレスが数値で表示されたことがわかります。
[root@server ~]# iptables -nL OUTPUT
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
OUTPUT_direct all -- 0.0.0.0/0 0.0.0.0/0
5.2 パケット数やバイト数を表示する方法(-v)
vオプションを付けてiptablesを実行します。
1列目にパケット数(pkts)、2列目にバイト数(bytes)が表示されていることがわかります。
[root@server ~]# iptables -vL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
827 84066 ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- lo any anywhere anywhere
12 2910 INPUT_direct all -- any any anywhere anywhere
12 2910 INPUT_ZONES_SOURCE all -- any any anywhere anywhere
12 2910 INPUT_ZONES all -- any any anywhere anywhere
0 0 DROP all -- any any anywhere anywhere ctstate INVALID
11 2858 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
5.3 ルールの番号を表示する方法(--line-numbers)
左端にルールの番号(num)が表示されていることがわかります。
[root@server ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
2 ACCEPT all -- anywhere anywhere
3 INPUT_direct all -- anywhere anywhere
4 INPUT_ZONES_SOURCE all -- anywhere anywhere
5 INPUT_ZONES all -- anywhere anywhere
6 DROP all -- anywhere anywhere ctstate INVALID
7 REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
6 ルールの追加、削除方法(-A,-D)
ルールの追加(-A)は、既存ルールの末尾に新規ルールを追加します。
6.1 ルールの追加(-A)
初期状態を確認します。
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
ICMPパケットを送信したらログに記録する、というルールを追加する。
[root@server ~]# iptables -A OUTPUT -p icmp -j LOG
OUTPUTのルールを確認します。
ルールが末尾に追加されたことがわかります。
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
2 LOG icmp -- anywhere anywhere LOG level warning
6.2 ルールの削除(-D)
ルールを削除するときは、-D <チェイン名> <ルールの番号>
と指定します。
"ルールの番号"とは、5.3で確認した番号になります。
ルールを確認します。ルールが2つあることがわかります。
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
2 LOG icmp -- anywhere anywhere LOG level warning
2番目のルールを削除します。
[root@server ~]# iptables -D OUTPUT 2
ルールを確認します。2番のルールが削除されたことがわかります。
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
7 ルールの挿入、削除方法(-I,-D)
挿入は、既存ルールの先頭、または既存ルールの途中に新規ルールを挿入します。
7.1 ルールの挿入(-I)
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
[root@server ~]# iptables -I OUTPUT 1 -p icmp -j LOG
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 LOG icmp -- anywhere anywhere LOG level warning
2 OUTPUT_direct all -- anywhere anywhere
7.2 ルールの削除(-D)
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 LOG icmp -- anywhere anywhere LOG level warning
2 OUTPUT_direct all -- anywhere anywhere
[root@server ~]# iptables -D OUTPUT 1
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
8 ルールを置き換える方法(-R)
既存ルールを別のルールに置き換える方法を説明します。
ICMPパケットを受信したらログを出力する、というルールを挿入する。
[root@server ~]# iptables -I INPUT 6 -p icmp -j LOG
ルールを確認する。6番目(★)にルールが挿入されたことがわかる。
[root@server ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
2 ACCEPT all -- anywhere anywhere
3 INPUT_direct all -- anywhere anywhere
4 INPUT_ZONES_SOURCE all -- anywhere anywhere
5 INPUT_ZONES all -- anywhere anywhere
6 ★LOG icmp -- anywhere anywhere LOG level warning
7 DROP all -- anywhere anywhere ctstate INVALID
8 REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
6番目のルールを置き換える。
[root@server ~]# iptables -R INPUT 6 -p udp -j LOG
INPUTチェインのルールを確認する。ICMPからUDPに関するルール(★)に置き換わったことがわかる。
[root@server ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
2 ACCEPT all -- anywhere anywhere
3 INPUT_direct all -- anywhere anywhere
4 INPUT_ZONES_SOURCE all -- anywhere anywhere
5 INPUT_ZONES all -- anywhere anywhere
6 ★LOG udp -- anywhere anywhere LOG level warning
7 DROP all -- anywhere anywhere ctstate INVALID
8 REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
9 カウンタをリセットする方法(-Z)
ICMPパケットを受信したらログを出力する、というルールを追加する。
[root@server ~]# iptables -A OUTPUT -p icmp -j LOG
ルールを確認する。ルールが追加されたことがわかる。パケットの送信個数は0(★)であることがわかる。
[root@server ~]# iptables -nvxL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 56 packets, 7700 bytes)
num pkts bytes target prot opt in out source destination
1 1402 217305 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2 ★0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
デフォルトGWに対してpingを実行する。
[root@server ~]# ping -c 1 192.168.0.1
OUTPUTチェインのルールを確認する。ICMPの送信パケット数が1(★)に増加したことがわかる。
[root@server ~]# iptables -nvxL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 117 packets, 17432 bytes)
num pkts bytes target prot opt in out source destination
1 1463 227037 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2 ★1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
OUTPUTチェインのカウンタを0クリアする。
[root@server ~]# iptables -Z OUTPUT
OUTPUTチェインのルールを確認する。ICMPの送信パケット数が0クリア(★)されたことがわかる。
[root@server ~]# iptables -nvxL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 5 packets, 664 bytes)
num pkts bytes target prot opt in out source destination
1 5 664 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2 ★0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
10 ユーザ定義チェイン
iptables利用者は、ユーザ定義チェインを作成することができます。
ここでは、"TEST"という名前のユーザ定義チェインの作成、削除等を実施します。
10.1 ユーザ定義チェインの作成方法(-N)
ユーザ定義チェイン(TEST)を作成する。
[root@server ~]# iptables -N TEST
ユーザ定義チェインに登録されているルールを確認する。
ユーザ定義チェインが作成されたことがわかる。
しかし、ユーザ定義チェインにはルールが登録されていません。
[root@server ~]# iptables -L TEST
Chain TEST (0 references)
target prot opt source destination
10.2 ユーザ定義チェインの削除方法(-X)
ユーザ定義チェイン(TEST)を削除する。
[root@server ~]# iptables -X TEST
ユーザ定義チェインに登録されているルールを確認する。チェインが削除されたので、エラーが表示されることがわかる。
[root@server ~]# iptables -L TEST
iptables: No chain/target/match by that name.
10.3 ユーザ定義チェインにルールを追加する方法(-A,-I)
ユーザ定義チェイン(TEST)を作成する。
[root@server ~]# iptables -N TEST
ユーザ定義チェインにルールを追加する。
[root@server ~]# iptables -A TEST -p icmp -j LOG
ユーザ定義チェインに登録されているルールを確認する。
[root@server ~]# iptables -L TEST
Chain TEST (0 references)
target prot opt source destination
LOG icmp -- anywhere anywhere LOG level warning
10.4 ユーザ定義チェインを組み込みチェインに登録する方法(-A,-I)
OUTPUTチェインにユーザ定義チェイン(TEST)を挿入する。
[root@server ~]# iptables -I OUTPUT -j TEST
OUTPUTチェインを確認する。1番目(★)にユーザ定義チェインが挿入されたことがわかる。
[root@server ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 ★TEST all -- anywhere anywhere
2 OUTPUT_direct all -- anywhere anywhere
10.5 ユーザ定義チェインの送信パケット数の確認方法
初期状態を確認する。ICMPパケットの送信数は0(★)であることがわかる。
[root@server ~]# iptables -nvL TEST
Chain TEST (1 references)
pkts bytes target prot opt in out source destination
★0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
ICMPパケットを5個送信する。
[root@server ~]# ping -c 5 192.168.0.1
ICMPパケットの送信個数を確認する。ICMPパケットの送信数が5(★)になったことがわかる。
[root@server ~]# iptables -nvL TEST
Chain TEST (1 references)
pkts bytes target prot opt in out source destination
★5 420 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
11 ルールの指定方法について
11.1 プロトコルを指定する方法(-p)
指定できるプロトコルとして、icmp,udp,tcp等があります。
/etc/protocolsに登録されているプロトコルが、-pのパラメータとして指定できます。
[root@server ~]# iptables -L OUTPUT
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
TEST all -- anywhere anywhere
OUTPUT_direct all -- anywhere anywhere
[root@server ~]# iptables -A OUTPUT -p icmp -j LOG
[root@server ~]# iptables -A OUTPUT -p udp -j LOG
[root@server ~]# iptables -A OUTPUT -p tcp -j LOG
[root@server ~]# iptables -L OUTPUT
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
TEST all -- anywhere anywhere
OUTPUT_direct all -- anywhere anywhere
LOG icmp -- anywhere anywhere LOG level warning
LOG udp -- anywhere anywhere LOG level warning
LOG tcp -- anywhere anywhere LOG level warning
11.2 インタフェースを指定する方法
11.2.1 入力インタフェースを指定する方法(-i)
[root@server ~]# iptables -I INPUT -p icmp -i eth0 -j LOG
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 LOG icmp --★eth0 * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 4348 445K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
3 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
4 172 26426 INPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
5 172 26426 INPUT_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0
6 172 26426 INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
7 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
8 171 26374 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
11.2.2 出力インタフェースを指定する方法(-o)
[root@server ~]# iptables -A OUTPUT -o eth0 -p icmp -j LOG
[root@server ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 46 packets, 6288 bytes)
num pkts bytes target prot opt in out source destination
1 1790 415K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 LOG icmp -- * ★eth0 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
11.2.3 全てのインタフェースを指定する方法(+)
本検証環境は、イーサネットインタフェースとしてeth0,eth1を搭載しています。
ここでは、eth0,eth1から入ってくるTCPパケット(宛先ポート番号80)の受信許可のルールを設定してみます。
[root@server ~]# ip a |grep -w inet
inet 127.0.0.1/8 scope host lo
inet 192.168.3.20/24 brd 192.168.3.255 scope global eth0
inet 192.168.3.4/24 brd 192.168.3.255 scope global dynamic eth1
全てのインタフェースを指定するには、eth+
と指定します。
[root@server ~]# iptables -A INPUT -i eth+ -p tcp --dport 80
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 31 packets, 1852 bytes)
pkts bytes target prot opt in out source destination
0 0 tcp -- eth+ * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
11.2.4 否定を指定する方法(!)
[root@server ~]# ip a |grep -w inet
inet 127.0.0.1/8 scope host lo
inet 192.168.3.20/24 brd 192.168.3.255 scope global eth0
inet 192.168.3.4/24 brd 192.168.3.255 scope global dynamic eth1
[root@server ~]# iptables -A INPUT ! -i eth1 -j ACCEPT
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
38 2204 ACCEPT all -- !eth1 * 0.0.0.0/0 0.0.0.0/0
11.3 IPアドレスを指定する方法
11.3.1 送信元IPを指定する方法(-s)
[root@server ~]# iptables -I INPUT -p icmp -s 192.168.0.1 -j LOG
[root@server ~]# iptables -nvxL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG icmp -- * * ★192.168.0.1 0.0.0.0/0 LOG flags 0 level 4
5763 588280 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
176 27738 INPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
176 27738 INPUT_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0
176 27738 INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
175 27686 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
[root@server ~]# ping -c 1 192.168.0.1
[root@server ~]# iptables -nvxL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
★1 84 LOG icmp -- * * 192.168.0.1 0.0.0.0/0 LOG flags 0 level 4
5796 591276 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
176 27738 INPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
176 27738 INPUT_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0
176 27738 INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
175 27686 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
ルールを削除する。
[root@server ~]# iptables -D INPUT 1
11.3.2 送信先IPを指定する方法(-d)
ICMPパケット(宛先IPが192.168.0.1)を送信したらログに記録する、というルールを追加する。
[root@server ~]# iptables -A OUTPUT -p icmp -d 192.168.0.1 -j LOG
ルールを確認する。ルール(★)が追加されたことがわかる。
[root@server ~]# iptables -nvxL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 56 packets, 7264 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 LOG icmp -- * eth0 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 0 0 LOG icmp -- * * 0.0.0.0/0 ★192.168.0.1 LOG flags 0 level 4
デフォルトGWに対してpingを実行する。
[root@server ~]# ping -c 1 192.168.0.1
ルールを確認する。ICMPパケットの送信個数が1個(★)に増加したことがわかる。
[root@server ~]# iptables -nvxL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 96 packets, 13468 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 LOG icmp -- * eth0 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 ★1 84 LOG icmp -- * * 0.0.0.0/0 192.168.0.1 LOG flags 0 level 4
11.4 ポート番号を指定する方法
11.4.1 送信元ポート番号を指定する方法(--sport)
DNS応答(送信元UDPポート番号53)のパケットを受信したらログに記録する、というルールを挿入する。
[root@server ~]# iptables -I INPUT -p udp --sport 53 -j LOG
DNS名前解決を行う。
[root@server ~]# dig ntp.nict.jp +short
133.243.238.164
133.243.238.163
133.243.238.244
133.243.238.243
ルールを確認する。DNS応答を1つ(★)受信したことがわかる。
[root@server ~]# iptables -nvxL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 ★1 235 LOG udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53 LOG flags 0 level 4
2 4917 504701 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
3 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
4 172 26426 INPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
5 172 26426 INPUT_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0
6 172 26426 INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
7 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
8 171 26374 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
ルールを削除する。
[root@server ~]# iptables -nvxL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
11.4.2 送信先ポート番号を指定する方法(--dport)
DNSクエリ(送信先UDPポート番号53)を送信したらログに記録する、というルールを挿入する。
[root@server ~]# iptables -I OUTPUT -p udp --dport 53 -j LOG
ルールを確認する。
[root@server ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 4 packets, 720 bytes)
num pkts bytes target prot opt in out source destination
1 ★0 0 LOG udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 LOG flags 0 level 4
2 0 0 LOG icmp -- * eth0 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
DNS名前解決を行う。
[root@server ~]# dig ntp.nict.jp +short
133.243.238.164
133.243.238.243
133.243.238.163
133.243.238.244
ルールを確認する。DNSクエリを1つ(★)送信したことがわかる。
[root@server ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 20 packets, 3852 bytes)
num pkts bytes target prot opt in out source destination
1 ★1 68 LOG udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 LOG flags 0 level 4
2 0 0 LOG icmp -- * eth0 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
11.5 TCPの制御フラグを指定する方法
11.5.1 SYNパケットをルールに指定する方法
TCPコネクション確立時のSYNパケットをiptablesのルールに指定してみます。
サーバ側の11111は、ポート番号を表します。
client server(11111)
| |
|----------- SYN ------------>| ★このパケットをiptablesのルールに指定する。
|<---------- SYN +ACK --------|
|----------- ACK ------------>|
| |
[root@server ~]# iptables -I INPUT -p tcp --dport 11111 --tcp-flags SYN SYN
[root@server ~]# iptables -nvL INPUT 1
0 0 tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:11111 flags:0x02/0x02
クライアントからサーバにTCPコネクションを確立します。
[root@server ~]# nc -kl 11111
[root@client ~]# nc 192.168.3.20 11111
SYNパケットを1つ(★)受信したことがわかります。
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1 60 tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:11111 flags:0x02/0x02
-以下、略-
11.5.2 FINパケットをルールに指定する方法
TCPコネクション切断時のFINパケットをiptablesのルールに指定してみます。
サーバ側の11111は、ポート番号を表します。
client server(11111)
| |
Ctrl +c | |
|----------- FIN ------------>| ★このパケットをiptablesのルールに指定する。
|<---------- ACK -------------|
| |
|<---------- FIN -------------|
|----------- ACK ------------>|
| |
[root@server ~]# iptables -I INPUT -p tcp --dport 11111 --tcp-flags FIN FIN
[root@server ~]# iptables -nvL INPUT 1
0 0 tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:11111 flags:0x01/0x01
クライアントからサーバにTCPコネクションを確立します。
[root@server ~]# nc -kl 11111
[root@client ~]# nc 192.168.3.20 11111
クライントでCtrl + cを押下して、TCPコネクションを切断します。
[root@client ~]# nc 192.168.3.20 11111
^C
FINパケットを1つ(★)受信したことがわかります。
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
★ 1 52 tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:11111 flags:0x01/0x01
-以下、略-
12 ターゲットとは?
ルールにマッチしたら実行する処理のことです。
LOGターゲットならログへの出力、
DROPターゲットならパケット廃棄といった処理を行います。
12.1 LOGターゲット
ルールに一致したらログに記録します。
[root@router1 ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 2089 packets, 472K bytes)
num pkts bytes target prot opt in out source destination
1 2089 472K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
[root@router1 ~]# iptables -I OUTPUT -p icmp -j LOG
[root@router1 ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 4 packets, 656 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 2137 479K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
[root@router1 ~]# ping -c 1 192.168.0.1
Chain OUTPUT (policy ACCEPT 37 packets, 5768 bytes)
num pkts bytes target prot opt in out source destination
1 ★1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 2170 484K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
ログを確認する。
[root@router1 ~]# journalctl -f
1月 16 20:58:43 router1 kernel: IN= OUT=eth0 SRC=192.168.0.10 DST=192.168.0.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=13633 DF PROTO=ICMP TYPE=8 CODE=0 ID=3608 SEQ=1
[root@router1 ~]# iptables -D OUTPUT 1
12.2 DROPターゲット
ルールに一致したらパケットを廃棄します。
192.168.0.0/24
.10 .20
router1 ---------------------------------------- router2
ping ----- ICMP echo request ------> 廃棄(DROP)
[root@router2 ~]# iptables -I INPUT -p icmp -j DROP
[root@router2 ~]# iptables -nvxL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DROP icmp -- * * 0.0.0.0/0 0.0.0.0/0
2 1947 243571 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
-以下、略-
router2に対して、pingを実行する。
[root@router1 ~]# ping -c 1 router2
ルールを確認する。ICMPパケットが1つ廃棄されたことがわかる。
[root@router2 ~]# iptables -nvxL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 ★1 84 DROP icmp -- * * 0.0.0.0/0 0.0.0.0/0
2 1974 246155 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
-以下、略-
12.3 REJECTターゲット
ルールに一致したらパケットを廃棄します。廃棄した旨をパケットの送信元に通知します。
192.168.0.0/24
.10 .20
router1 ---------------------------------------- router2
ping ----- ICMP echo request ------> 廃棄(REJECT)
<----- ICMP port unreachable ---
[root@router2 ~]# iptables -I INPUT -p icmp -j REJECT
[root@router2 ~]# iptables -nvxL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 REJECT icmp -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
2 2198 271851 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
-以下、略-
router2に対して、pingを実行する。
[root@router1 ~]# ping -c 1 router2
[root@router2 ~]# tcpdump -i eth0 icmp -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:12:53.274415 IP 192.168.0.10 > 192.168.0.20: ICMP echo request, id 3630, seq 1, length 64
21:12:53.274577 IP 192.168.0.20 > 192.168.0.10: ICMP 192.168.0.20 protocol 1 port 51103 unreachable, length 92
[root@router2 ~]# iptables -nvxL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 ★1 84 REJECT icmp -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
2 2255 277443 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
-以下、略-
12.4 RETURNターゲット
ルールに一致したら、それ以上、ルールに一致しているかどうかの処理をしません。
ルールの呼び出し元チェインに復帰します。
ユーザ定義チェイン(TEST)を作成する。
[root@router1 ~]# iptables -N TEST
ユーザ定義チェインにルールを3つ追加する。
[root@router1 ~]# iptables -A TEST -p icmp -j LOG --log-prefix "--LOG1--"
[root@router1 ~]# iptables -A TEST -p icmp -j RETURN
[root@router1 ~]# iptables -A TEST -p icmp -j LOG --log-prefix "--LOG2--"
ユーザ定義チェインのルールを確認する。
[root@router1 ~]# iptables -L TEST
Chain TEST (0 references)
target prot opt source destination
LOG icmp -- anywhere anywhere LOG level warning prefix "--LOG1--"
RETURN icmp -- anywhere anywhere
LOG icmp -- anywhere anywhere LOG level warning prefix "--LOG2--"
ユーザ定義チェインをOUTPUTチェインに挿入する、。
[root@router1 ~]# iptables -I OUTPUT -j TEST
OUTPUTチェインを確認する。ユーザ定義チェインがOUTPUTチェインに挿入されたことがわかる。
[root@router1 ~]# iptables -nvxL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 28 packets, 3744 bytes)
num pkts bytes target prot opt in out source destination
1 28 3744 TEST all -- * * 0.0.0.0/0 0.0.0.0/0
2 245 33352 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
pingを実行する。
[root@router1 ~]# ping -c 1 192.168.0.1
ログを確認する。"--LOG1--"が付いたログだけが表示されていることがわかる。
[root@router1 ~]# journalctl -b0 -f
1月 16 21:46:14 router1 kernel: ★--LOG1--IN= OUT=eth0 SRC=192.168.0.10 DST=192.168.0.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27794 DF PROTO=ICMP TYPE=8 CODE=0 ID=3998 SEQ=1
OUTPUTチェインからユーザ定義チェインを削除する。
[root@router1 ~]# iptables -D OUTPUT 1
ユーザ定義チェインのルールを削除する。
[root@router1 ~]# iptables -D TEST 1
[root@router1 ~]# iptables -D TEST 1
[root@router1 ~]# iptables -D TEST 1
ユーザ定義チェインを削除する。
[root@router1 ~]# iptables -X TEST
12.5 REDIRECTターゲット
宛先ポート番号を変更するターゲットです。
ここでは、受信パケットの宛先ポート番号を10000から20000に変更してみます。
クライアントから10000番ポートへのパケットを送信すると、20000番ポートで
待ち受けているサーバにパケットが届きます。
192.168.0.0/24
.10 .20
router1 ---------------------------------------- router2
宛先ポート番号 10000 -> 20000
[root@router2 ~]# firewall-cmd --add-port=20000/tcp
success
宛先ポート番号を10000から20000に変更する。
[root@router2 ~]# iptables -t nat -A PREROUTING -p tcp --dport 10000 -j REDIRECT --to-port 20000
ルールを確認する。REDIRECターゲット(★)が追加されたことがわかる。
[root@router2 ~]# iptables -t nat -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 149 35250 PREROUTING_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2 149 35250 PREROUTING_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0
3 149 35250 PREROUTING_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 ★tcp dpt:10000 redir ports 20000
サーバ側でncコマンドを実行する。20000番ポートでListenする。
[root@router2 ~]# nc -kl 20000
サーバにTCPコネクションを接続する。宛先ポート番号は10000でTCPコネクションを確立する。
[root@router1 ~]# nc 192.168.0.20 10000
12345
サーバに文字列が送信されたことがわかる。
[root@router2 ~]# nc -kl 20000
12345
PREROUTINGチェインを確認する。
[root@router2 ~]# iptables -t nat -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 1 60 PREROUTING_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2 1 60 PREROUTING_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0
3 1 60 PREROUTING_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
4 ★1 60 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:10000 redir ports 20000
12.6 NFLOGターゲット
チェインの任意の場所に、tcpdumpのフックポイントを設定するためのターゲットです。
ICMPパケットならnflogデバイスにパケットを出力する、というターゲットを挿入する。
[root@router1 ~]# iptables -I OUTPUT -p icmp -j NFLOG
OUTPUTチェインを確認する。NFLOGターゲット(★)が挿入されたことがわかる。
[root@router1 ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 31 packets, 4056 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 NFLOG★ icmp -- * * 0.0.0.0/0 0.0.0.0/0
2 252 30016 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
tcpdumpを実行する。インタフェースはnflogを指定する。
インタフェースがnflogの場合、標準出力にパケットを出力することができないようです。
wオプションでpcapファイルに保存し、WireSharkで確認する必要があります。
[root@router1 ~]# tcpdump -i nflog -w nflog.cap
もう1つターミナルを開く。デフォルトGWに対してpingを実行する。
[root@router1 ~]# ping -c 1 192.168.0.1
ファイルを確認する。このファイルをWireSharkで確認します。
[root@router1 ~]# ls nflog.cap
nflog.cap
OUTPUTチェインを確認する。ICMPパケットが1つ(★)送信されたことがわかる。
[root@router1 ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 166 packets, 23509 bytes)
num pkts bytes target prot opt in out source destination
1 ★1 84 NFLOG icmp -- * * 0.0.0.0/0 0.0.0.0/0
2 387 49469 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
12.7 NOTRACKターゲット
conntrackコマンドの使い方は、ここ(conntrackコマンドの使い方)を参照してください。
12.7.1 ICMPの場合
conntrackを実行する。コネクショントラッキングの情報を表示する。
[root@server strace]# conntrack -E -p icmp
もう1つターミナルを開く。デフォルトGWに対してpingを実行する。
[root@server ~]# ping -c 1 192.168.0.1
コネクショントラッキングの情報が表示されたことがわかる。
[root@server strace]# conntrack -E -p icmp
[NEW] icmp 1 30 src=192.168.0.20 dst=192.168.0.1 type=8 code=0 id=2071 [UNREPLIED] src=192.168.0.1 dst=192.168.0.20 type=0 code=0 id=2071
[UPDATE] icmp 1 29 src=192.168.0.20 dst=192.168.0.1 type=8 code=0 id=2071 src=192.168.0.1 dst=192.168.0.20 type=0 code=0 id=2071
[root@server ~]# iptables -t raw -A OUTPUT -p icmp -j NOTRACK
[root@server ~]# iptables -t raw -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 8 packets, 1440 bytes)
pkts bytes target prot opt in out source destination
0 0 CT icmp -- * * 0.0.0.0/0 0.0.0.0/0 NOTRACK
conntrackを実行する。コネクショントラッキングの情報を表示する。
[root@server strace]# conntrack -E -p icmp
もう1つターミナルを開く。デフォルトGWに対してpingを実行する。
[root@server ~]# ping -c 1 192.168.0.1
ICMPのコネクショントラッキングを追跡しないようにしたので、
今度は、pingを実行しても、トラッキング情報が表示されないことがわかる。
今度は、コネクショントラッキングの情報が表示されないことがわかる。
[root@server strace]# conntrack -E -p icmp
iptablesを実行する。NOTRACKのパケット数が1個(★)に増えたことがわかる。
[root@server ~]# iptables -t raw -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 44 packets, 6624 bytes)
pkts bytes target prot opt in out source destination
★1 84 CT icmp -- * * 0.0.0.0/0 0.0.0.0/0 NOTRACK
12.7.2 UDPの場合
conntrackを実行する。コネクショントラッキングの情報を表示する。
[root@server strace]# conntrack -E -p udp
もう1つターミナルを開く。UDPのコネクショントラッキングを無効にする。
[root@server ~]# iptables -t raw -I OUTPUT -p udp --dport 53 -j NOTRACK
[root@server ~]# iptables -t raw -I PREROUTING -p udp --sport 53 -j NOTRACK
[root@server ~]# iptables -I OUTPUT -p udp --dport 53 -j ACCEPT
[root@server ~]# iptables -I INPUT -p udp --sport 53 -j ACCEPT
digコマンドを実行する。
[root@server ~]# dig ntp.nict.jp +short
133.243.238.244
133.243.238.243
133.243.238.163
133.243.238.164
コネクショントラッキングの情報が表示されないことがわかる。
[root@server strace]# conntrack -E -p udp
12.7.3 TCPの場合
conntrackを実行する。コネクショントラッキングの情報を表示する。
[root@server strace]# conntrack -E -p tcp
もう1つターミナルを開く。TCPのコネクショントラッキングを無効にする。
[root@server ~]# iptables -t raw -I OUTPUT -p tcp --dport 80 -j NOTRACK
[root@server ~]# iptables -t raw -I PREROUTING -p tcp --sport 80 -j NOTRACK
[root@server ~]# iptables -I OUTPUT -p tcp --dport 80 -j ACCEPT
[root@server ~]# iptables -I INPUT -p tcp --sport 80 -j ACCEPT
example.com(TCP 80番ポート)にアクセスする。
[root@server ~]# curl -I http://example.com
コネクショントラッキングの情報が表示されないことがわかる。
[root@server strace]# conntrack -E -p tcp
このとき、googleにアクセスしてみる。宛先ポート番号は443になります。
[root@server ~]# curl -I https://www.google.co.jp
443番ポートはコネクショントラッキング対象なので、今度は、以下のような情報が表示されます。
[root@server strace]# conntrack -E -p tcp
[NEW] tcp 6 120 SYN_SENT src=192.168.0.20 dst=172.217.31.163 sport=46318 dport=443 [UNREPLIED] src=172.217.31.163 dst=192.168.0.20 sport=443 dport=46318
[UPDATE] tcp 6 60 SYN_RECV src=192.168.0.20 dst=172.217.31.163 sport=46318 dport=443 src=172.217.31.163 dst=192.168.0.20 sport=443 dport=46318
[UPDATE] tcp 6 432000 ESTABLISHED src=192.168.0.20 dst=172.217.31.163 sport=46318 dport=443 src=172.217.31.163 dst=192.168.0.20 sport=443 dport=46318 [ASSURED]
-以下、略-
12.8 LOGターゲット
[root@server ~]# iptables -I INPUT -p tcp --sport 80 -j LOG --log-tcp-sequence
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 LOG tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp spt:80 LOG flags 1 level 4
example.comにHTTPでアクセスする。
[root@server ~]# curl -I http://example.com
ログを確認する。TCPのシーケンス番号(★)が表示されていることがわかる。
[root@server ~]# journalctl -b0 -f
2月 01 22:12:43 server kernel: IN=eth0 OUT= MAC=00:0c:29:d4:53:28:00:3a:9d:1e:da:07:08:00 SRC=93.184.216.34 DST=192.168.0.20 LEN=60 TOS=0x00 PREC=0x00 TTL=48 ID=0 DF PROTO=TCP SPT=80 DPT=55006 ★SEQ=755177060 ACK=757724945 WINDOW=65535 RES=0x00 ACK SYN URGP=0
12.9 MARKターゲット
ここでは、受信したICMPパケット対して、PREROUTINGチェインで100番のMARKを付けます。
そして、INPUTチェインでは、100番のパケットに対して、LOGターゲットを実行します。
比較のため、INPUTチェインでは、200番のルールも作成しますが、200番のルールでは、
ICMPパケットはLOGターゲットで処理されないことがわかります。
+-----------------------------+
| |
| INPUT chain |
| | 100番のパケットをLOGターゲットで処理する。
+-----------------------------+
A
|
|
+-----------------------------+
| |
| PREROUTING chain |
| | ICMPパケットに100番を付ける
+-----------------------------+
A
|
|
ICMPパケット
[root@server ~]# iptables -t mangle -I PREROUTING -p icmp -j MARK --set-mark 100
[root@server ~]# iptables -t mangle -nvL PREROUTING
Chain PREROUTING (policy ACCEPT 67 packets, 3952 bytes)
pkts bytes target prot opt in out source destination
0 0 MARK icmp -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0xc8
-以下、略-
[root@server ~]# iptables -I INPUT -m mark --mark 100 -j LOG
[root@server ~]# iptables -I INPUT -m mark --mark 200 -j LOG
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0xc8 LOG flags 0 level 4
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x64 LOG flags 0 level 4
-以下、略-
クライアントからサーバにpingを実行する。
[root@client ~]# ping -c 1 192.168.3.10
MARKが100に設定されたICMPパケットをINPUTチェインで処理した際に、
パケットの受信数が1になっていることがわかる。
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
★ 1 84 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0xc8 LOG flags 0 level 4
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x64 LOG flags 0 level 4
-以下、略-
12.10 TCPMSSターゲット
TCP SYNパケットのMSS(Maximum Segment Size)値を変更することができます。
MSSはMTUからTCP/IPヘッダサイズを引いた値になります。
通常、Ethernet環境ではMTUは1500(byte)です。
また、TCP/IPの各々のヘッダサイズは20(byte)となるので、MSSは1460(byte)になります。
しかし、最近ではTCP TimeStampオプションが付くことが一般的です。
TCP TimeStampオプションのサイズは12(byte)です。
したがって、MSSは1448(byte)になることが多い(*)
ようです。
(*) MSSはMTUやTCPコネクションの結果によって変化する、ということです。
ここで、TCPMSSの値を1000に変更してみます。
インタフェース名を間違えないようにしてください。私の環境はeth0ではなくenp0s3という名前です。
[root@client ~]# iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o enp0s3 -j TCPMSS --set-mss 1000
設定したTCPMSSの値を確認してみます。TCPMSSが1000になったことがわかります。
[root@client ~]# iptables -t mangle -nvL POSTROUTING --line-numbers
Chain POSTROUTING (policy ACCEPT 13 packets, 1276 bytes)
num pkts bytes target prot opt in out source destination
1 487 44991 POSTROUTING_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 TCPMSS tcp -- * enp0s3 0.0.0.0/0 0.0.0.0/0 tcp flags:0x06/0x02 TCPMSS set 1000
次に、クライアントからサーバにTCPコネクションを確立してみます。
そして、TCPコネクション確立時のSYNパケットの中身を確認してみます。
なお、ncコマンドの使い方は、ここ(ncコマンドの使い方)、
tcpdumpは、ここ(tcpdumpの使い方)を参照してください。
サーバ側は、TCPの11111番ポートでListenします。
[root@server ~]# nc -klv 11111
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::11111
Ncat: Listening on 0.0.0.0:11111
tcpdumpは、送信先/送信元のポート番号が11111番だけのパケットをキャプチャします。
[root@server ~]# tcpdump -i enp0s3 port 11111
クライアントからサーバの11111番ポートにTCPコネクション確立を試みます。
[root@client ~]# nc server 11111
TCPコネクション確立時のtcpdumpを確認すると、
SYNパケットのMSSオプションの値が1000になっていることがわかります。
なお、サーバからクライアントに通知するMSSの値は1460のままです。
[root@server ~]# tcpdump -i enp0s3 port 11111
-snip-
16:05:35.245007 IP client.53476 > server.vce: Flags [S], seq 3816904446, win 29200, options [mss 1000,sackOK,TS val 3099227 ecr 0,nop,wscale 7], length 0
16:05:35.245066 IP server.vce > client.53476: Flags [S.], seq 1164680373, ack 3816904447, win 28960, options [mss 1460,sackOK,TS val 3107112 ecr 3099227,nop,wscale 7], length 0
16:05:35.245481 IP client.53476 > server.vce: Flags [.], ack 1, win 229, options [nop,nop,TS val 3099229 ecr 3107112], length 0
なお、TCPコネクションが確立されると、サーバ、クライアントともにTCP TimeStampオプションを
使っていることがわかるので、サーバはクライアントのMSSを988(byte)と認識します。
また、クライアントはサーバのMSSを1448(byte)と認識します。
上記結果は、サーバでNICのsegmentation offload機能を無効にすることで確認できます。
無効化しないと、TCP層でパケットの分割が行われないまま
tcpdumpでパケットをキャプチャするため、パケットサイズが分割前のサイズになります。
つまり、2000(byte)と表示されてしまう。
(注) ethtoolコマンドの大文字K、小文字kを間違えないように
[root@server ~]# ethtool -K enp0s3 tso off gso off
[root@server ~]# ethtool -k enp0s3 |grep -e tcp -e generic-segmentation
tcp-segmentation-offload: off
tx-tcp-segmentation: off
tx-tcp-ecn-segmentation: off [fixed]
tx-tcp6-segmentation: off [fixed]
tx-tcp-mangleid-segmentation: off
generic-segmentation-offload: off
サーバからクライアントに2000(byte)のデータを送信します。
2000(byte)のパケットが、988,988,24のサイズに分割されていることがわかります。
[root@server ~]# tcpdump -i enp0s3 port 11111
-snip-
16:57:09.345982 IP server.vce > client.53490: Flags [.], seq 4001:4989, ack 1, win 227, options [nop,nop,TS val 6201213 ecr 6133145], length 988
16:57:09.345988 IP server.vce > client.53490: Flags [.], seq 4989:5977, ack 1, win 227, options [nop,nop,TS val 6201213 ecr 6133145], length 988
16:57:09.345990 IP server.vce > client.53490: Flags [P.], seq 5977:6001, ack 1, win 227, options [nop,nop,TS val 6201213 ecr 6133145], length 24
16:57:09.346372 IP client.53490 > server.vce: Flags [.], ack 6001, win 447, options [nop,nop,TS val 6193329 ecr 6201213], length 0
ちなみに、offload機能を有効にしてみます。
(注) ethtoolコマンドの大文字K、小文字kを間違えないように
[root@server ~]# ethtool -K enp0s3 tso on gso on
[root@server ~]# ethtool -k enp0s3 |grep -e tcp -e generic-segmentation
tcp-segmentation-offload: on
tx-tcp-segmentation: on
tx-tcp-ecn-segmentation: off [fixed]
tx-tcp6-segmentation: off [fixed]
tx-tcp-mangleid-segmentation: on
generic-segmentation-offload: on
サーバからクライアントに2000(byte)のデータを送信します。
パケットのサイズが2000(byte)と表示されています。
つまり、パケットがTCP層で分割されていないことがわかります。
[root@server ~]# tcpdump -i enp0s3 port 11111
-snip-
17:12:33.167523 IP server.vce > client.53490: Flags [P.], seq 122:2122, ack 1, win 227, options [nop,nop,TS val 7125034 ecr 7108110], length 2000
17:12:33.167868 IP client.53490 > server.vce: Flags [.], ack 2122, win 479, options [nop,nop,TS val 7117151 ecr 7125034], length 0
13 gotoの使い方
gotoはチェインに移動するするときに使います。
ユーザ定義チェイン(TEST1,TEST2,TEST3)を作成する。
[root@server ~]# iptables -N TEST1
[root@server ~]# iptables -N TEST2
[root@server ~]# iptables -N TEST3
ユーザ定義チェインにルールを登録する。
[root@server ~]# iptables -A TEST1 -p icmp --goto TEST3
[root@server ~]# iptables -A TEST1 -p icmp -j LOG
[root@server ~]# iptables -A TEST2 -p icmp -j LOG
[root@server ~]# iptables -A TEST3 -p icmp -j LOG
OUTPUTチェインを確認する。
[root@server ~]# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 9 packets, 1912 bytes)
pkts bytes target prot opt in out source destination
9 1912 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 TEST1 icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 TEST2 icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 TEST3 icmp -- * * 0.0.0.0/0 0.0.0.0/0
pingを実行する。
[root@server ~]# ping -c 1 192.168.0.1
ユーザ定義チェイン(TEST1)のカウンタを確認する。
[root@server ~]# iptables -nvL TEST1
Chain TEST1 (1 references)
pkts bytes target prot opt in out source destination
1 84 TEST3 icmp -- * * 0.0.0.0/0 0.0.0.0/0 [goto]
0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
ユーザ定義チェイン(TEST2)のカウンタを確認する。
[root@server ~]# iptables -nvL TEST2
Chain TEST2 (1 references)
pkts bytes target prot opt in out source destination
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
ユーザ定義チェイン(TEST3)のカウンタを確認する。
[root@server ~]# iptables -nvL TEST3
Chain TEST3 (2 references)
pkts bytes target prot opt in out source destination
2 168 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
[root@server ~]# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 52 packets, 8412 bytes)
pkts bytes target prot opt in out source destination
76 11820 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
1 84 TEST1 icmp -- * * 0.0.0.0/0 0.0.0.0/0
1 84 TEST2 icmp -- * * 0.0.0.0/0 0.0.0.0/0
1 84 TEST3 icmp -- * * 0.0.0.0/0 0.0.0.0/0
14 拡張マッチングモジュールの使い方
拡張マッチングモジュールの使い方は、ここ(iptables-extensionsの使い方)に移動しました。