hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

ipsetコマンドの使い方



1 ipsetコマンドとは?

ipsetコマンドは、IPアドレスやポート番号などをまとめて管理するためのツールです。ipsetを使用することで、これらの要素をセットとしてまとめることができます。作成したセットは、iptablesのsetモジュールで使用することが可能です。これにより、iptablesコマンドで個々のIPアドレスを1つずつ登録するのではなく、セットを使用して一括登録することができるようになります。

2 検証環境

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

[root@server ~]# cat /etc/redhat-release
AlmaLinux release 9.1 (Lime Lynx)

カーネル版数は以下のとおりです。

[root@server ~]# uname -r
5.14.0-162.6.1.el9_1.x86_64

ipsetコマンドの版数は以下のとおりです。

[root@server ~]# ipset -v
ipset v7.11, protocol version: 7

3 オプション一覧

[root@server ~]# ipset help
ipset v7.11

Usage: ipset [options] COMMAND

Commands:
create SETNAME TYPENAME [type-specific-options]
        Create a new set
add SETNAME ENTRY
        Add entry to the named set
del SETNAME ENTRY
        Delete entry from the named set
test SETNAME ENTRY
        Test entry in the named set
destroy [SETNAME]
        Destroy a named set or all sets
list [SETNAME]
        List the entries of a named set or all sets
save [SETNAME]
        Save the named set or all sets to stdout
restore
        Restore a saved state
flush [SETNAME]
        Flush a named set or all sets
rename FROM-SETNAME TO-SETNAME
        Rename two sets
swap FROM-SETNAME TO-SETNAME
        Swap the contect of two existing sets
help [TYPENAME]
        Print help, and settype specific help
version
        Print version information
quit
        Quit interactive mode

Options:
-o plain|save|xml
       Specify output mode for listing sets.
       Default value for "list" command is mode "plain"
       and for "save" command is mode "save".
-s
        Print elements sorted (if supported by the set type).
-q
        Suppress any notice or warning message.
-r
        Try to resolve IP addresses in the output (slow!)
-!
        Ignore errors when creating or adding sets or
        elements that do exist or when deleting elements
        that don't exist.
-n
        When listing, just list setnames from the kernel.

-t
        When listing, list setnames and set headers
        from kernel only.
-f
        Read from the given file instead of standard
        input (restore) or write to given file instead
        of standard output (list/save).

Supported set types:
    list:set            3       skbinfo support
    list:set            2       comment support
    list:set            1       counters support
    list:set            0       Initial revision
-snip-

4 セットの作成、削除方法

セットはメソッドとデータタイプを指定して作成します。書式は以下のとおりです。

TYPENAME := method:datatype[,datatype[,datatype]]

・method:list,hash,bitmapを指定できます。
・datatype:ip,net,mac,port,ifaceを指定できます。

メソッドの各意味を以下のとおりです。

メソッド 意味
list セットをリスト形式で格納します
hash ハッシュテーブルを使用してセットを格納します。ハッシュメソッドは、IPアドレスやネットワークを格納するときに使用します
bitmap ビットマップを使用してセットを格納します。ポート番号やポート範囲を格納するときに使用します

4.1 セットを作成する方法(nまたはcreate)

名前がtest1、タイプがhash:ipのセットを作成してみます。

[root@server ~]# ipset n test1 hash:ip

作成したセットを確認します。test1という名前のセットが作成できたことがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xcbb84ee8
Size in memory: 216
References: 0
Number of entries: 0
Members:

4.2 セットを削除する方法(xまたはdel)

セットの一覧を確認します。test1という名前のセットが存在することがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xcbb84ee8
Size in memory: 216
References: 0
Number of entries: 0
Members:

test1という名前のセットを削除します。

[root@server ~]# ipset x test1

セットの一覧を確認します。test1という名前のセットが削除されたことがわかります。

[root@server ~]# ipset l
[root@server ~]#

4.3 セットを一括削除する方法(xまたはdel)

事前準備として、test1,test2という名前のセットを2つ作成しておきます。

[root@server ~]# ipset n test1 hash:ip
[root@server ~]# ipset n test2 hash:ip

セットの一覧を確認します。test1,test2という名前のセットが作成されたことがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xa5a2e8c8
Size in memory: 216
References: 0
Number of entries: 0
Members:

Name: test2
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x0dad6e43
Size in memory: 216
References: 0
Number of entries: 0
Members:

2つのセットを一括で削除します。

[root@server ~]# ipset x

セットの一覧を確認します。test1,test2という名前のセットが削除されたことがわかります。

[root@server ~]# ipset l
[root@server ~]#

5 セットの名前を変更する方法(eまたはrename)

事前準備として、test1という名前のセットを作成しておきます。

[root@server ~]# ipset n test1 hash:ip

作成したセットを確認します。test1という名前のセットが作成できたことがわかります。

[root@server ~]# ipset l -n
test1

test1という名前のセットをtest2に変更します。

[root@server ~]# ipset e test1 test2

セットの一覧を確認します。test1という名前のセットがtest2に変更されたことがわかります。

[root@server ~]# ipset l -n
test2

あと始末をします。

[root@server ~]# ipset x

6 セットにエントリを追加/削除する方法

6.1 エントリを追加する方法(aまたはadd)

事前準備として、名前がtest1、タイプがhash:ipのセットを作成してみます。

[root@server ~]# ipset n test1 hash:ip

