Amazon EC2でiptables,ipsetを使いホワイトリスト/ブラックリストを設定する
Linuxカーネルにはnetfilter(iptables,firewalld)というファイアウォール機能がありますが、Amazon EC2ではセキュリティグループを使って簡単にファイアウォールの設定を行うことができるので、iptablesやfirewalldを使うことはあまりありません。Amazon Linuxでもデフォルトではiptables,firewalldサービスはインストールされておらず、netfilterの設定は空になっています。
ただ、ファイアウォールを設定する上で、特定のサービス(ssh,ftp,etc.)に対して特定IPからのみ接続を許可(ホワイトリスト)したり、拒否(ブラックリスト)したいことがあります。
これにはセキュリティグループにルールを登録していけばいいのですが、登録できるルールには上限があるのでそれにひっかかる可能性があります(*1)。
そこで、基本的な設定はセキュリティグループを使いつつ、接続元IPでのホワイトリスト、ブラックリスト設定はLinuxカーネルのnetfilterを使って行う方法を説明したいと思います。アクセス制限を行うサービスはFTPとします。
Linuxのファイアウォール設定にはiptables、firewalld-cmd(firewalld)がありますが、今回のケースではiptablesを使用します(*2)。
セキュリティグループは以下のように設定されているものとします。ソースは0.0.0.0/0とか::/0で接続元制限はしていません。
前提とするセキュリティグループの設定
Port | Source | 備考 |
---|---|---|
TCP: 80 | 0.0.0.0/0 | http(IPv4) |
TCP: 80 | ::/0 | http(IPv6) |
TCP: 443 | 0.0.0.0/0 | https(IPv4) |
TCP: 443 | ::/0 | https(IPv6) |
TCP: 22 | 0.0.0.0/0 | ssh |
TCP: 21 | 0.0.0.0/0 | FTP(IPv4) |
TCP: 60001-60010 | 0.0.0.0/0 | FTP Passive Port |
設定をしていく
設定を間違えてsshで接続できなくなるリスクもあるので、作業前にはスナップショットをとっておきましょう。
それでは設定作業です。まずはiptablesとipsetをインストールします。
yum install iptables-services ipset-service
そしてホワイトリストとなるipsetを作成していきます(ipset名はWhiteListFtp)。
ipset create WhiteListFtp hash:net ← ipset作成 ipset add WhiteListFtp xx.xx.xx.xx/32 ← 許可対象のIPを登録していく ipset add WhiteListFtp xx.xx.xx.xx/32 :
作成したipsetの内容を/etc/sysconfig/ipsetに保存しておきます。これで、再起動した時などに設定が自動で読み込まれるようになります。
ipset save > /etc/sysconfig/ipset
自動保存したいような場合は/etc/sysconfig/ipset-configのIPSET_SAVE_ON_STOP="no"を変更しておきましょう。
次にiptablesの設定です。iptablesの設定ファイルは/etc/sysconfig/iptablesになります。このファイルを直接修正していきます。
デフォルトでは以下のようになっていますが、
デフォルトの/etc/sysconfig/iptables
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT
この設定を全部消して以下のように書き換えます。
修正後の/etc/sysconfig/iptables
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state NEW -m set --match-set WhiteListFtp src -m tcp -p tcp --dport 21 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j REJECT COMMIT
設定の要点としては、WhiteListFtpにマッチする接続元からのFTP(port 21)に対する新規接続はACCEPTし、ホワイトリスト外からのFTP接続はREJECTしています。それ以外の通信はINPUTチェーンのデフォルトアクション(つまりACCEPT)に飛ばしています。
デフォルトの設定にあった'-A INPUT -j REJECT --reject-with icmp-host-prohibited'がないので、セキュリティグループを通過したPort21宛以外の通信はすべて通すことになります。
なお、今回はIPv6についてはFTPを提供していない前提なので、アクセス元制限の設定は行わないものとします。アクセス制限を行わない場合は/etc/sysconfig/ip6tablesは空にしておきます。
/etc/sysconfig/ip6tables
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] COMMIT
これで、IPv6については、セキュリティグループを通過してきた通信は全て通すことになります。
設定ファイルができたので、ipsetとiptablesサービスを開始しておきます。
systemctl enable ipset.service systemctl start ipset.service systemctl enable iptables.service systemctl start iptables.service systemctl enable ip6tables.service systemctl start ip6tables.service
これで、設定したIP制限が有効になります。
上記はホワイトリストの例ですが、httpで特定のネットワークからのアクセスを拒否したいような場合(ブラックリスト)には、/etc/sysconfig/iptablesに以下のエントリを追加します(httpsの方は省略)。
ブラックリスト設定の例
-A INPUT -m state --state NEW -m set --match-set BlackListHttp src -m tcp -p tcp --dport 80 -j REJECT
BlackListHttpにマッチする接続元からのhttp接続を拒否します(BlackListHttpセットは別途作成しておく必要があります)。
ただし、http/httpsについてはWebサーバーがApplication Load Balancer配下で動作している場合はこの方法は使えないので、Webサーバー(apache,nginx)でdeny設定をするかWAFを別途導入する必要がありますが。
まとめ
以上のようにして、セキュリティグループのルール数を抑えながら、細かいアクセス制限を行うことができます。
sshについては設定を間違えて接続できなくならないよう、セキュリティグループのみでの設定にしておいた方がよいと思います。繰り返しになりますが、作業前には念の為スナップショットをとっておきましょう。
(*1) 2019.8.6時点では、VPC セキュリティグループ当たりのルールの数は60。制限緩和申請もできますが、VPC セキュリティグループ当たりのルールの数 × Elastic Network Interface 当たりの VPC セキュリティグループの数 の値が1000までとなります。
参考: https://aws.amazon.com/jp/premiumsupport/knowledge-center/increase-security-group-rule-limit/
(*2)今回のケースではfirewalldだとゾーン設定が邪魔になります。Linuxカーネル側に設定するのは接続元IPに関する最低限の設定しか行わないので、必要最低限のルールだけ設定できるiptablesを使います。
投稿日:2019/08/07 12:50