Linuxでファイヤーウォール設定
このエントリは2007/11/28の再掲です
Linuxでhosts.allow/hosts.denyファイルでIPアドレス/ポートベースのアクセス制御が有効なのは、
- inetdを使ったサービスアプリケーション
- ssh等のhosts.allow/hosta.denyを独自に使うアプリケーション
しかありません。なので、その他のサービスについて、ポートをブロックしたり、許可IPアドレスを制限したりするには、iptablesでIPフィルタリングすることになります。Linuxカーネル2.4以降で、IPフィルタリングはすべて、iptablesで包括的に管理できるようになったそうです。
iptables自体の詳細については、既存の文書を:
http://www.asahi-net.or.jp/~aa4t-nngk/iptables.html
http://iptables-tutorial.frozentux.net/iptables-tutorial.html
http://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/index.html
以下、RedHat系(FedoraCore/CentOS)でiptablesを使ったプライベートなファイヤーウォール(適用範囲が自クライアントのみ)を設定する方法を説明します。
iptablesサービスが稼動していると、コマンドを実行するたびに、IPフィルタが書き換わります。
service iptables save
とすることで、iptablesサービスのリスタート時(つまりリブート時)に、現在のフィルタ状態を再現することができるようになります。この状態は /etc/sysconfig/iptablesファイルに保存されているので、どうにもならなくなったときは、このファイルを削除して、
service iptables restart
しましょう。また、随時コマンド実行していると、sshもtelnetもできなくなる瞬間ができてしまうので、リモート管理したい場合はかならず、シェルスクリプトに禁止操作と許可操作をまとめて書き、一括実行するようにしましょう。
具体的にどう設定すればよいのかについては、じっさいのところ、「iptables自体が高度すぎるために、記述方法を一般化できない」ようです。なので、一例を書きます。
#! /bin/sh TRUST_IP='xxx.xxx.xxx.xxx' iptables -F iptables -X iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT #loopback iptables -A INPUT -i lo -j ACCEPT #pass established iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT #ICMP iptables -A INPUT -p icmp --icmp-type any -j ACCEPT #client functions iptables -A INPUT -p udp --sport 53 -j ACCEPT iptables -A INPUT -p udp --dport 53 -j ACCEPT iptables -A INPUT -p tcp --sport 25 -j ACCEPT iptables -A INPUT -p tcp --sport 80 -j ACCEPT iptables -A INPUT -p tcp --sport 443 -j ACCEPT #services iptables -A INPUT -p tcp --dport 22 -j ACCEPT #iptables -A INPUT -p tcp --dport 80 -j ACCEPT #iptables -A INPUT -p tcp --dport 443 -j ACCEPT #iptables -A INPUT -p tcp --dport 21 -j ACCEPT #for testing phase iptables -A INPUT -p tcp -s $TRUST_IP --dport 80 -j ACCEPT iptables -A INPUT -p tcp -s $TRUST_IP --dport 443 -j ACCEPT iptables -A INPUT -p tcp -s $TRUST_IP --dport 8080 -j ACCEPT
これで、
- フォワーディング全面的に禁止
- 自分が自分にアクセスするのは全面的に許可
- 自分へのアクセスが継続接続であれば無条件に許可(新規のみフィルタ)
- 自分のbindがDNSとしてちゃんと機能する
- 自分は他サーバの25,80,443ポート以外へアクセスできない
- ポート22(ssh)へのアクセスを許可する
- ポート80,443,8080へのアクセスは、TRUST_IPにしか許可していない
となります。TRUST_IP='xxx.xxx.xxx.xxx'は任意のIPアドレスに設定してください。 sshへのアクセスを限定していないのは、sshがhosts.allow/hosts.denyでIPアドレスベースのアクセス制限を行うことができるためです。
@ITにも同様のサンプルがあるものの、ちょっとやりすぎていて、記述性も可読性も悪く、意味の把握がおろそかになってしまうので、逆に危険な気がします。参考程度にどうぞ。
http://www.atmarkit.co.jp/flinux/index/indexfiles/iptablesindex.html
おまけ:
OS インストール直後、*nixのC標準ライブラリにあるgethostname()は、"localhost.localdomain"を返します。 bindで「外から見た名前」をアサインしても、自分自身の内部で「自分のドメイン名」を取得するときは、DNSをあてにしないのが普通です。デフォルト値として「自分の名前」をサポートするアプリケーションは、gethostname()など、DNSと無関係なAPIを使うのです。
- /etc/hosts
- /etc/sysconfig/network
の両方に、自分の名前を書いておきましょう。
/etc/hosts
127.0.0.1 myhost.mydomain localhost.localdomain localhost
/etc/sysconfig/network
HOSTNAME="myhost.mydomain"