#! /bin/bash # 注意: 配列を使っているのでBourne Shellでは動作しません。要Bash等。 #E=echo export LANG=C # ■ブロードバンドルータと組み合わせて使うフィルタリングルール■ # # ブロードバンドルータのいわゆるDMZ機能を使い、 # 外部からの通信はすべてLinuxサーバに向ける。 # パケットフィルタリングはLinux側で行う。 # ■ポリシー■ # ・クラッカー/マナー違反の所からは接続させない。 # ・ソースアドレスがプライベートな通信がルータ側から開始されたら、 # ルータの syslog や ntp 等必要最小限のもの以外は無視。 # ・外部に提供するサービスは許可。 # ・特定の相手にのみ提供するサービスを許可。 # ・固定IPアドレスサービスで ISP から割り当てられているIPアドレス向けへの # 通信は自分当てにリダイレクト。 # ・squid で透過プロキシ。 # ・あとは、接続確立中の通信は許可するが、他はログ残して捨てる。 # ■その他■ # ・最近のネットゲームはクライアント側から TCPで接続するので、特別なルールは # 記述しないことにする。 # ・IPマスカレードはしない。(ルータに任せる) ############################################################################### #============================================================================== # このスクリプトの説明 #------------------------------------------------------------------------------ # Linuxサーバの上流にルータを2つ接続するためのフィルタリングルール。 # 別途iproute2で設定してトラフィックの分散を図る。 #============================================================================== # Router-A: ルータ :Router-B # ISP-A: ISP :ISP-B # 固定: IPアドレス :可変 #------------------------------------------------------------------------------ IP_ROUTER1=192.168.0.253 ;IP_ROUTER2=192.168.1.253 MAC_ROUTER1=AA:AA:AA:AA:AA:AA ;MAC_ROUTER2=BB:BB:BB:BB:BB:BB IP_GLOBAL1=XXX.XXX.XXX.XXX ;IP_GLOBAL2= IP_WAN1=192.168.0.254 ;IP_WAN2=192.168.1.254 #未使用? IF_WAN1=eth1 ;IF_WAN2=eth2 #未使用? #============================================================================== # LAN #------------------------------------------------------------------------------ IP_LAN=192.168.2.254 IF_LAN=eth0 #============================================================================== # その他設定 #------------------------------------------------------------------------------ #USE_MASQUERADE=yes #IF_PPP=ppp0 #============================================================================== #============================================================================== # パケットを受け付けるルールを追加する関数 # Usage: Accept SRCs TYPE PORTs # SRCs = IPアドレスブロックまたはそれをカンマ区切りで列挙する # TYPE = tcp, udp, icmp, all のいずれか # PORTs = ポート番号、ポート番号をカンマ区切りで列挙、ポート範囲のいずれか # # 注意: ポート番号を列挙する場合 multiport モジュールを使用するため # ポート番号の列挙は15個まで。また列挙に範囲を含めてはいけない。 #------------------------------------------------------------------------------ Accept () { srcs=$1 type=$2 ports=$3 for src in `echo $srcs | sed 's/,/ /g'` do case $ports in *,*) $E iptables -A INPUT -s $src -p $type -m multiport --dports $ports -j ACCEPT ;; *) $E iptables -A INPUT -s $src -p $type --dport $ports -j ACCEPT ;; esac done } #IF_WAN1の方のみ許可する。 Accept1 () { srcs=$1 type=$2 ports=$3 for src in `echo $srcs | sed 's/,/ /g'` do case $ports in *,*) $E iptables -A INPUT -i $IF_WAN1 -s $src -p $type -m multiport --dports $ports -j ACCEPT ;; *) $E iptables -A INPUT -i $IF_WAN1 -s $src -p $type --dport $ports -j ACCEPT ;; esac done } #IF_WAN2の方のみ許可する。 Accept2 () { srcs=$1 type=$2 ports=$3 for src in `echo $srcs | sed 's/,/ /g'` do case $ports in *,*) $E iptables -A INPUT -i $IF_WAN2 -s $src -p $type -m multiport --dports $ports -j ACCEPT ;; *) $E iptables -A INPUT -i $IF_WAN2 -s $src -p $type --dport $ports -j ACCEPT ;; esac done } #============================================================================== #============================================================================== # パケットを自分自身にリダイレクトするルールを追加する関数 # # Usage: Redirect TYPE PORTs # TYPE = tcp, udp, icmp, all のいずれか # PORTs = ポート番号、ポート範囲、それらをカンマ区切りで列挙 # # 注意: リダイレクト対象は IP_GLOBAL1 宛の通信のみ。 # IPアドレス固定の方を IP_GLOBAL1 に指定すること。 # この関数では multiport モジュールは使用しないので # 列挙したポートの数だけルールが追加される。 #------------------------------------------------------------------------------ Redirect () { type=$1 ports=$2 for port in `echo $ports | sed 's/,/ /g'` do $E iptables -t nat -A PREROUTING -i $IF_LAN -p $type -d $IP_GLOBAL1 \ --dport $port -j DNAT --to-destination $IP_LAN:$port done } #============================================================================== #============================================================================== # パケットを積極的に破棄するルールを追加する関数 # Usage: Drop SRCs # SRCs = IPアドレスブロックまたはそれをカンマ区切りで列挙する #------------------------------------------------------------------------------ Drop () { srcs=$1 for src in `echo $srcs | sed 's/,/ /g'` do $E iptables -A INPUT --source $src -j cracker done } #============================================================================== #============================================================================== # 特定の送信先ポート宛のパケットを別のマシンにDNATするための関数。 # DNATの設定およびパケットの受信許可の2つを設定を行う。 # 自分がPPPを喋らない場合は通常使用しない。(ルータ側で設定するはず) # 使用例: 古いネットゲームやBitTorrent等、外から接続を開始してくる通信を # そのクライアントが動作しているマシンへ静的NATする。 #------------------------------------------------------------------------------ StaticNATdest () { protocol=$1 src=$2 destport=$3 dest=$4 $E iptables -t nat -A PREROUTING -i $IF_PPP -p $protocol \ -s $src --dport $destport -j DNAT --to-destination $dest $E iptables -A FORWARD -p $protocol -s $src -d $dest \ --dport $destport -j ACCEPT } #============================================================================== #============================================================================== # 特定の送信元ポート宛のパケットを別のマシンにDNATするための関数。 # DNATの設定およびパケットの受信許可の2つを設定を行う。 # 自分がPPPを喋らない場合は通常使用しない。(ルータ側で設定するはず) # 使用例: さて…なんでしょうね(笑) #------------------------------------------------------------------------------ StaticNATsrc () { protocol=$1 src=$2 srcport=$3 dest=$4 $E iptables -t nat -A PREROUTING -i $IF_PPP -p $protocol \ -s $src --sport $srcport -j DNAT --to-destination $dest $E iptables -A FORWARD -p $protocol -s $src -d $dest \ --sport $srcport -j ACCEPT } #============================================================================== #============================================================================== # モジュールの明示的組み込みなど #------------------------------------------------------------------------------ $E modprobe -r ipchains $E modprobe ip_conntrack #============================================================================== #============================================================================== # 古いルールを削除するための情報収集。 # ルールを更新する手順は次のようになる。 # 1.チェイン毎に現在のルールの数を数える iptables -L チェイン名 # 2.新ルールを末尾に追加していく iptables -A チェイン名 # 3.現在のルールを1.の数だけ末尾から削除する iptables -D チェイン名 番号 #------------------------------------------------------------------------------ # 0 1 2 3 4 5 6 CHAIN=(block cracker INPUT OUTPUT FORWARD POSTROUTING PREROUTING) CHAINNUM=6 for i in `seq 0 $CHAINNUM` do chain=${CHAIN[$i]} echo "# get number of current rule in $chain chain" # natやmangleテーブルへのチェインも盛り込む場合はここを修正する。 if [ $chain = "POSTROUTING" -o $chain = "PREROUTING" ] then opt="-t nat" else opt="" fi RULENUM[$i]=`iptables $opt -L $chain -n | tail +3 | wc -l` done # debug print echo "# number of rules:" for i in `seq 0 $CHAINNUM` do printf "# %12s = %3d\n" ${CHAIN[$i]} ${RULENUM[$i]} done #============================================================================== #============================================================================== # block チェイン: Accept() や Redirect() 等で明示的に受け付けた通信 # 以外のパケットが最終的に入ってくるチェイン。 #------------------------------------------------------------------------------ $E iptables -N block # 確立済みおよびそれに関係するコネクションは通過する。 $E iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT # 内部からの新しいコネクションは受け付ける $E iptables -A block -m state --state NEW -i $IF_LAN -j ACCEPT $E iptables -A block -m state --state NEW -i lo -j ACCEPT # tcp/udp 135,137,139,445 は即座に捨ててログに残さない(多すぎる…) $E iptables -A block -m multiport -p tcp --destination-ports 135,137,139,445 -j DROP $E iptables -A block -m multiport -p udp --destination-ports 135,137,139,445 -j DROP # あんまり嬉しくないものはログに残す $E iptables -A block -j LOG --log-level info --log-prefix 'iptables: ' # traceroute を受け付ける設定 $E iptables -A block -p udp --sport 30000:65535 --dport 30000:65535 -j ACCEPT # ping を受け付ける設定 $E iptables -A block -p icmp --icmp-type 8 -m limit --limit 1/s -j ACCEPT # 最後に、捨てます $E iptables -A block -j REJECT -p tcp --reject-with tcp-reset $E iptables -A block -j DROP #============================================================================== #============================================================================== # cracker チェイン: 明示的にパケットを捨てるためのチェイン。 # クラッカーとか変な通信を仕掛けてくるホスト用。 #------------------------------------------------------------------------------ $E iptables -N cracker # とりあえずログに残す $E iptables -A cracker -j LOG --log-level info --log-prefix 'iptables: (cracker) ' # そして即座に捨てる $E iptables -A cracker -j DROP #============================================================================== #============================================================================== # 接続を拒否するサイトのブラックリスト #------------------------------------------------------------------------------ # もうすぐ検索サービスを停止するらしい所の腐れロボット対策 Drop 218.145.25.0/24,61.78.61.0/24,220.73.0.0/16,64.203.129.94 # 逆引きもまともに設定できない会社のアホロボット対策 Drop 64.124.85.0/24 #============================================================================== #============================================================================== # ルータ(あるいはルータ役のPC)からのsyslog等を受信する設定。 # この後でWAN側からのソースアドレスがプライベートな通信を拒否するので # その前に設定する。 # ルータから開始する通信が他にもあるようならここで設定する。 #------------------------------------------------------------------------------ # ROUTER1 ntp,syslog Accept1 $IP_ROUTER1 udp 123,514 #============================================================================== #============================================================================== # WAN側からソースアドレスがプライベートな通信があったら拒否。 #------------------------------------------------------------------------------ $E iptables -A INPUT -i $IF_WAN1 --source 192.168.0.0/16 -j block $E iptables -A INPUT -i $IF_WAN1 --source 172.16.0.0/12 -j block $E iptables -A INPUT -i $IF_WAN1 --source 10.0.0.0/8 -j block if [ x"$IF_WAN2" != x"" ] then $E iptables -A INPUT -i $IF_WAN2 --source 192.168.0.0/16 -j block $E iptables -A INPUT -i $IF_WAN2 --source 172.16.0.0/12 -j block $E iptables -A INPUT -i $IF_WAN2 --source 10.0.0.0/8 -j block fi #============================================================================== #============================================================================== # IPマスカレードの設定 (ルータ等がなく、自分がPPPoE等を喋っている場合) #------------------------------------------------------------------------------ if [ x"$USE_MASQUERADE" = x"yes" ] then $E iptables -t nat -A POSTROUTING -o $IF_PPP -j MASQUERADE fi #============================================================================== #============================================================================== # どこからでも接続を受け付ける (外部向けサービスなど) #------------------------------------------------------------------------------ # smtp,www Accept1 0.0.0.0/0 tcp 25,80 # domain Accept1 0.0.0.0/0 udp 53 #============================================================================== #============================================================================== # 特定の所からのみ接続を受け付ける #------------------------------------------------------------------------------ # NNTP feed Accept1 AAA.AAA.AAA.AAA tcp 119 # # Name Server (Primary/Secondary) Accept1 BBB.BBB.BBB.BBB tcp 53 #============================================================================== #============================================================================== # 対外サーバの固定IPアドレスへの通信をリダイレクトする。 # これをやらないと最悪一旦ISPのルータまでパケットがいってしまう。 #------------------------------------------------------------------------------ Redirect tcp 25,80 #============================================================================== #============================================================================== # squidの透過プロキシの設定 #------------------------------------------------------------------------------ $E iptables -t nat -A PREROUTING -i $IF_LAN -p tcp --dport 80 \ -j REDIRECT --to-port 1234 #============================================================================== #============================================================================== # StaticNATdest / StaticNATsrc のルールを記述する場合はここに書く。 #------------------------------------------------------------------------------ # for old NetGame (Diablo II) # protocol srcaddr destport targetaddr #StaticNATdest udp 63.241.83.0/28 6112:6119 192.168.2.1 #StaticNATdest tcp 63.241.83.0/28 6112:6119 192.168.2.1 #StaticNATdest udp 63.241.83.0/28 4000 192.168.2.1 #StaticNATdest tcp 63.241.83.0/28 4000 192.168.2.1 # # for BitTorrent # protocol srcaddr destport targetaddr #StaticNATdest tcp 0.0.0.0/0 6881:6900 192.168.2.2 #============================================================================== #============================================================================== # 後始末。 # INPUT および FORWARD チェインを block チェインへ飛ばして不要な通信を拒否。 #------------------------------------------------------------------------------ $E iptables -A INPUT -j block $E iptables -A FORWARD -j block #============================================================================== # そしてパケット転送の設定。 #------------------------------------------------------------------------------ if [ x"$E" = x"echo" ] then $E "echo 1 > /proc/sys/net/ipv4/ip_forward" else echo 1 > /proc/sys/net/ipv4/ip_forward fi #============================================================================== # 最後に、古いルールの削除。 #------------------------------------------------------------------------------ for i in `seq 0 $CHAINNUM` do chain=${CHAIN[$i]} echo "# delete old rules in $chain chain" if [ $chain = "POSTROUTING" -o $chain = "PREROUTING" ] then opt="-t nat" else opt="" fi num=${RULENUM[$i]} for j in `seq $num -1 1` do $E iptables $opt -D $chain $j done done #==============================================================================