ファイアウォールの作成

iptablesスクリプト作成

習うより慣れろ・・・ということで、実際のiptablesの設定を見ていただきたいと思います。iptablesの設定は、特に設定ファイル書く
というよりは、shellスクリプトを書いて、実行させ、それをiptablesに記憶させるという方法をとります。以下は、そのshellスクリプトで
す。途中、for文などですっきりさせたつもりですが、不都合などございましたらご連絡ください。

#!/bin/bash

##########################################################################
# 変数の設定
##########################################################################
LAN_PORT=eth2
LAN_NET="192.168.20.0/24"
LAN_BASE="192.168.20.0"
LAN_BCAST="192.168.20.255"
LAN_IP="192.168.20.1"

DMZ_PORT=eth1
DMZ_NET="192.168.10.0/24"
DMZ_BASE="192.168.10.0"
DMZ_BCAST="192.168.10.255"
DMZ_SVR="192.168.10.2"
DMZ_IP="192.168.0.1"

WAN_PORT=ppp0
WAN_IP="218.45.162.31"

IPTABLES="/sbin/iptables"
MODPROBE="/sbin/modprobe"

# 通信すべきでないホストとネットワークのIPアドレス
SHUN=""

# ありえなさそうなIPアドレス
BADIP="$DMZ_BCAST $DMZ_BASE $LAN_BASE $LAN_BCAST 0.0.0.0/8 \
10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 224.0.0.0/4 \
240.0.0.0/5 255.255.255.255"