作成したセットを確認します。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 120
References: 0
Number of entries: 0
Members:
[root@server ~]#

セットにIPアドレスのエントリを2つ追加します。

[root@server ~]# ipset add test1 192.168.10.10
[root@server ~]# ipset add test1 192.168.10.20

セットを確認します。追加したエントリが2つ作成されたことがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 216
References: 0
Number of entries: 2
Members:
192.168.10.20
192.168.10.10

6.2 エントリを削除する方法(dまたはdel)

セットからエントリを1つ削除します。

[root@server ~]# ipset d test1 192.168.10.10

セットを確認します。エントリが1つ削除されたことがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 168
References: 0
Number of entries: 1
Members:
192.168.10.20

セットからもう1つエントリを削除します。

[root@server ~]# ipset d test1 192.168.10.20

セットの中身を確認します。エントリが全て削除されたことがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 120
References: 0
Number of entries: 0
Members:

6.3 エントリを一括削除する方法(fまたはflush)

セットを確認します。エントリが2つ存在することがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 216
References: 0
Number of entries: 2
Members:
192.168.10.20
192.168.10.10

エントリを一括で削除します。

[root@server ~]# ipset f test1

セットの中身を確認します。エントリが全て削除されたことがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 120
References: 0
Number of entries: 0
Members:

7 セーブ、リストア方法

セットの内容をファイルに保存したり、ファイルに保存したセットをリストアすることができます。

7.1 セットの内容をファイルに保存する方法(save)

テスト用のセットを作成します。

[root@server ~]# ipset n test1 hash:ip
[root@server ~]# ipset a test1 192.168.10.1

作成したセットをファイルに保存します。

[root@server ~]# ipset save > ip_set.txt

ファイルに保存したセットの内容を確認します。

[root@server ~]# cat ip_set.txt
create test1 hash:ip family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x1266b74c
add test1 192.168.10.1

7.2 リストアする方法(restore)

セットの一覧を確認します。セットが登録されていないことを確認します。

[root@server ~]# ipset l
[root@server ~]#

ファイルに保存されているセットを確認します。

[root@server ~]# cat ip_set.txt
create test1 hash:ip family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x1266b74c
add test1 192.168.10.1

ファイルに保存されているセットをリストアします。

[root@server ~]# ipset restore < ip_set.txt

セットを確認します。ファイルに保存されていたセットがリストアされたことがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0x1266b74c
Size in memory: 256
References: 0
Number of entries: 1
Members:
192.168.10.1

8 タイムアウトの設定方法(timeout)

エントリにタイムアウトを設定することができます。指定した時間を経過すると、エントリが削除されます。ここでは、エントリに10秒のタイムアウトを設定してみます。10秒経過すると、エントリが削除されることを確認してみます。

[root@server ~]# ipset n test1 hash:ip timeout 10

セット(test1)にエントリ(192.168.10.10)を追加します。

[root@server ~]# ipset a test1 192.168.10.10

セットに追加されたエントリを確認します。エントリの削除まで4秒であることがわかります。

[root@server ~]# ipset l test1
Name: test1
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 timeout 10 bucketsize 12 initval 0x728c1f29
Size in memory: 280
References: 0
Number of entries: 1
Members:
192.168.10.10 timeout 4

セットに追加されたエントリを確認します。エントリが削除されたことがわかります。

[root@server ~]# ipset l test1
Name: test1
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 timeout 10 bucketsize 12 initval 0x728c1f29
Size in memory: 280
References: 0
Number of entries: 0
Members:

9 カウンタの設定方法(counters)

カウンタ付のセットを作成します。

[root@server ~]# ipset n test1 hash:ip counters

セットにエントリを追加します。

[root@server ~]# ipset a test1 192.168.122.213

セットの内容を表示します。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 counters bucketsize 12 initval 0x1707fb58
Size in memory: 296
References: 0
Number of entries: 1
Members:
192.168.122.213 packets 0 bytes 0

セットをINPUTチェインに追加します。

[root@server ~]# iptables -A INPUT -m set --match-set test1 src -p icmp -j LOG

INPUTチェインのルールを確認します。test1セットがINPUTチェインに追加されたことがわかります。

[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 --  *      *       0.0.0.0/0            0.0.0.0/0            match-set test1 src LOG flags 0 level 4

クライアントからサーバに対してpingコマンドを1回実行します。なお、pingコマンドの使い方は、pingコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@client~]# ping -c 1 192.168.122.16

セットの内容を確認します。192.168.122.213から84バイトのパケットを1つ受信したことがわかります。

[root@server ~]# ipset l
Name: test1
Type: hash:ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 counters bucketsize 12 initval 0x1707fb58
Size in memory: 296
References: 1
Number of entries: 1
Members:
192.168.122.213 packets 1 bytes 84

INPUTチェインを確認します。ICMPパケットを受信したことがわかります。

[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        1    84 LOG        icmp --  *      *       0.0.0.0/0            0.0.0.0/0            match-set test1 src LOG flags 0 level 4

ipsetコマンドを実行したときのカーネルの動作をsystemtapで確認する。

[root@server ~]# ipset n test1 hash:ip
pp=module("ip_set_hash_ip").function("hash_ip_create@net/netfilter/ipset/ip_set_hash_gen.h:1207")
pp=module("ip_set_hash_ip").function("htable_size@net/netfilter/ipset/ip_set_hash_gen.h:103")