*

ipsetを使ってスマートにiptablesを設定する

公開日: : ipset, iptables, Linux, ネットワーク, 技術

ギークな知人から「vpsでiptables設定していたらルール設定数の上限に引っかかって思い通りの設定ができない!」との話を聞き、それは一体どんな大きさのiptablesなんだと内心ツッコミを入れつつ、対応方法を調べることにした。知人曰くipsetが使えそうとの事なので、調査した結果をブログにまとめておく。

ipsetとは?

ipsetとはLinuxカーネルバージョン2.4以降で利用できるIP管理用のユーティリティのことだ。 ipsetを利用することで、IPアドレスの集合を簡単に管理することができる。

ipset自体はネットワーク管理機能を持たないが、iptablesと組み合わせることで、

  1. iptablesのフィルタリングルールを一括で更新できる
  2. IPを集合として扱う事で、煩雑なiptables管理を単純化できる

 

といったメリットがある。

ipsetを使ってみよう

それでは、実際にipsetを使ってiptablesを設定してみよう。今回は接続を拒否したいネットワークアドレスの集合をipsetを利用して”BLACKLIST”という名称で管理し、iptablesに追加してみる。ipsetは私の環境(CentOS6.5)では標準で入っていないため、インストールから始める。

1.iptablesのインストール

$ sudo yum install ipset
# 一部省略
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package ipset.x86_64 0:6.11-1.el6 will be installed
--> Processing Dependency: libmnl.so.0(LIBMNL_1.0)(64bit) for package: ipset-6.11-1.el6.x86_64
--> Processing Dependency: libmnl.so.0()(64bit) for package: ipset-6.11-1.el6.x86_64
--> Running transaction check
---> Package libmnl.x86_64 0:1.0.2-3.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

==============================================================================================================================================
 Package                          Arch                             Version                               Repository                      Size
==============================================================================================================================================
Installing:
 ipset                            x86_64                           6.11-1.el6                            base                            61 k
Installing for dependencies:
 libmnl                           x86_64                           1.0.2-3.el6                           base                            21 k

Transaction Summary
==============================================================================================================================================
Install       2 Package(s)

Total download size: 82 k
Installed size: 205 k
Is this ok [y/N]: y 
Downloading Packages:
(1/2): ipset-6.11-1.el6.x86_64.rpm                                                                                     |  61 kB     00:00     
(2/2): libmnl-1.0.2-3.el6.x86_64.rpm                                                                                   |  21 kB     00:00     
----------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                         115 kB/s |  82 kB     00:00     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Warning: RPMDB altered outside of yum.
  Installing : libmnl-1.0.2-3.el6.x86_64                                                                                                  1/2 
  Installing : ipset-6.11-1.el6.x86_64                                                                                                    2/2 
  Verifying  : libmnl-1.0.2-3.el6.x86_64                                                                                                  1/2 
  Verifying  : ipset-6.11-1.el6.x86_64                                                                                                    2/2 

Installed:
  ipset.x86_64 0:6.11-1.el6                                                                                                                   

Dependency Installed:
  libmnl.x86_64 0:1.0.2-3.el6                                                                                                                 

Complete!

 

2.セットの作成

ipsetでは、IPアドレスの集合をセットという単位で管理する。先ず、セットを作成し、セットに対してIPアドレス(エントリ)を追加していくイメージだ。
先ずは接続を拒否したいネットワークのアドレスを保持するセット”BLACKLIST”を作成する。

$ #接続拒否IPの集合"BLACKLIST"を作成
$ sudo ipset create BLACKLIST hash:net

コマンドはipset create SET名 TYPENAME [CREATE-OPTIONS]という書式を持つ。TYPENAMEとCREATE-OPTIONについて解説しておこう。

 TYPENAME

作成するセットの種類を指定する。指定可能なTYPENAMEはいくつかパターンがあり、このページに詳しく記載されている。簡単に言えば「アドレスの格納方法:格納できる情報(カンマ区切り)」という形式だ。TYPENAMEの一覧と簡単な説明は以下の通りだ。

TYPE格納情報詳細
bitmap:ipIPIPアドレスを保持。
CIDR形式でエントリを追加した場合、指定したネットワークに属する全てのIP(NW、ブロードキャストアドレス含)が個々に展開されて格納される。ただし、展開されるだけで、展開後IPはネットマスクを保持していない。
また、後述する「netmask」CREATE-OPTIONを指定するとネットワークアドレスのみ保持するセットとして定義できる。
bitmap:ip,macIPとMACのペアIPとMACの組合せを保持。IPはネットマスクを保持できない。
bitmap:portPORTPORT番号を保持。
1-1023のようにPORTを範囲指定してエントリ追加できるものの、個々のPORT番号に展開されて格納される。
hash:ipIPhashを利用してIPアドレスを保持。
セットに格納できるIPの範囲を制限(「range」CREATEオプション。詳細は後述)できない点を除きbitmap:ipと同じ。
hash:netIP
(NWアドレス)
ネットワークアドレスを保持。
CIDR表記でエントリ追加した場合、指定されたIPのネットワークアドレスがエントリとして登録される。(ホストアドレス部分は無視される。)
⇒ 192.0.2.1/24を追加しても、エントリ追加されるのは192.0.2.0/24(ホストアドレス無視)
※ CIDR形式を利用しなければ、単一IPをエントリ追加可能だが、ネットマスクを持てない
hash:ip,portIP、PORT、L4 Protocolの組合せIP(ネットマスク保持不可)、PORT、L4プロトコルの組み合わせをハッシュで保持。
エントリ追加時にL4プロトコルは省略可能で、デフォルトはTCP。
また、CIDR表記によるエントリ追加は可能だが、該当ネットワークに属する個々のIPに展開されてエントリ追加される。(展開されるだけでネットマスクの情報はセットに保持されない)
hash:net,portIP(NWアドレス)、PORT、L4 Protocolの組合せNWアドレスを含むIP、PORT、L4プロトコルの組合せで保持。
IPのエントリ追加に関する挙動は「hash:net」と同じ。
L4プロトコルの考え方は「hash:ip,port」と同じ。
hash:ip,port,ipIP×2、PORT1エントリで2つのIPアドレスとPORT番号の組合せを保持。
1対1のIPの紐付け管理ができるからNAT設定向きか?
hash:ip,port,netIP、PORT、L4 Protocolの組合せIPアドレスとPORTとネットワークアドレスを保持。
L4プロトコルの考え方は「hash:ip,port」と同じ。
エントリの追加は紛らわしい。CIDR表記によってIPを指定できるが、ネットワークアドレスは別途指定する。
CIDR表記が表すNWの全てのIPが展開されてエントリに追加され、その後、個々のIPに対して指定したネットワークアドレスが割り当てられる。(ネットマスクではなく、ネットワークアドレスで管理される)
hash:net,ifaceIP、NWインタフェースのペアネットワークアドレスを含むIPとネットワークインタフェースをペアで保持できる。NWインタフェースの指定はインタフェース名(eth1など)を使う。
list:setセット上記のセットを複数まとめて保持。
複数のセットをまとめて管理することができる。

今回作成する”BLACK LIST”は接続を拒否したいネットワークのアドレスを保持するので、hash:netを選択する。

CREATE-OPTIONS

セットに対して様々な設定を行う事ができる。セットのTYPENAMEによって利用できるオプションは異なる。主なオプションは以下の通り。

OPTION使途対応TYPE
rangeセットに保持するIPやPORTの範囲指定が可能。
指定した範囲から外れたエントリを追加しようとするとエラー。
bitmap系のTYPEでのみ指定可能であり、かつ指定必須。
bitmap:ip
bitmap:ip,mac
bitmap:port
timeoutセット内のエントリの有効期間を秒指定。
指定した秒数の経過後、エントリはセット内から削除される。
デフォルトは"0"(無期限)。
全てのTYPE
familyセット内で利用するIPのアドレスファミリ。
デフォルトは"inet"(IPv4)。IPv6を扱う場合は"inet6"を指定。
IPを取り扱える全TYPE
hashsizeハッシュのサイズ。
デフォルトは"1024"。
hash系の全TYPE
maxelemハッシュに登録できるエントリの最大数。
デフォルトは"65536"
hash系の全TYPE
netmaskエントリに適用するネットマスク。
当オプションを指定したセットはネットワークアドレスしか保持できない。(ホストアドレス部分は常に無視される)
1 - 31で指定する。
bitmap:ip
hash:ip

3.エントリの追加

作成したセット「BLACKLIST」に対してエントリを追加する。
今回は「192.0.2.128/26」と「192.0.2.192/26」の2つのネットワークを追加してみよう。

$ sudo ipset add BLACKLIST 192.0.2.128/26
$ sudo ipset add BLACKLIST 192.0.2.192/26
$ sudo ipset list BLACKLIST
Name: BLACKLIST
Type: hash:net
Header: family inet hashsize 1024 maxelem 65536 
Size in memory: 16816
References: 0
Members:
192.0.2.128/26
192.0.2.192/26

セットに対するエントリの追加はipset add セット名 追加エントリコマンドで実行可能だ。また、セットが保持するエントリのリストはipset list セット名で表示できる。
なお、エントリの削除はipset del セット名 削除エントリコマンドで実行できる。

4.作成したセットをiptablesに追加

では、作成したセット”BLACKLIST”をiptablesに混ぜ込んでみる。

$ #BLACKLIST内に保持するNWアドレスを持つパケットは全てアクセスさせない
$ sudo iptables -I INPUT -m set --match-set BLACKLIST src -j DROP

$ sudo iptables -L
# 一部省略
Chain INPUT (policy ACCEPT)
target   prot opt source      destination         
DROP     all  --  anywhere    anywhere    match-set BLACKLIST src

iptablesは-m(または-match)オプションを利用することで拡張モジュールを使うことができる。今回、iptablesコマンドでipsetを使っているのは-mオプションに続く-m set --match-set BLACKLIST srcの部分だ。
ipsetを利用する場合の拡張モジュール名は「set」であるため、今回の-mオプションは-m setとなる。また、拡張モジュール側のコマンドとして--match-set BLACKLIST srcを利用しているが、これは、”BLACKLIST”にマッチするIPアドレスsourceアドレスとして利用するというコマンドだ。 なお、拡張モジュール側で利用できるコマンドと書式はiptables -m set -hコマンドから確認できる。

$ sudo iptables -m set -h
# --match-setと関係する部分のみ抜粋
iptables v1.4.7

set match options:
 [!] --match-set name flags
		 'name' is the set name from to match,
		 'flags' are the comma separated list of
		 'src' and 'dst' specifications.

 

今回、iptables -Lコマンドで出力されたルールのsourceはanywareとなっているが、実際はBLACKLISTに指定されたネットーワークからのパケットをDROPすることができる。

これで、iptables上に設定しているルールは1つだが、実際は複数のNWに対してルールを設定することができた。(ルール数を削減できた)

 注意点.セットはサーバ再起動時に削除される

ipsetのセットはiptablesのルールと同じでサーバ再起動時に削除される(iptablesの場合はサービス再起動でも削除される)。
再起動後にセットを引き継ぐためにはipset saveコマンドとipset restoreコマンドを利用する。

$ sudo ipset list
Name: BLACKLIST
Type: hash:net
Header: family inet hashsize 1024 maxelem 65536 
Size in memory: 16816
References: 0
Members:
192.0.2.192/26
192.0.2.128/26

$ #restore用のコマンドを保存しておく
$ sudo ipset save | tee restorecommand
create BLACKLIST hash:net family inet hashsize 1024 maxelem 65536 
add BLACKLIST 192.0.2.192/26
add BLACKLIST 192.0.2.128/26

$ #ここでサーバが再起動されたと仮定。今回の例ではセットを削除
$ sudo ipset destroy

$ #destroyした後だから全てのセットが存在しない
$ sudo ipset list

$ #リストアする
$ sudo ipset restore < restorecommand

$ #リストアによってBLACKLISTが復活
$ sudo ipset list
Name: BLACKLIST
Type: hash:net
Header: family inet hashsize 1024 maxelem 65536 
Size in memory: 16816
References: 0
Members:
192.0.2.192/26
192.0.2.128/26

基本的な考え方はiptables-saveiptables-restoreと同じだ。ipset saveコマンドでリストア用のコマンドを出力し、ipset restoreコマンドで取り込めば良い。

 

後日談

この手順を知人が試した結果、知人のvps環境ではipsetが使えないことが分かった。
どうやら必要なカーネルモジュールが足りていないらしい。vpsがOSレベル仮想化を利用しているため、ホスト側にモジュールが無い⇒どうしようもないという展開に。うーん、なんとかならないものか・・。

関連記事

文字コードの考え方から理解するUnicodeとUTF-8の違い

UnicodeとUTF-8の違いを理解していない方が結構居るようなので、文字コードの考え方を元に解説

記事を読む

Ctrl+Cとkill -SIGINTの違いからLinuxプロセスグループを理解する

しばらくLinuxネタが続く・・。 近いうちに最近出たJava8ネタを書いてみようと思います。が、

記事を読む

「Systemd」を理解する ーシステム起動編ー

2014年6月10日、とうとうRHEL7が正式リリースを迎えた。RHEL7での変更点については、この

記事を読む

例示専用のIPアドレスとドメインを使いこなす

前回の記事ではネットワークに関する記事を投稿させていただいたが、今回も引き続きネットワーク関連のネタ

記事を読む

Java8のHotSpotVMからPermanent領域が消えた理由とその影響

今回も前回の記事につづき、Java8による変更点で未だあまり紹介されていないポイントを記事にしようと

記事を読む

Linuxプロセス起動時の環境変数ダンプの取得

UnixやLinux上で不具合の調査等々を行う際、特定のプロセス起動時の環境変数を知りたい場合がある

記事を読む

「Systemd」を理解する ーシステム管理編ー

前回の記事「Systemd」を理解するーシステム起動編ーでは、Systemdの概念とSystemdに

記事を読む

sshd再起動時にssh接続が継続する動作について

Linux/Unixサーバにsshしている際、sshdを再起動したとする。 sshdは一度終了する

記事を読む

Java8のインタフェース実装から多重継承とMixinを考える

2014年3月18日、ついにJava8が正式にリリースを迎えた。 折角なので、今後、Java8の新

記事を読む

Comment

  1. Johne435 より:

    Really enjoyed reading ur blog. aagfebceddcf

Message

メールアドレスが公開されることはありません。

「Systemd」を理解する ーシステム管理編ー

前回の記事「Systemd」を理解するーシステム起動編ーでは、Syst

「Systemd」を理解する ーシステム起動編ー

2014年6月10日、とうとうRHEL7が正式リリースを迎えた。RHE

例示専用のIPアドレスとドメインを使いこなす

前回の記事ではネットワークに関する記事を投稿させていただいたが、今回も

ipsetを使ってスマートにiptablesを設定する

ギークな知人から「vpsでiptables設定していたらルール設定数の

Java8のHotSpotVMからPermanent領域が消えた理由とその影響

今回も前回の記事につづき、Java8による変更点で未だあまり紹介されて

→もっと見る

PAGE TOP ↑