Linux でサーバを構築する際のiptablesでのファイアウォールのサンプルです。
サンプルではssh接続を受け入れるようにしています。
サンプル中のコメントを外すと、メールサーバやwebサーバにも対応できます。
また、今後、設定を追加すると外部からのサーバへのssh辞書攻撃への対応や、日本国内からのみ接続出来るようにすることも可能です。
これについては、後日記載します。
6/8追記:記載しました
日本国内からのみ接続出来るようにする iptables - 国内からの接続のみ許可して海外からの接続を遮断する
外部からのサーバへのssh辞書攻撃への対応 SSH総当たり攻撃(辞書攻撃/ブルートフォースアタック)の対策とその効果
7/4修正:
変更前:$IPTABLES -A INPUT -p tcp -m state –state NEW -j sshguard
変更後:$IPTABLES -A INPUT -p tcp -j sshguard
サンプル
sh setip.sh を実行すると、ファイアウォールのルールをセットします。
sh setip.sh stop と実行すると、全てのルールを削除し、ファイアウォール無しの状態(全てのパケットを受け入れる状態)になります。
setip.sh
#!/bin/sh IPTABLES=/sbin/iptables if [ $# -eq 1 ] then if [ $1 = "stop" ] then $IPTABLES -F $IPTABLES -Z $IPTABLES -X $IPTABLES -P INPUT ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -P FORWARD DROP echo stopped.. exit fi fi $IPTABLES -F $IPTABLES -Z $IPTABLES -X $IPTABLES -P INPUT DROP $IPTABLES -P OUTPUT DROP $IPTABLES -P FORWARD DROP $IPTABLES -N ACCEPT_FILTER $IPTABLES -A ACCEPT_FILTER -j ACCEPT $IPTABLES -N sshguard $IPTABLES -A INPUT -i lo -j ACCEPT $IPTABLES -A OUTPUT -o lo -j ACCEPT $IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP $IPTABLES -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j REJECT --reject-with tcp-reset $IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT $IPTABLES -A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type source-quench -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type redirect -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type parameter-problem -j ACCEPT #VPNでIPsecを使用する場合 #$IPTABLES -A INPUT -p 50 -j ACCEPT #$IPTABLES -A INPUT -p 51 -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type echo-request -j ACCEPT_FILTER #メールサーバの場合 #$IPTABLES -A INPUT -p tcp --dport 25 -m state --state NEW -j ACCEPT $IPTABLES -A INPUT -p tcp -j sshguard $IPTABLES -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset #ssh接続を許可 $IPTABLES -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT_FILTER #メールサーバの場合:pop3,pop3s,iamp4,imap4s許可 #$IPTABLES -A INPUT -p tcp -m multiport --dport 110,995,143,993 -m state --state NEW -j ACCEPT_FILTER #メールサーバの場合:サブミッションポート許可 #$IPTABLES -A INPUT -p tcp -m multiport --dport 587 -m state --state NEW -j ACCEPT_FILTER #Webサーバの場合:http,https許可 #$IPTABLES -A INPUT -p tcp -m multiport --dport 80,443 -m state --state NEW -j ACCEPT_FILTER
説明
$IPTABLES -F $IPTABLES -Z $IPTABLES -X $IPTABLES -P INPUT DROP $IPTABLES -P OUTPUT DROP $IPTABLES -P FORWARD DROP
iptables初期化の為の処理です。
チェインを初期化し、以降で記述するルールにマッチしないパケットは破棄して受け入れない様に設定します。
ファイアウォールのルール設定の考え方は、全てのパケットはデフォルトで破棄するようにしておき、それから必要なパケットを受け入れるように設定していきます。
$IPTABLES -F
全てのチェインの内容を全消去します。
「チェイン」とは、ルールセットです。デフォルトで利用できるチェイン(組み込みチェイン)に、INPUT チェイン、OUTPUT チェイン、FORWARD チェインがあります。
INPUT チェインは、自分宛てに届くパケットに対するルールセットを定義します。
OUTPUT チェインは自分から送信するパケットに対するルールセットを定義します。
FORWARD チェインは、転送するパケットに対するルールセットを定義します。
$IPTABLES -Z
すべてのチェインのパケットカウンタとバイトカウンタをゼロにします。
$IPTABLES -X
ユーザー定義チェインを削除します。$IPTABLES -F でチェインの内容を消去しておかないと、Too many links. と表示が出て、ユーザー定義チェインの削除に失敗します。
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P INPUT DROP は、INPUTチェインのポリシーを DROP に設定します。
ポリシーとは、パケットがどのルールにもマッチしない場合の挙動で、ACCEPT(パケットを受け入れる)、DROP(パケットを捨てる)、REJECT(パケットを捨てると共に拒否応答をする)があります。
同様に、$IPTABLES -P OUTPUT DROP と $IPTABLES -P FORWARD DROP は、OUTPUTチェインとFORWARDチェインのポリシーをDROP に設定します。
$IPTABLES -N ACCEPT_FILTER $IPTABLES -A ACCEPT_FILTER -j ACCEPT $IPTABLES -N sshguard
$IPTABLES -N ACCEPT_FILTER
$IPTABLES -N ACCEPT_FILTER -j ACCEPT
-N は指定した名前でユーザー定義チェインを作成します。
$IPTABLES -N ACCEPT_FILTER で、ACCEPT_FILTER という名前で作成しています。
$IPTABLES -N ACCEPT_FILTER -j ACCEPT で、ACCEPT_FILTERチェインではパケットを全て ACCEPT(許可) します。
この2行は、今後設定を追加した際に、日本国内からの接続のみに制限が出来るようにするための布石です。
設定追加までは、サンプル中で -j ACCEPT_FILTER となっている箇所は、-j ACCEPT と同じと考えてください。
$IPTABLES -N sshguard
チェイン sshguard を作成します。
ssh辞書攻撃への対応でsshguardを使用した際に、sshguardでこのチェインは使用します。
sshguardの設定については、後日説明します。
設定追加までは、サンプル中で $IPTABLES -A INPUT -p tcp -j sshguard となっている箇所は、何もしないと考えてください。
日本国内からの接続のみに制限方法やsshguardについては、後日記載します。
6/8追記:記載しました
日本国内からのみ接続出来るようにする iptables - 国内からの接続のみ許可して海外からの接続を遮断する
外部からのサーバへのssh辞書攻撃への対応 SSH総当たり攻撃(辞書攻撃/ブルートフォースアタック)の対策とその効果
$IPTABLES -A INPUT -i lo -j ACCEPT $IPTABLES -A OUTPUT -o lo -j ACCEPT $IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP $IPTABLES -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j REJECT $IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT $IPTABLES -A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT
サーバの通信に必要な最低限の設定を行います。
この部分まであれば、外部からの接続はブロックするファイアウォールになります。
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A OUTPUT -o lo -j ACCEPT
自分から自分宛てのパケット(ループバック)を許可(受け入れ)します。
$IPTABLES -A INPUT -p tcp ! –syn -m state –state NEW -j DROP
-p tcp はプロトコルがTCPであるもの、 ! –syn は SYNフラグが立っていないもの、-m state はstateモジュールを利用可能にし、–state NEW ステートが NEWであることを指定しています。
この行で、NEWステート(相手からのTCP接続の開始要求のパケット)で、SYNフラグが立っていない受信パケット破棄します。
これが無いと、TCP接続の手順を踏んでいないパケットも受け入れてしまいます。
$IPTABLES -A INPUT -p tcp –tcp-flags SYN,ACK SYN,ACK -m state –state NEW -j REJECT –reject-with tcp-reset
TCP成りすまし攻撃の踏み台とならないように、NEWステートでSYN/ACKフラグがセットされているパケットの受信を拒否します。
TCP成りすまし攻撃の例と、拒否によってなぜ回避できるかはIptablesチュートリアル 1.2.2のSYN/ACKでNEWなパケットを参照してください。
$IPTABLES -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
確立された接続のパケット、既存の接続に関連するパケットの受信を許可します。
既存の接続に関連するパケットは、例えばTCPやUDPでの通信時にICMPプロトコルで通知されるエラーがあります。 既存の通信に関するものに対してのエラー通知なので、このようなパケットは既存の接続に関連するパケットです。
同様にFTPでは、相手サーバへの接続後、データ通信の接続が相手サーバから自分宛てに来るのですが、このような接続も、既存の通信に関連するものです。
なお、-p tcp のように、-p によってプロトコルを指定していないことに注意してください。-p tcp としてしまうと、UDPの通信が行えくなったり、ICMPでのエラー通知が届かなくなります。
$IPTABLES -A OUTPUT -m state –state NEW,ESTABLISHED -j ACCEPT
確立された接続のパケットの送信、接続要求の送信を許可します。
先の $IPTABLES -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT と合わせて、接続に関するパケットの送受信がこれで許可され、通信が行えます。
どちらか一方が欠けると、パケットが往復できなくなり、通信が行えなくなりますので、この2行は iptables には必須の記述です。
$IPTABLES -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type source-quench -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type redirect -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type parameter-problem -j ACCEPT
ICMPメッセージの受信を許可します。
ICMPメッセージについては、@ITの基礎から学ぶWindowsネットワークのTCP/IPプロトコルを支えるICMPメッセージがわかりやすく詳しいです。
なお、pingを打った時の応答は ICMPメッセージの Type:0(エコー応答(echo reply))というパケットが返ってきますが、ここでは記述していません。
先の $IPTABLES -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT によって、応答は受信許可されているので、ここでは記述する必要はありません。
$IPTABLES -A INPUT -p 50 -j ACCEPT $IPTABLES -A INPUT -p 51 -j ACCEPT
VPNでIPsecを使用する場合に記述して下さい。
-p の 50,51 はそれぞれプロトコル ESP , AH を示します。
$IPTABLES -A INPUT -p icmp --icmp-type echo-request -j ACCEPT_FILTER
-p icmp –icmp-type echo-request で ICMPプロトコルのメッセージタイプ Echo Request を指定します。
Echo Requestは、相手がpingを自分宛てに打った先に届きます。Echo Request に対して、相手に Echo Replyメッセージを返信すると、相手に ping の応答が返ることになります。
このパケットを拒否すると、相手に Echo Replyメッセージを返信することも無いので、相手にはpingの応答が返らなくなります。
$IPTABLES -A INPUT -p tcp --dport 25 -m state --state NEW -j ACCEPT
メールサーバの場合、この記述は必須です。
SMTP(25番)ポート宛ての接続を許可します。
この25番ポートを許可しないと、ユーザが SMTPにてメール送信が行えなくなります。
また、25番ポートは外部メールサーバからのメール配信にも使用されるので、25番ポートを許可しないとユーザ宛てのメールが外部から届かなくなってしまいます。
$IPTABLES -A INPUT -p tcp -j sshguard
ssh辞書攻撃への対処を行うsshguardを導入した場合に、sshguardで使用します。
sshguardの導入/設定については、後日説明します。
設定までは、この行は何もしないと考えてください。
6/8追記:記載しました
外部からのサーバへのssh辞書攻撃への対応 SSH総当たり攻撃(辞書攻撃/ブルートフォースアタック)の対策とその効果
7/4 修正:
変更前:$IPTABLES -A INPUT -p tcp -m state –state NEW -j sshguard
変更後:$IPTABLES -A INPUT -p tcp -j sshguard
$IPTABLES -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset
113番ポート(auth/IDENT)への接続に対して、拒否応答を返します。
このパケットを ACCEPT や DROP すると、外部のメールサーバやFTPサーバに接続した際に、接続に時間がかかるようになってしまいます。
メールサーバやFTPサーバの設定では、相手から接続されてきた時に、接続元ユーザを特定する為に、Auth/IDENTサービスのポート(113番)にアクセス(ident要求)してきます。
ident要求に対して REJECT すると、外部のメールサーバやFTPサーバはident要求をあきらめて処理を継続します。
もし、ident要求をDROP(パケットを破棄)してしまうと、外部のメールサーバやFTPサーバは ident要求の応答をタイムアウトまで待ち、それから処理を継続する為、接続に時間がかかるようになってしまいます。
こちらのTCP/113 AUTH/IDENT に関してに図入りで説明があります。
$IPTABLES -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT_FILTER
sshを使用する場合は記述して下さい。
ssh接続を許可します。
$IPTABLES -A INPUT -p tcp -m multiport --dport 110,995,143,993 -m state --state NEW -j ACCEPT_FILTER
メール受信サーバの場合に設定します。
POP(110)、POP3S(995)、IMAP(443)、IMAP4S(993)を許可しています。
$IPTABLES -A INPUT -p tcp -m multiport --dport 465,587 -m state --state NEW -j ACCEPT_FILTER
メール送信サーバの場合に設定します。
SMTPS(465)、サブミッションポート(587)を許可しています。
SMTP(25)については、先の $IPTABLES -A INPUT -p tcp –dport 25 -m state –state NEW -j ACCEPT を記述して下さい。
もしメールサーバが送信専用の場合は、代わりにここで
$IPTABLES -A INPUT -p tcp -m multiport –dport 25,465,587 -m state –state NEW -j ACCEPT_FILTER
と記述してください。
$IPTABLES -A INPUT -p tcp -m multiport --dport 80,443 -m state --state NEW -j ACCEPT_FILTER
Webサーバの場合に設定します。
http,https接続を許可します。
iptables設定内容の保存
なお、iptablesでコマンド実行したのみでは、その設定内容はどこにも保存されていないので、サーバを再起動すると設定内容が消えてしまいます。
保存の為に作業が必要です。
CentOSの場合
/etc/init.d/iptables save を実行
Ubuntuの場合
Ubuntuでiptablesを設定する方法 を参考に設定してください。
参考
Man page of IPTABLES
Iptablesチュートリアル 日本語訳
@IT 連載記事 「習うより慣れろ! iptablesテンプレート集」
TCP/113 AUTH/IDENT に関して
@IT 基礎から学ぶWindowsネットワーク TCP/IPプロトコルを支えるICMPメッセージ
Ubuntuでiptablesを設定する方法
6/8追記
iptables - 国内からの接続のみ許可して海外からの接続を遮断する
SSH総当たり攻撃(辞書攻撃/ブルートフォースアタック)の対策とその効果
コメント
大変恐縮ですが、ご回答いただけたら幸いです。
SSH、HTTPの接続を許可してICMPを特定サーバからのみ
許可する設定の場合はどのようにしたらよろしいのでしょうか。
ここで説明している icmpパケットはブロックすると、サーバの通信に影響が出るものです。
なので、特定サーバからのみ許可はしない方が良いです。
echo-request(pingの応答要求)については、ブロックしてもOKです。
おそらくですが、pingに応答しないようにしたいのではないでしょうか。
$IPTABLES -A INPUT -p icmp –icmp-type echo-request -j ACCEPT_FILTER
を
$IPTABLES -A INPUT -p icmp –icmp-type echo-request -s xx.xx.xx.xx -j ACCEPT
と変更すれば、特定サーバへのみ応答します。
xx.xx.xx.xx は許可したい特定サーバのIPアドレスです。
ご多用の中、返信ありがとうございます。
> ここで説明している icmpパケットはブロックすると、サーバの通信に影響が出るも>のです。
> なので、特定サーバからのみ許可はしない方が良いです。
> echo-request(pingの応答要求)については、ブロックしてもOKです。
上記、承知いたしました。
>おそらくですが、pingに応答しないようにしたいのではないでしょうか。
>$IPTABLES -A INPUT -p icmp –icmp-type echo-request -j ACCEPT_FILTER
>を
>$IPTABLES -A INPUT -p icmp –icmp-type echo-request -s xx.xx.xx.xx -j ACCEPT
>と変更すれば、特定サーバへのみ応答します。
>xx.xx.xx.xx は許可したい特定サーバのIPアドレスです。
内部のwebサーバ←→外部のWebサイトを公開するリーバスプロキシサーバ
(内部IP)との通信だけをさせたいので何とかして関係のない場所からの
pingをすべて拒否したいと考えております。
説明が下手で申し訳ございません。
図をアップロードできればいいのですが、アップできないので(^。^;)
上記で対応してみたいと思います。
iptablesの事で再度質問致します。
特定の接続元から特定の接続先・ポートの場合の接続はどのようにすればいいでしょうか。
WinSCP(SFTP)で接続先172.XXX.XXX.XXXのport8888は許可し、10.XXX.XXX.XXXの
port8888は許可をしないようしたいと思っております。
今思いつくのは以下の3つのどれかでないかと思っております。
(1)接続先サーバのファイアウォールの設定
接続元サーバのアドレス(-s)・接続先サーバのアドレス(-d)・ポート(–dport)
(2)接続元サーバのファイアウォールの設定
接続先サーバのアドレス(-d)・ポートを許可(–dport)
(3)接続元サーバ・接続先サーバのファイアウォール設定
接続元サーバ⇒接続先サーバのアドレス(-d)・ポート(–dport)を許可
接続先サーバ⇒接続元サーバのアドレス(-s)・接続先サーバのポート(–dport)を許可
ご多用の中誠に恐れ入りますが、ご教示よろしくお願いします。
(a)サーバ観点で、接続してくるクライアントを限定したいのか、(b)クライアント(接続元サーバ)観点で、接続先サーバを限定させたいのか、どちらに主眼を置くかによって変わります。
(a)なら藤堂さんの(1)、(b)なら(2)です。
(a)(b)ともなら(3)です。
(a)(b)は、管理観点で言い換えると、
(a)自分はサーバを管理している、(b)自分はサーバに接続するクライアントを管理している
です。