#ログの出力のタイミング
LOGOPT="--log-level=3 -m limit --limit 3/minute --limit-burst 3"
#SYNFLOODと扱うしきい値
SYNOPT="-m limit --limit 10/second --limit-burst 20"
#pingを許可するネットワーク
PING="192.168.10.0/24 192.168.20.0/24"
##########################################################################
# モジュールの読み込み、カーネル動作の設定
##########################################################################
$MODPROBE ip_tables
$MODPROBE iptable_filter
$MODPROBE ip_conntrack
$MODPROBE iptable_nat
$MODPROBE ip_nat_ftp
$MODPROBE ip_conntrack_ftp
$MODPROBE ipt_state
$MODPROBE ipt_MASQUERADE
$MODPROBE ipt_LOG
$MODPROBE ipt_REJECT
$MODPROBE ipt_limit
# IPマスカレード許可
echo 1 > /proc/sys/net/ipv4/ip_forward
# pingのブロード/マルチキャストを無視
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# ソースアドレスの妥当性検査
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f; done
# ありえないアドレスをログに記録
for f in /proc/sys/net/ipv4/conf/*/log_martians; do echo "1" > $f; done
# ICMP redirect messageを無視
for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 1 > $f; done
# SYN FLOOD攻撃対策
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# Smurf攻撃対策
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

##########################################################################
# DMZで公開するポート
##########################################################################

DMZ_SVC_TCP="ssh smtp domain http pop3"

DMZ_SVC_UDP="domain"

##########################################################################
# 既存のファイアウォールルールをクリアする
##########################################################################

if [ ! -x $IPTABLES ]
then
echo "firewall: can't execute $IPTABLES"
fi

$IPTABLES -P INPUT   DROP # デフォルトポリシーはDROP
$IPTABLES -P OUTPUT  DROP # デフォルトポリシーはDROP
$IPTABLES -P FORWARD DROP # デフォルトポリシーはDROP
$IPTABLES -F   # すべてのチェインをフラッシュ
$IPTABLES -X   # すべてのチェインをフラッシュ

#すべてのテーブルでルール、チェイン、カウンタをクリアする
for table in filter nat mangle
do
$IPTABLES -t $table -F  # ルールの削除
$IPTABLES -t $table -X  # チェインの削除
$IPTABLES -t $table -Z  # カウンタのクリア
done


##########################################################################
#ユーザ定義のチェイン。プログラムで言うところの自作した関数。
##########################################################################

#-------------------------------------------------------------------------
# BAD_IPチェイン。望ましくないIPのものはログを残して破棄。
#-------------------------------------------------------------------------

$IPTABLES -N BAD_IP
$IPTABLES -A BAD_IP -j LOG --log-prefix "IPTABLES BAD_IP: " $LOGOPT
$IPTABLES -A BAD_IP -j DROP

#-------------------------------------------------------------------------
# SHUNチェイン。敵対ホストのIPアドレスならBAD_IPチェインに渡す。
#-------------------------------------------------------------------------

$IPTABLES -N SHUN
for ip in $SHUN
do
$IPTABLES -A SHUN -s $ip -j BAD_IP
$IPTABLES -A SHUN -d $ip -j BAD_IP
done
#-------------------------------------------------------------------------
# IN_IP_CHECKチェイン。送信元IPアドレスがありえないものなら
# BAD_IPチェインに渡す
#-------------------------------------------------------------------------

$IPTABLES -N IN_IP_CHECK

#送信元IPアドレスが変数 BADIP にあるものならBAD_IPチエインに渡す
for sip in $BADIP
do
$IPTABLES -A IN_IP_CHECK -s $sip -j BAD_IP
done

#それぞれのポートから入るパケットで、ありえない送信元IPアドレスなら、
#BAD_IPチエインへ
$IPTABLES -A IN_IP_CHECK -i $WAN_PORT -s $DMZ_NET -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $WAN_PORT -s $LAN_NET -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $DMZ_PORT -s $WAN_IP  -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $DMZ_PORT -s $LAN_IP  -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $LAN_PORT -s $WAN_IP  -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $LAN_PORT -s $DMZ_NET -j BAD_IP

#------------------------------------------------------------------------
# OUT_IP_CHECKチェイン。送信先、送信元IPアドレスが正しくなければ
# BAD_IPチエインに渡す
#------------------------------------------------------------------------

$IPTABLES -N OUT_IP_CHECK

#送信先IPアドレスが変数 BADIP にあるものならBAD_IPチェインに渡す
for dip in $BADIP
do
$IPTABLES -A OUT_IP_CHECK -d $dip -j BAD_IP
done

#それぞれのポートから出るパケットで、送信元IPが正しければこのチェインは通過。
#正しくなければBAD_IPチェインに渡す
$IPTABLES -A OUT_IP_CHECK -o $WAN_PORT -s $WAN_IP  -j RETURN
$IPTABLES -A OUT_IP_CHECK -o $LAN_PORT -s $LAN_NET  -j RETURN
$IPTABLES -A OUT_IP_CHECK -o $DMZ_PORT -s $DMZ_NET  -j RETURN
$IPTABLES -A OUT_IP_CHECK -j BAD_IP


#------------------------------------------------------------------------
# CHKMSNETチェイン。Microsoftネットワーク関連のFORWARD拒否。
#------------------------------------------------------------------------

$IPTABLES -N CHKMSNET
$IPTABLES -A CHKMSNET -p tcp --dport 42 -j DROP # wins dup
$IPTABLES -A CHKMSNET -p tcp --dport 135 -j DROP # MS-RPC
$IPTABLES -A CHKMSNET -p udp --dport 135 -j DROP # MS-RPC
$IPTABLES -A CHKMSNET -p udp --dport 137:138 -j DROP # MS browse
$IPTABLES -A CHKMSNET -p udp --dport 137:138 -j DROP # MS browse
$IPTABLES -A CHKMSNET -p tcp --dport 139 -j DROP # SMB
$IPTABLES -A CHKMSNET -p tcp --dport 445 -j DROP # DHSMB

#------------------------------------------------------------------------
# BADFLAGSチェイン。望ましくないTCPフラグならばログに残して破棄。
#------------------------------------------------------------------------

$IPTABLES -N BADFLAGS< br />$IPTABLES -A BADFLAGS -j LOG --log-prefix "IPTABLES BADFLAGS: " $LOGOPT
$IPTABLES -A BADFLAGS -j DROP

#------------------------------------------------------------------------
# TCPフラグの検査。望ましくないTCPフラグならBADFLAGSチェインに渡す。
#------------------------------------------------------------------------
echo "tcp flag"
$IPTABLES -N TCP_FLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ACK,FIN FIN -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ACK,PSH PSH -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ACK,URG URG -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags FIN,RST FIN,RST -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags SYN,FIN SYN,FIN -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags SYN,RST SYN,RST -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL ALL -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL NONE -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL FIN,PSH,URG -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j BADFLAGS

#------------------------------------------------------------------------
# SYN_FLOODチェイン。しきい値以上のタイミングでパケットがきたら
# SYNフラッド攻撃としてログに残した上で拒否する。
#------------------------------------------------------------------------
echo "syn flood"
$IPTABLES -N SYN_FLOOD
$IPTABLES -A SYN_FLOOD -p   tcp   --syn $SYNOPT -j RETURN
$IPTABLES -A SYN_FLOOD -p ! tcp                 -j RETURN
$IPTABLES -A SYN_FLOOD -p   tcp ! --syn         -j RETURN
$IPTABLES -A SYN_FLOOD -j LOG --log-prefix "IPTABLES SYN_FLOOD: " $LOGOPT
$IPTABLES -A SYN_FLOOD -j DROP

#------------------------------------------------------------------------
# IN_ICMPチェイン。入ってくるICMPが害のあるものならログに残して拒否
#------------------------------------------------------------------------
echo "inbound icmp"
$IPTABLES -N IN_ICMP

#変数 PING に指定されるネットワークからのpingには応答する。
for sip in $PING
do
$IPTABLES -A IN_ICMP  -p icmp --icmp-type echo-request -s $sip   -j ACCEPT
$IPTABLES -A FORWARD_FROM_WAN -o $DMZ_PORT -p tcp --dport $i -j ACCEPT
$IPTABLES -A IN_ICMP  -p icmp --icmp-type echo-reply   -s $sip   -j ACCEPT
done

#ネットワーク管理上必要なicmpパケットは許可する。ないものは拒否。
$IPTABLES -A IN_ICMP  -p icmp --icmp-type destination-unreachable  -j ACCEPT
$IPTABLES -A IN_ICMP  -p icmp --icmp-type source-quench            -j ACCEPT
$IPTABLES -A IN_ICMP  -p icmp --icmp-type time-exceeded            -j ACCEPT
$IPTABLES -A IN_ICMP  -p icmp --icmp-type parameter-problem        -j ACCEPT
$IPTABLES -A IN_ICMP -j LOG --log-prefix "IPTABLES In ICMP: " $LOGOPT
$IPTABLES -A IN_ICMP -j DROP

#------------------------------------------------------------------------------
# OUT_ICMPチェイン。出て行くICMPが害のあるものならログに残して拒否
#------------------------------------------------------------------------------
echo "outbound icmp"
$IPTABLES -N OUT_ICMP

#送信先が変数 PING に登録されていれば許可
for dip in $PING
do
$IPTABLES -A OUT_ICMP -p icmp --icmp-type echo-request -d $dip     -j ACCEPT
$IPTABLES -A OUT_ICMP -p icmp --icmp-type echo-reply   -d $dip     -j ACCEPT
done

#ネットワーク管理上必要なicmpパケットは許可する。ないものはログに残して拒否。
$IPTABLES -A OUT_ICMP -p icmp --icmp-type fragmentation-needed -j ACCEPT
$IPTABLES -A OUT_ICMP -p icmp --icmp-type source-quench            -j ACCEPT
$IPTABLES -A OUT_ICMP -p icmp --icmp-type parameter-problem        -j ACCEPT
$IPTABLES -A OUT_ICMP -j LOG --log-prefix "IPTABLES Out ICMP: " $LOGOPT
$IPTABLES -A OUT_ICMP -j DROP

#------------------------------------------------------------------------------
# DROPPACKETチェイン。不正なパケットをログに記録して破棄
#------------------------------------------------------------------------------
echo "droppacket"
$IPTABLES -N DROPPACKET # DROPPACKTチェインの作成
$IPTABLES -A DROPPACKET -j LOG --log-prefix "INVALID_PACKET: " $LOGOPT
$IPTABLES -A DROPPACKET -j DROP

#------------------------------------------------------------------------------
# FORWARD_BEFORE_CHECKチェイン。FORWARD前の不正なパケットでないかをチェック
#------------------------------------------------------------------------------
echo "checking before forward"
$IPTABLES -N FORWARD_BEFORE_CHECK

# LANから外部へフォワードされるMicrosoftネットワークのチェック
$IPTABLES -A FORWARD_BEFORE_CHECK -o $WAN_PORT -j CHKMSNET

# ブラックホールルータ対策
$IPTABLES -A FORWARD_BEFORE_CHECK -o $WAN_PORT -p tcp --tcp-flags SYN,RST \
SYN -j TCPMSS --clamp-mss-to-pmtu

# PINGについてのチェック
$IPTABLES -A FORWARD_BEFORE_CHECK -p icmp -j IN_ICMP
$IPTABLES -A FORWARD_BEFORE_CHECK -p icmp -j OUT_ICMP
# TCPのフラグが正しいかをチェック
$IPTABLES -A FORWARD_BEFORE_CHECK -p tcp -j TCP_FLAGS
# SYN_FLOOD攻撃でないかをチェック
$IPTABLES -A FORWARD_BEFORE_CHECK -p tcp --syn -j SYN_FLOOD

#------------------------------------------------------------------------------
# FORWARD_FROM_WANチェイン。WANポートから来たパケットのFORWARDについての設定
#------------------------------------------------------------------------------
echo "from wan port"
$IPTABLES -N FORWARD_FROM_WAN

# 外部からDMZへの接続で、接続済みのもののFORWARDを許可
$IPTABLES -A FORWARD_FROM_WAN -o $DMZ_PORT -m state --state \
ESTABLISHED,RELATED -j ACCEPT

for i in $DMZ_SVC_TCP
do
# 外部からDMZへの新規接続で、サービスをしているもののFORWARDを許可(tcp)
$IPTABLES -A FORWARD_FROM_WAN -o $DMZ_PORT -p tcp --dport $i -j ACCEPT
done

for i in $DMZ_SVC_UDP
do
# 外部からDMZへの新規接続で、サービスをしているもののFORWARDを許可(udp)
$IPTABLES -A FORWARD_FROM_WAN -o $DMZ_PORT -p udp --dport $i -j ACCEPT
done

# 外部からLANへの接続で、接続済みのもののFORWARDを許可 図5
$IPTABLES -A FORWARD_FROM_WAN -o $LAN_PORT -d $LAN_NET -m state --state \
ESTABLISHED,RELATED -j ACCEPT

#------------------------------------------------------------------------------
# FORWARD_FROM_DMZチェイン。DMZポートから来たパケットのFORWARDについての設定。
#------------------------------------------------------------------------------
echo "from dmz port"
$IPTABLES -N FORWARD_FROM_DMZ

#DMZから外部への接続を許可
$IPTABLES -A FORWARD_FROM_DMZ -o $WAN_PORT -s $DMZ_NET -m state --state \
NEW,ESTABLISHED,RELATED -j ACCEPT

#DMZからLANへの、接続済みのもののみ許可
$IPTABLES -A FORWARD_FROM_DMZ -o $LAN_PORT -s $DMZ_NET -m state --state \
ESTABLISHED,RELATED -j AC CEPT

#------------------------------------------------------------------------------
# FORWARD_FROM_LANチェイン。LANポートから来たパケットのFORWARDについての設定
#------------------------------------------------------------------------------
echo "from lan port"
$IPTABLES -N FORWARD_FROM_LAN

# LAN内からDMZへの接続を許可
$IPTABLES -A FORWARD_FROM_LAN -o $DMZ_PORT -s $LAN_NET -m state --state \
NEW,ESTABLISHED,RELATED -j ACCEPT
# LAN内から外部への接続を許可
$IPTABLES -A FORWARD_FROM_LAN -o $WAN_PORT -s $LAN_NET -m state --state \
NEW,ESTABLISHED,RELATED -j ACCEPT

#------------------------------------------------------------------------------
# INPUT_FIREWALLチェイン。INPUTチェインの基本的なルール。
#------------------------------------------------------------------------------
echo "input chain"
$IPTABLES -N INPUT_FIREWALL

#icmpのチェック
$IPTABLES -A INPUT_FIREWALL -p icmp -j IN_ICMP
#TCPフラグのチェック
$IPTABLES -A INPUT_FIREWALL -p tcp -j TCP_FLAGS
#SYNフラッド攻撃かをチェック
$IPTABLES -A INPUT_FIREWALL -p tcp --syn -j SYN_FLOOD
#IPアドレスが正当化をチェック
$IPTABLES -A INPUT_FIREWALL -j IN_IP_CHECK
# パケットの正当性チェック
$IPTABLES -A INPUT_FIREWALL -m state --state INVALID -j DROPPACKET
# 接続済みの入力を許可
$IPTABLES -A INPUT_FIREWALL -m state --state ESTABLISHED,RELATED -j ACCEPT
# AUTHリクエストを拒否
$IPTABLES -A INPUT_FIREWALL -p tcp --dport 113 -j REJECT --reject-with tcp-reset
#ログに残す
$IPTABLES -A INPUT_FIREWALL -j LOG --log-prefix "UNDEFIND_INPUT: " $LOGOPT

#------------------------------------------------------------------------------
# OUTPUT_FIREWALLチェイン。OUTPUTチェインの基本的なルール。
#------------------------------------------------------------------------------
echo "output chain"
$IPTABLES -N OUTPUT_FIREWALL
#icmpパケットのチェック
$IPTABLES -A OUTPUT_FIREWALL -p icmp -j OUT_ICMP
# TCPフラグのチェック
$IPTABLES -A OUTPUT_FIREWALL -p tcp -j TCP_FLAGS
#ipアドレスのチェック
$IPTABLES -A OUTPUT_FIREWALL -j OUT_IP_CHECK

# 出力を許可
$IPTABLES -A OUTPUT_FIREWALL -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# 上記以外のパケットはログに記録(デフォルトポリシーで破棄)
$IPTABLES -A OUTPUT_FIREWALL -j LOG --log-prefix "UNDEFIND_OUTPUT: " $LOGOPT

##########################################################################
# IPマスカレード
##########################################################################
echo "masquerade"
# DMZからの外部へのIPマスカレード(SNAT)の許可
$IPTABLES -t nat -A POSTROUTING -s $DMZ_NET -o $WAN_PORT -j MASQUERADE
# LANからの外部へのIPマスカレード(SNAT)の許可
$IPTABLES -t nat -A POSTROUTING -s $LAN_NET -o $WAN_PORT -j MASQUERADE

##########################################################################
# DMZへの転送~DNAT(静的NAT)
##########################################################################
echo "dnat"

for i in $DMZ_SVC_TCP # DMZで公開するポートの設定(tcp)
do
# WANからの接続要求をDMZに転送する(tcp)
$IPTABLES -t nat -A PREROUTING -i $WAN_PORT -p tcp --dport $i \
-j DNAT --to-destination $DMZ_SVR
done

for i in $DMZ_SVC_UDP # DMZで公開するポートの設定(tcp)
do
# WANからの接続要求をDMZに転送する(tcp)
$IPTABLES -t nat -A PREROUTING -i $WAN_PORT -p udp --dport $i \
-j DNAT --to-destination $DMZ_SVR
done

########################################################################
#メインのファイアウォールルール。プログラムで言うmain関数。
########################################################################
echo "main firewall -- forward"
$IPTABLES -A FORWARD                    -j FORWARD_BEFORE_CHECK
$IPTABLES -A FORWARD                    -j SHUN
$IPTABLES -A FORWARD -i $WAN_PORT -j FORWARD_FROM_WAN
$IPTABLES -A FORWARD -i $DMZ_PORT -j FORWARD_FROM_DMZ
$IPTABLES -A FORWARD -i $LAN_PORT -j FORWARD_FROM_LAN
$IPTABLES -A FORWARD -j LOG --log-prefix "IPTABLES DROP FORWARD: " $LOGOPT
$IPTABLES -A FORWARD -j DROP
echo "main firewall -- input"
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A INPUT              -j SHUN
$IPTABLES -A INPUT -j INPUT_FIREWALL
$IPTABLES -A INPUT -j LOG --log-prefix "IPTABLES DROP INPUT: " $LOGOPT
$IPTABLES -A INPUT -j DROP
echo "main firewall -- output"
$IPTABLES -A OUTPUT -o lo -j ACCEPT
$IPTABLES -A OUTPUT         -j SHUN
$IPTABLES -A OUTPUT -j OUTPUT_FIREWALL
$IPTABLES -A OUTPUT -j LOG --log-prefix "IPTABLES DROP OUTPUT: " $LOGOPT
$IPTABLES -A OUTPUT -j DROP

ポートスキャンによるチェック

sygate online serviceから、「Quick Scan」を行って、サービスを提供しているものは「OPEN」、していないものは「BLOCKED」「CLOSED」になっているはずです。なっていなければ、早急にスクリプトを見直してみましょう。

設定を保存する

現在のiptablesの設定を保存することで、次回サーバ起動時に自動的に現在の設定を読まれます。

# /etc/init.d/iptables save

で、現在の設定(スクリプトの内容)が保存されます。また、「デスクトップ」→「管理」→「サービスの設定」で、iptablesを起動時にスタートするようにしましょう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です