わすれっぽいきみえ

みらいのじぶんにやさしくしてやる

iptablesをいじってた

七夕ですね。サーバに夢を詰めよう。

なんか久しぶりにサーバいじりたくなったのでモニョモニョしてた。
vagrant触る時にどうせローカル開発環境だし別にいいやーとiptables切ってたんだけど、実際の環境でそんなことしたらアホみたいにアクセスくるので、やっぱちゃんと触ろうと思った。といってもいきなりかっこいいことできないので人の設定例をパクり参考にしながらいじってみる。

そもそもiptablesって

ざっくりいうとパケットフィルタリングの設定を保持しているファイル名(/etc/sysconfig/iptables)もしくはコマンド名のこと。サーバに渡されたパケットをどういうルールで受け取るか、もしくは捨てるかを設定することでファイヤーウォールとして利用する。

入ってきたパケットはroutingを介してホストにはいるINPUTチェイン、ホストから出て行くOUTPUTチェイン、別のホストへ転送されるFORWARDチェインの3つに大別される。以下がイメージ図

f:id:kimikimi714:20150707014827p:plain

それぞれのチェインにルールを設定する。例えば「INPUTチェインにTCPプロトコルで22ポートからのアクセスがあったパケットを通す」みたいなルールを設定するとSSHに関するルールになる。

実際に触ってみる

昔disったCentOS6でしたが、それは過去のこと。やっぱり仲良くしよう。

$ sudo cat /etc/redhat-release
CentOS release 6.6 (Final)

iptablesはあらかじめインストールされてる前提で話す。iptablesに何も設定しない状態だと以下のようになる。

$ sudo iptables -L // -L で現在の設定をみる
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

上で話したINPUT、FORWARD、OUTPUTにルールが何も設定されてない真っ新な状態。
また本当に一番最初だとiptablesに関する設定ファイルは

$ sudo cat /etc/sysconfig/iptables
cat: /etc/sysconfig/iptables: そのようなファイルやディレクトリはありません

と出力されて、存在しないことがわかる。
このあと設定を追加していくが、iptablesコマンドを実行して増やしたルールというのは再起動すると揮発するので、もし再起動しても適応しておいてほしいルールがあるのなら

$ sudo service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]

で、設定ファイルを保存してやる必要がある。*1
といっても今はまだルールを設定してないのでINPUTチェイン、OUTPUTチェイン、FORWARDチェインが記載されたファイルができるだけ。

もしくは手で書いたiptablesファイルを配置して、

$ sudo service iptables restart
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Unloading modules:                               [  OK  ]
iptables: Applying firewall rules:                         [  OK  ]

で設定ファイルを読み込ませる。

私はお勉強がしたいので真っ新なところからコマンドで設定を加えてみる。まずユーザ定義チェインを追加してみる。

$ sudo iptables -N RH-Firewall-1-INPUT // -N 好きなチェイン名 で追加できる
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain RH-Firewall-1-INPUT (0 references) // ←追加された
target     prot opt source               destination

ユーザ定義チェインというのは文字通り自分で作れるチェインのこと。自分で作ったチェインにルールを設定した後、そのルール自体をINPUTチェインなり、OUTPUTチェインなりに追加して共通のルールを設定することができる。今は0 referencesとなっていて、他のどのチェインにも参照されてないことを示す。
試しにINPUTチェインとFORWARDチェインにRH-Firewall-1-INPUTチェインを追加してみる。

$ sudo iptables -A INPUT -j RH-Firewall-1-INPUT // -A チェイン名 -j ターゲット でチェインにターゲットを追加する
$ sudo iptables -A FORWARD -j RH-Firewall-1-INPUT
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere // ←追加された

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain RH-Firewall-1-INPUT (2 references)
target     prot opt source               destination

これでINPUTチェインとFORWARDチェインにはRH-Firewall-1-INPUTというユーザ定義チェインで設定されたルールが適応されるようになった。
ここでいうターゲットとは「パケットにどのルールを適応するか」を表していて、以下のものなどから選べる。

ターゲット 意味
ACCEPT 許可
DROP 破棄
REJECT 拒否(送信元に通知)
LOG ログに出す
ユーザ定義チェイン(上ではRH-Firewall-1-INPUTのこと) パケットをさらに定義したチェインに設定しているルールで振り分ける

具体的にRH-Firewall-1-INPUTにルールを追加してみる。

$ sudo iptables -A RH-Firewall-1-INPUT -i lo -j ACCEPT // 受信インタフェースが"lo"(ループバック)ならば、通信を許可
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain RH-Firewall-1-INPUT (2 references)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere

もちろんユーザ定義チェインを介さなくても直接それぞれのチェインにルールを記載することができる。

$ sudo iptables -A INPUT -i lo -j ACCEPT
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain RH-Firewall-1-INPUT (2 references)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere

でもRH-Firewall-1-INPUTで設定したのをもう一回INPUTで設定する意味ないから、さっきのはやっぱなしで

$ sudo iptables -D INPUT 2 // INPUTチェインの上から2番目のルールを削除する
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain RH-Firewall-1-INPUT (2 references)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere

こんな感じでいじったのを/etc/sysconfig/iptablesに書き出す。

$ sudo service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]
$ sudo cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.7 on Tue Jul  7 01:30:08 2015
*filter
:INPUT ACCEPT [42:3100]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [25:3112]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
COMMIT
# Completed on Tue Jul  7 01:30:08 2015

こんな感じで書いていく。

上の例で書いた設定だと攻撃やりたい放題でやばいので、ACCEPTも大事だけど、どんな時にDROPさせるかとか、REJECTって送信元に「これはダメ」って通知するわけだけど、どこまで通知していいのかとかそういう話をちゃんと知る必要がある。

なので本、今読んでます。唐突なアフィ

ネット上にはiptablesの簡単に説明してくれる記事は他にもあって、私は以下のページを見たりしました。

参考リンク

*1:iptables -Lで表示されるのは/etc/sysconfig/iptablesに書かれている内容ではなく、あくまでも現在の設定を表示している。service iptables saveを行わずにサーバ再起動をかけると設定が全部吹っ飛ぶことに注意。なので多くの記事ではコマンドでルールを追加するよりも、ファイルを書いてrestartで読み込ませるパターンで書かれてるんだと思う。

*2:日本語の記事もあるが、紹介が漏れてるポート番号があるので英語の方を見た方が良い