Help us understand the problem. What is going on with this article?

iptablesの使い方

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
hostsファイル
[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チェインのルールの表示方法

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チェインのルールの表示方法

OUTPUTチェインの表示
[root@server ~]# iptables -L OUTPUT
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
OUTPUT_direct  all  --  anywhere             anywhere

4.3 FORWARDチェインのルールの表示方法

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オプションを付けてルールを表示します。

PREROUTINGチェインの表示
[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オプションを付けてルールを表示します。

POSTROUTINGチェインの表示
[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オプションを付けてルールを表示します。

RAWチェインの表示
[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 ------------>|
        |                             |
サーバ側(iptablesのルール設定)
[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コネクションを確立します。

TCPコネクション確立
[root@server ~]# nc -kl 11111
[root@client ~]# nc 192.168.3.20 11111

SYNパケットを1つ(★)受信したことがわかります。

iptablesの統計情報の確認
[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 ------------>|
        |                             |
サーバ側(iptablesのルール設定)
[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コネクションを確立します。

TCPコネクション確立
[root@server ~]# nc -kl 11111
[root@client ~]# nc 192.168.3.20 11111

クライントでCtrl + cを押下して、TCPコネクションを切断します。

クライアント側(TCPコネクション切断)
[root@client ~]# nc 192.168.3.20 11111
^C

FINパケットを1つ(★)受信したことがわかります。

iptablesの統計情報の確認
[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

nflog.png

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ターゲット

TCPのシーケンス番号をログに記録する方法
[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パケット
PREROUTINGチェインの設定内容
[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
-以下、略-
INPUTチェインの設定内容
[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を実行する。

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という名前です。

TCPMSSの設定
[root@client ~]# iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o enp0s3 -j TCPMSS --set-mss 1000

設定したTCPMSSの値を確認してみます。TCPMSSが1000になったことがわかります。

TCPMSSの設定確認
[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します。

サーバ側(ncコマンド起動)
[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番だけのパケットをキャプチャします。

サーバ側(tcpdump起動)
[root@server ~]# tcpdump -i enp0s3 port 11111

クライアントからサーバの11111番ポートにTCPコネクション確立を試みます。

クライアント側
[root@client ~]# nc server 11111

TCPコネクション確立時のtcpdumpを確認すると、
SYNパケットのMSSオプションの値が1000になっていることがわかります。
なお、サーバからクライアントに通知するMSSの値は1460のままです。

SYNパケットのMSS確認
[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を間違えないように

サーバ側NICのoffload機能無効化
[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を間違えないように

offload機能の有効化
[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の使い方)に移動しました。

X 参考情報

PowerDNS Recursor performance

hana_shin
写真は淡路島SAから明石海峡大橋を撮影したものです('19夏撮影)。'20年夏も3年連続で四国、大阪に行く予定!毎回車でいってます。今から楽しみぃ~。次は、四国の四万十川に行ってみたいけど、ちょっと遠いかな?最近はネットワークに力を入れてます。保有国家資格:ネットワークスペシャリスト、オンライン情報処理技術者。メールは hana.shin.2018@gmail.com まで。
https://hana-shin.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした