目次
「CentOS 7」環境の「firewalld」で特定の国からのアクセスを拒否する設定を行ったところ、ルールが4000~5000とかなり多くなってしまいました。
その結果「firewalld」の動作がかなり重くなってしまい、良い方法を色々と調べてみたところ「ipset」と組み合わせて使用することで幸せになれるという情報が見つかりましたので、導入した際の手順についてまとめました。
ipsetとは
IPアドレスやネットワークアドレス、ポート番号、インターフェイス名などを組み合わせて管理することができるユーティリティになります。
「firewalld」で一つ一つルールを追加するよりも、格段にパフォーマンスも向上します。
ipsetインストール
まずは「yum」で「ipset」をインストールします。
# yum install ipset
セットの作成
「ipset」を使用するには、まずセット(ポリシー名みたいなもの)作成してから、そこにネットワークアドレスやIPアドレス等を追加していく必要があります。
セットを作成するためコマンドは下記の通りとなります。
ipseet create セット名 タイプ名 オプション
セット名
セット名はどのようなルールを管理しているのかが分かりやすい名前を設定します。
今回はアクセスを禁止するネットワークアドレスをまとめて管理するため「BLACKLIST」と付けることにします。
タイプ名
作成するセットの種類を指定します。
指定できるタイプは色々とあるのですが、今回使用するタイプはネットワークアドレスを管理するための「hash:net」を指定します。
タイプ一覧
指定できるタイプについて簡単にまとめて見ました。
タイプ | 管理する情報 |
---|---|
hash:ip | hashを使用してIPアドレスを管理 |
hash:net | hashを使用してネットワークアドレスを管理 |
hash:ip,port | hashを使用してIPとポート番号を管理 |
hash:net,port | hashを使用してネットワークアドレスとポート番号を管理 |
hash:ip,port,ip | hashを使用してIPとポート番号の2つを管理 |
hash:ip,port,net | hashを使用してIPとポート番号とネットワークアドレスの3つを管理 |
hash:net,iface | hashを使用して、ネットワークアドレスとNICの2つを管理 |
bitmap:ip | IPアドレスを管理 オプションでrange指定が必要 |
bitmap:ip,mac | IPアドレスとMACアドレスの管理 オプションでrange指定が必要 |
bitmap:port | ポート番号を管理 オプションでrange指定が必要 |
list:set | 複数のセットを管理することができる |
オプション
今回はすべてデフォルト設定でいきますので、特にオプションの指定は行いません。
オプション一覧
「ipset create」でセット作成する際に使用できるオプションの一覧です。
オプション | 説明 | 使用可能タイプ |
---|---|---|
family | inet(IPv4)かinet6(IPv6)を設定 デフォルトはinet |
IPを使用するタイプ全般 |
hashsize | ハッシュのサイズ デフォルトは1024 |
hashを使用するタイプ全般 |
maxelem | 登録できるルールの数 デフォルトは65536 |
hashを使用するタイプ全般 |
netmask | ネットマスクを指定(1-31) | bitmap:ip hash:ip |
range | IPやポート番号の範囲を指定 | bitmap系のタイプで使用(必須) |
timeout | セットの有効期限を設定 デフォルトは無制限(0) |
全てのタイプで使用可能 |
セット作成例
今回作成する「BLACKLIST」という名前のセットには、ネットワークアドレス登録するのでタイプは「hash:net」を指定して作成します。
# ipset create BLACKLIST hash:net
ネットワークアドレス追加
セットの作成が完了しましたら、「ipset add」コマンドでネットワークアドレスを追加していきます。
ipset add セット名 ネットワークアドレス/ネットマスク
追加例
先ほど作成したセットである「BLACKLIST」にネットワークアドレスを追加していきます。
# ipset add BLACKLIST 192.168.0.0/24 # ipset add BLACKLIST 192.168.2.0/24
追加確認
セットに登録された情報は下記のコマンドで確認することが出来ます。
ipset list セット名
先ほど実際に登録した内容を確認してみます。
# ipset list BLACKLIST Name: BLACKLIST Type: hash:net Revision: 3 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16848 References: 0 Members: 192.168.0.0/24 192.168.2.0/24
登録したネットワークアドレスが確認できました。
firewalldと連携
「ipset」の準備が出来たので、次に「firewalld」との連携設定を行っていきます。
連携には「firewall-cmd」の「--direct」オプションを使用して設定を行っていきます。
書式
firewall-cmd [--permanent] --direct --add-rule [ipv4|ipv6] テーブル名 チェイン 優先順位 -m set --match-set ipsetセット名 src -j DROP
作業時の注意点
「firewalld」の設定を行う場合は十分に注意して行ってください。
設定を失敗すると、対象サーバに接続することが出来なくなってしまう場合もあります。
設定例
今回は外部からの接続対してのルールを設定するので、テーブルは「filter」を、チェインは「INPUT」を指定しています。
# firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -m set --match-set BLACKLIST src -j DROP # firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -m set --match-set BLACKLIST src -j DROP
ここで設定した内容は「INPUT_direct」チェインに登録されます。
設定ファイル
「--direct」オプションで設定した内容は「/etc/firewalld/direct.xml」に保存されます。
direct.xml内容
<?xml version="1.0" encoding="utf-8"?> <direct> <rule priority="0" table="filter" ipv="ipv4" chain="INPUT">-m set --match-set BLACKLIST src -j DROP</rule> </direct>
設定確認
「iptables -L INPUT_direct -v」コマンドで「INPUT_direct」チェインの設定を確認して、「match-set」の部分に「ipset」で作成したセットが設定されていることを確認します。
INPUT_directチェイン確認
# iptables -L INPUT_direct -v Chain INPUT_direct (1 references) pkts bytes target prot opt in out source destination 0 0 DROP all -- any any anywhere anywhere match-set BLACKLIST src
INPUTチェイン確認
次に「INPUT」チェインに「INPUT_direct」チェインが登録されていることを確認してください。
# iptables -L INPUT -v Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 432 42740 ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED 0 0 ACCEPT all -- lo any anywhere anywhere 491 48989 INPUT_direct all -- any any anywhere anywhere 491 48989 INPUT_ZONES_SOURCE all -- any any anywhere anywhere 491 48989 INPUT_ZONES all -- any any anywhere anywhere 0 0 ACCEPT icmp -- any any anywhere anywhere 491 48989 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
両方とも確認できましたら、「ipset」と「fireawalld」の連携は完了です。
ipset自動作成
「ipset」と「firewalld」の連携が完了しましたら、次に「ipset」に作成したセットを自動作成する設定を行っていきます。
「ipset」はメモリ上にセット内容を格納しているため、サーバを再起動したりすると内容が削除されてしまいます。
そのため「firewalld」の起動前に「ipset」のセットを作成して、セットにルールを追加するという作業が必要になるのですが、サーバの再起動毎に手動で作業を行うのは現実的ではないので、自動的にセットを作成するためのスクリプトを作成していきます。
ipset データセーブ格納ディレクトリ作成
まずは、データ保存用のディレクトリを作成します。
# mkdir /etc/ipset
セット内容保存
現在の「ipset」の情報は下記の方法で保存することが出来ます。
ipset save > ファイル名
情報の保存
「BLACKLIST」というファイルに「ipset」のセット情報を保存していきます。
# ipset save > /etc/ipset/BLACKLIST
リストア方法
保存した情報は「ipset restore」コマンドでリストアすることができます。
ipset restore < ファイル名
ipset作成スクリプト
サーバ起動時や、「firewalld」の再起動時に自動的に「ipset」のセットを作成するために、「ipset_create.sh」というスクリプトを作成します。
※スクリプトの名前はお好きな名前でかまいません。
# vi /etc/ipset/ipset_create.sh
スクリプト内容
「ipset destroy」で既存のセット情報があればそれを削除して、その後「ipset restore」でバックアップした情報からセットを作成するという動作をします。
#!/bin/bash IPSET=/sbin/ipset DIR=/etc/ipset CONF=BLACKLIST cd $DIR $IPSET destroy $IPSET restore < $CONF
パーミッション設定
作成したスクリプトのパーミッションを設定します。
# chmod 744 ipset_create.sh
スクリプト動作確認
スクリプトの作成が終わりましたら、次に動作試験を行っていきます。
firewalldとの連係解除
「firewalld」と連携していると「ipset destroy」や「ipset restore」が行えないため、一度「firewalld」との連携を解除します。
# firewall-cmd --direct --remove-rule ipv4 filter INPUT 0 -m set --match-set BLACKLIST src -j DROP
スクリプト動作試験
「firewalld」との連携が解除されましたら、「ipset destoy」でセットを削除してからスクリプトを実行しセットがリストアされることを確認してください。
既存のセット削除と削除確認
# ipset destroy # ipset list
スクリプト実行
# sh -x /etc/ipset/ipset_create.sh # ipset list
スクリプトの動作に問題が無ければ、「firewalld」が起動する前に「ipset」のセット作成スクリプトを実行して、セットを作成するように設定を行っていきます。
firewalldsystemd管理用スクリプト変更
「firewalld」が起動する前にipsetのセットが作成されている必要があるため、「firewalld」のsystemd管理用スクリプト(/usr/lib/systemd/system/firewalld.service)を編集していきます。
# cp -p /usr/lib/systemd/system/firewalld.service /usr/lib/systemd/system/firewalld.service_yyyymmdd # vi /usr/lib/systemd/system/firewalld.service
変更内容
[Service]セクションに「ExecStartPre」を設定すると、起動前に実行するスクリプトを指定できるので「ipset」作成用のスクリプト(/etc/ipset/ipset_create.sh)を指定します。
[Service] EnvironmentFile=-/etc/sysconfig/firewalld ExecStartPre=/etc/ipset/ipset_create.sh <-----追加 ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS ExecReload=/bin/kill -HUP $MAINPID
動作確認
「/usr/lib/systemd/system/firewalld.service」の編集が完了しましたら、「firewalld」と「ipset」の連携試験を行っていきます。
firewalld再起動テスト
「ipset」の中身を空にしてから「firewalld」を再起動して「ipset」と連携できているか確認します。
ipset flush
一旦「ipset」のセット「BLACKLIST」の情報を削除します。
# ipset destroy # ipset list
「firewalld」を再起動して、「ipset」と連携できているか確認します。
# systemctl restart firewalld
ipset確認
「ipset」のセット登録情報を確認します。
# ipset list BLACKLIST
iptable設定状況確認
「INPUT」と「INPUT_direct」チェインの内容を確認し、それぞれ登録されていることを確認してください。
# iptables -L INPUT_direct -v Chain INPUT_direct (1 references) pkts bytes target prot opt in out source destination 14 612 DROP all -- any any anywhere anywhere match-set BLACKLIST src
# iptables -L INPUT -v Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 171 15112 ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED 0 0 ACCEPT all -- lo any anywhere anywhere 41 2480 INPUT_direct all -- any any anywhere anywhere 8 1032 INPUT_ZONES_SOURCE all -- any any anywhere anywhere 8 1032 INPUT_ZONES all -- any any anywhere anywhere 0 0 ACCEPT icmp -- any any anywhere anywhere 8 1032 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
サーバ再起動試験
「firewalld」の再起動試験で問題がなければ大丈夫だと思いますが、念のためにサーバの再起動試験が行えるのであれば実施したほうが安心です。
もし、今すぐにサーバの再起動が行えない場合は、次回サーバ再起動時に忘れずに確認を行ってください。
以上で作業完了となります。
国別のIPリスト作成方法
特定の国からの通信を遮断したい場合、その国に配布されているIPアドレスの一覧を調べる必要があります。
IPアドレスを管理している各団体のページから情報をダウンロードしてきて、自分で必要な情報を抽出するという方法もありますが、それは面倒なので私はいつも下記のサイトのお世話になっています。
IPアドレスの一覧が欲しい国を選択すると、その国に割り当てられているIPアドレスの一覧を表示してくれます。
また、画面右側の「Download」の「プレインテキスト」からテキストで情報をダウンロードすることができるので、これを元にIPセットを作成すると良いでしょう。
ちなみに、私はセットに登録する際には下記のようなスクリプトを使用して登録しています。
※登録するセットは事前に作成しておいてください。
#!/bin/bash LIST="ファイル名" SET="セット名" COM="/sbin/ipset add" while read line; do $COM $SET $line done < $LIST
tamohikoさん suhsiです。
バーチャルホストできました\(*T▽T*)/
本当にありがとうございます!!!
めちゃめちゃ感動ですよ!!!
親身になって優しくしていただいて
なんとお礼を言ったらいいかヽ(^◇^*)/
tamohiko さん の ご回答を何度も
読み直して、わたしの間違っているところを
調べなおしたんですね、そしたら
「あれ?バーチャルホストにしたいドメインの」
DNS設定ってしっかりなってるのかな?と思って
メインのドメインの方は、CENTOS7にインストールした
DICEでやっているんですけど、
サブドメインは未設定だったんですね
(。-人-。) オ、オユルシヲ・・・
それで、バーチャルホストにしたい方のアドレスを
MyDNS のオンラインサービスDNSでやることにしたんです。
そして、/etc/hosts で名前解決もして、
そしたら大成功ですよ!
本当にありがとうございました^^
超うれしいです。本日、さらに一段と自宅サーバーが
大好きになりました^^
なぜBINDの設定をしたかですけど、
以前に、ヤフー知恵袋に
この件を相談したときに、BINDを設定しないとダメだよ!
と回答されて、それで設定したんですね。
私の場合、これは関係なかったんですね、それか、
自分で、DNSサーバーを作る人はこれが必要だったのかな?
直接のメールやり取り!喜んで^^
ぜひぜひ、弟子にしてください!
tamohikoさんから、バーチャルホスト、
ウェブアライザー、ファイヤーウォールdの使い方を
教わって、これで超楽しい自宅サーバーライフが
はじまりますね!
本当にありがとうございました。直接のメール
お待ちしてまーすヽ(*^^*)ノ