iptables-extensionsの使い方

以下に移行予定です。
https://hana-shin.hatenablog.com/entry/2022/12/27/213154

#1 iptables-extensionsとは?
iptablesで利用できる、拡張パケットマッチングモジュールのことです。
マッチングモジュールは、パケットが条件(サイズ等)に一致したかどうかを判定するときに使います。
マッチングモジュールには、limit,mac,conntrack等、様々なものが存在します。

ここでは、マッチングモジュールの使い方について説明します。
なお、iptablesの使い方は、[ここ(iptablesの使い方)](https://qiita.com/hana_shin/items/956dfaca4539ba257c16)を参照してください。

#2 環境
VMware Workstation 14 Player上の仮想マシンを使いました。
サーバ(server)側でiptables-extensionsを使用します。

IPアドレス、MACアドレスは以下のとおりです。

```console:ネットワーク構成
                     192.168.3.0/24
      .50                                  .20
client ------------------------------------- server 
00:0c:29:a8:bf:66                          00:0c:29:f0:6e:a2
````

仮想マシンのOS版数は以下のとりです。

```console:OS版数
[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

[root@server ~]# uname -r
3.10.0-693.el7.x86_64
```

iptablesの版数は以下のとおりです。

```console:iptablesの版数
[root@server ~]# iptables -V
iptables v1.4.21
```

iptables-extensionsの使い方を簡潔に説明するため、ここでは、firewaldを停止しておきます。

```console:firewalldの停止方法
[root@server ~]# systemctl stop firewalld.service
[root@server ~]# systemctl is-active firewalld.service
inactive
```


#3 manの参照方法

```
[root@server ~]# man iptables-extensions
iptables-extensions(8)                             iptables 1.4.21                             iptables-extensions(8)

NAME
       iptables-extensions ― list of extensions in the standard iptables distribution
(以下、略)
```

#4 使い方
たとえば、INPUTチェインに対してマッチングモジュールを使う場合、
マッチングモジュールの名前とオプションを以下のように指定して使います。
`iptables -A INPUT -m <モジュール名> <モジュールのオプション>  <ターゲット>`


#5 macモジュールの使い方
送信元MACアドレスにもとづいて、パケットをフィルタリングするモジュールです。
PREROUTING,FORWARD,INPUTの3つのチェインに対して使うことができます。
ここでは、送信元MACアドレスが`00:0c:29:a8:bf:66`のパケットを破棄するルールを設定してみます。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -m mac --mac-source 00:0c:29:a8:bf:66 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 50 packets, 2900 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            MAC 00:0C:29:A8:BF:66
```

クライアントからサーバにpingを実行します。パケットが破棄(★)されていることがわかります。

```console:実行結果
[root@client ~]# ping -c 1 192.168.3.20
PING 192.168.3.20 (192.168.3.20) 56(84) bytes of data.

--- 192.168.3.20 ping statistics ---
1 packets transmitted, 0 received, ★100% packet loss, time 0ms
```

iptablesの統計情報を確認してみます。ICMPパケットが1つ破棄されていることがわかります。

```console:iptables統計情報の確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 86 packets, 5884 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        1    84 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            MAC 00:0C:29:A8:BF:66
```

```console:後始末（ルールの削除）
削除するルールの番号を確認する。削除するルールは1番であることがわかる。
[root@server ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    DROP       all  --  anywhere             anywhere             MAC 00:0C:29:A8:BF:66

1番のルールを削除する。
[root@server ~]# iptables -D INPUT 1

ルールを確認する。1番のルールが削除できたことがわかる。
[root@server ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
```

#6 commentモジュールの使い方
iptablesのルールにコメントをつけるモジュールです。

```console:コメントの設定
[root@server ~]# iptables -A INPUT -p icmp -m comment --comment "This is test comment" -j ACCEPT
```

```console:コメントの確認
[root@server ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     icmp --  anywhere             anywhere             /* This is test comment */
```

```console:あと始末(ルールの削除)
削除するルールの番号を確認する。削除するルールは1番であることがわかる。
[root@server ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     icmp --  anywhere             anywhere             /* This is test comment */

1番のルールを削除する。
[root@server ~]# iptables -D INPUT 1

ルールを確認する。1番のルールが削除できたことがわかる。
[root@server ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
```


#7 icmpモジュールの使い方
ICMPパケットのタイプ／コードにもとづいて、パケットをフィルタリングするモジュールです。

##7.1 ICMP echoパケットの指定方法(type=8)

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 50 packets, 2900 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            icmptype 8
```

クライアントからサーバにpingを実行します。パケットが破棄(★)されていることがわかります。

```console:実行結果
[root@client ~]# ping -c 1 server
PING server (192.168.3.20) 56(84) bytes of data.

--- server ping statistics ---
1 packets transmitted, 0 received, ★100% packet loss, time 0ms
```

iptablesの統計情報を確認してみます。ICMPパケットが1つ破棄されていることがわかります。

```console:iptables統計情報の確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 73 packets, 4316 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            icmptype 8
```



##7.2 ICMP network unreachableパケットの指定方法(type=3,code=0)

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p icmp -m icmp --icmp-type 3/0 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 8 packets, 512 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            icmptype 3 code 0
```






#8 lengthモジュールの使い方
IPパケット長にもとづいて、パケットをフィルタリングするモジュールです。

##8.1 パケットサイズを指定する方法
パケット長が28バイトのICMPパケットを廃棄してみます。
28バイトのパケットは、20バイトのIPヘッダ、8バイトのICMPヘッダだけのパケットになります。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p icmp -m length --length 28 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 8 packets, 512 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            length 28
```

クライアントからサーバにping(28バイト)を実行します。
パケットが破棄(★)されていることがわかります。

```console:実行結果(パケット長が28バイトのとき）
[root@client ~]# ping -c 1 -s 0 server
PING server (192.168.3.20) 0(28) bytes of data.

--- server ping statistics ---
1 packets transmitted, 0 received, ★100% packet loss, time 0ms
```

次に、クライアントからサーバにping(29バイト)を実行します。
パケットは破棄されていないことがわかります(★)。

```console:実行結果(パケット長が29バイトのとき）
[root@client ~]# ping -c 1 -s 1 server
PING server (192.168.3.20) 1(29) bytes of data.
9 bytes from server (192.168.3.20): icmp_seq=1 ttl=64

--- server ping statistics ---
1 packets transmitted, 1 received, ★0% packet loss, time 0ms
```




##8.2 パケットサイズの範囲を指定する方法
パケット長が30バイト以上、31バイト以下のICMPパケットを廃棄してみます。
また、他のパケット長のICMPパケットは破棄されないことを確認します。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p icmp -m length --length 30:31 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 49 packets, 2860 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            length 30:31
```

クライアントからサーバにping(30バイト)を実行します。
パケットが破棄(★)されていることがわかります。

```console:実行結果(パケット長が30バイトのとき）
[root@client ~]# ping -c 1 -s 2 server
PING server (192.168.3.20) 2(30) bytes of data.

--- server ping statistics ---
1 packets transmitted, 0 received, ★100% packet loss, time 0ms
```

クライアントからサーバにping(31バイト)を実行します。
パケットが破棄(★)されていることがわかります。

```console:実行結果(パケット長が31バイトのとき）
[root@client ~]# ping -c 1 -s 3 server
PING server (192.168.3.20) 3(31) bytes of data.

--- server ping statistics ---
1 packets transmitted, 0 received, ★100% packet loss, time 0ms
```

次に、クライアントからサーバにping(28バイト)を実行します。
パケットは破棄されていないことがわかります(★)。

```console:実行結果(パケット長が28バイトのとき）
[root@client ~]# ping -c 1 -s 0 server
PING server (192.168.3.20) 0(28) bytes of data.
8 bytes from server (192.168.3.20): icmp_seq=1 ttl=64

--- server ping statistics ---
1 packets transmitted, 1 received, ★0% packet loss, time 0ms
```

次に、クライアントからサーバにping(29バイト)を実行します。
パケットは破棄されていないことがわかります(★)。

```console:実行結果(パケット長が29バイトのとき）
[root@client ~]# ping -c 1 -s 1 server
PING server (192.168.3.20) 1(29) bytes of data.
9 bytes from server (192.168.3.20): icmp_seq=1 ttl=64

--- server ping statistics ---
1 packets transmitted, 1 received, ★0% packet loss, time 0ms
```

##8.3 パケットサイズの範囲(以上、以下)を指定する方法
パケット長が31バイト以下のICMPパケットを廃棄してみます。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p icmp -m length --length :31 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 64 packets, 3748 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            length 0:31
```

クライアントからサーバにping(31バイト)を実行します。
パケットが破棄(★)されていることがわかります。

```console:実行結果(パケット長が31バイトのとき）
[root@client ~]# ping -c 1 -s 3 server
PING server (192.168.3.20) 3(31) bytes of data.

--- server ping statistics ---
1 packets transmitted, 0 received, ★100% packet loss, time 0ms
```

クライアントからサーバにping(32バイト)を実行します。
パケットは破棄されていないことがわかります(★)。

```console:実行結果(パケット長が32バイトのとき）
[root@client ~]# ping -c 1 -s 4 server
PING server (192.168.3.20) 4(32) bytes of data.
12 bytes from server (192.168.3.20): icmp_seq=1 ttl=64

--- server ping statistics ---
1 packets transmitted, 1 received, ★0% packet loss, time 0ms
```



#9 multiportモジュールの使い方
ポート番号にもとづいて、パケットをフィルタリングするモジュールです。


##9.1 特定のポート番号を指定する方法
TCP/11111番ポート宛のパケットは破棄する、というルールを設定してみます。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p tcp -m multiport --dports 11111 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 50 packets, 2900 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 11111
```

TCPの11111番ポートでListenします。
なお、ncコマンドの使い方は、[ここ(ncコマンドの使い方)](https://qiita.com/hana_shin/items/97e6c03ac5e5ed67ce38)を参照してください。

```console:実行結果(サーバ側)
[root@server ~]# nc -kl 11111
```

クライアントから11111番ポートにアクセスします

```console:実行結果(クライアント側)
[root@client ~]# nc -w 1 server 11111
Ncat: Connection timed out.
```

```console:iptablesの統計情報確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 76 packets, 4524 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        1    60 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 11111
```

次に、TCPの22222番ポートでListenします。

```console:実行結果(サーバ側)
[root@server ~]# nc -kl 22222
```

クライアントから22222番ポートにアクセスします。"Connection timed out."は発生しません。
"test"と入力すると、サーバが"test"をエコーバックしていることがわかります。

```console:実行結果(クライアント側)
[root@client ~]# nc -w 1 server 22222
test
```




##9.2 ポート番号の範囲を指定する方法
TCP/11111～11115宛のパケットは破棄する、というルールを設定してみます。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p tcp -m multiport --dports 11111:11115 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 34 packets, 1972 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 11111:11115
```

##9.3 ポート番号を複数指定する方法
TCP/80番ポート、および11111～11115宛のパケットは破棄する、というルールを設定してみます。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p tcp -m multiport --dports 80,11111:11115 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 8 packets, 512 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 80,11111:11115
```


#10 timeモジュールの使い方
日時にもとづいて、パケットをフィルタリングするモジュールです。
なお、timeモジュールはUTCしか使えないようです。UTCは以下のようにして確認できます。

```console:UTC時刻の確認方法
[root@server ~]# date;date -u
2018年 11月 21日 水曜日 22:27:20 JST
2018年 11月 21日 水曜日 13:27:20 UTC
```

##10.1 日時を指定する方法(--datestart,--datestop)
下記時間帯に受信したICMPは破棄する、とういうルールを設定してみます。
`2018/11/21 13:00:00 ～ 2018/11/21 14:00:00`

```console:時刻の確認
[root@server ~]# date -u
2018年 11月 21日 水曜日 13:45:57 UTC
```

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p icmp -m time --datestart 2018-11-21T13:00:00 --datestop 2018-11-21T14:00:00 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 35 packets, 2048 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            TIME starting from 2018-11-21 13:00:00 until date 2018-11-21 14:00:00 UTC
```

クライアントからサーバにpingを実行します。
パケットが破棄(★)されていることがわかります。

```console:実行結果
[root@client ~]# ping -w 1 -c 1 server
PING server (192.168.3.20) 56(84) bytes of data.

--- server ping statistics ---
2 packets transmitted, 0 received, ★100% packet loss, time 999ms
```

```console:実行結果(iptablesの統計情報確認)
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 11 packets, 668 bytes)
 pkts bytes target     prot opt in     out     source               destination
    1    84 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            TIME starting from 2018-11-21 13:00:00 until date 2018-11-21 14:00:00 UTC
```

##10.2 時刻を指定する方法(--timestart,--timestop)
下記時間帯に受信したICMPは破棄する、とういうルールを設定してみます。
`14:00:00 ～ 15:00:00`

```console:時刻の確認
[root@server ~]# date -u
2018年 11月 21日 水曜日 13:52:54 UTC
```

現在時刻は13:52なので、パケットは廃棄されない、というのが期待値になります。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p icmp -m time --timestart 14:00:00 --timestop 15:00:00 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 31 packets, 1816 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            TIME from 14:00:00 to 15:00:00 UTC
```

クライアントからサーバにpingを実行します。
パケットが破棄されていないことがわかります(★)。

```console:実行結果
[root@client ~]# ping -w 1 -c 1 server
PING server (192.168.3.20) 56(84) bytes of data.
64 bytes from server (192.168.3.20): icmp_seq=1 ttl=64 time=0.401 ms

--- server ping statistics ---
1 packets transmitted, 1 received, ★0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.401/0.401/0.401/0.000 ms
```



#11 setモジュールの使い方
ipsetコマンドで作成したセットにもとづいて、パケットをフィルタリングするモジュールです。
なお、ipsetコマンドの使い方は、[ここ(ipsetコマンドの使い方)](https://qiita.com/hana_shin/items/6b4756d85ced525c34ba)を参照してください。

```console:セットの作成
[root@server ~]# ipset n ng_host hash:ip
[root@server ~]# ipset a ng_host 192.168.3.50
[root@server ~]# ipset l ng_host
Name: ng_host
Type: hash:ip
Revision: 1
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 16544
References: 1
Members:
192.168.3.50
```

パケット送信元(src)が192.168.3.50であるパケットを破棄する、というルールを設定します。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -m set --match-set ng_host src -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 38 packets, 2240 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set ng_host src
```

クライアントからサーバにpingを実行します。
パケットが破棄(★)されていることがわかります。

```console:実行結果
[root@client ~]# ping -w 1 -c 1 server
PING server (192.168.3.20) 56(84) bytes of data.

--- server ping statistics ---
2 packets transmitted, 0 received, ★100% packet loss, time 999ms
```


#12 connlimitモジュールの使い方
同時接続数を制御するためのモジュールです。

クライアントから11111番ポートへの接続数が2を超える場合、接続を拒否する設定をする。
なお、下記で使用するncコマンドは、[ここ(ncコマンドの使い方)](https://qiita.com/hana_shin/items/97e6c03ac5e5ed67ce38)を参照してください。

```console:ルールの設定
[root@server ~]# iptables -A INPUT -p tcp --dport 11111 -m connlimit --connlimit-above 2 -j DROP
```

```console:ルールの確認
[root@server ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 112 packets, 6524 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:11111 #conn src/32 > 2
```
サーバ側は11111番ポートでListenする。

```console:サーバ側
[root@server ~]# nc -kl 11111
```

```console:クライアント側(1つ目)
[root@client ~]# nc server 11111
```

```console:クライアント側(2つ目)
[root@client ~]# nc server 11111
```

```console:クライアント側(3つ目)
[root@client ~]# nc server 11111
Ncat: Connection timed out.
```



#Z 参考情報
[iptables-extensions](https://linuxjm.osdn.jp/html/iptables/man8/iptables-extensions.8.html)