iptablesをフィルタを組み合わせてロールベースで設定管理する高機能スクリプト「iptables-firewall」

iptables-firewallはIPホワイトリスト、国別制限、Firewall、IDS/IPSなどの各種自動生成されるフィルタを用途ごとに自由に組み合わせてルールセットを作成し、任意のロールとして設定・運用することで厳格かつ柔軟なアクセス制御機構を実装するスクリプトです。

導入

GitHub - falsandtru/iptables-firewall: iptables rule generating and management script.

=======================
  PACKET FLOW EXAMPLE
=======================

== config ==
  ROLES=(SSH)
  SSH=(BLOCK_COUNTRY "file{1,2}|TRACK_PROWLER|DROP" LOCAL_COUNTRY FIERWALL IPF "IPS|LOG...|DROP")
  ...
  MAP=("${MAP[@]}" "INPUT -p tcp --dport 60022 -j SSH")
  MAP=("${MAP[@]}" "INPUT -j TRAP_PORTSCAN")
  MAP=("${MAP[@]}" "FORWARD -j TRAP_PORTSCAN")


== apply ==
            INTERNET
        ______ V ______________________________________________________    _______
INPUT  |               | TCP UDP ICMP                                  |  |       |
       |   TCP 60022   |       TRAP_PORTSCAN  ( --> TRACK_PROWLER  )  --->| POLICY|
       |               |                                               |  |       |
       |====== | ======|===============================================|  |_______|
       |====== V ======|===============================================|   _______
Layer1 |                                                               |  |       |
       |                          BLOCK_COUNTRY                       --->|       |
       |______________________________ V ______________________________|  |       |
Layer2 | Rule1         | Rule101       | Rule201       | Rule202       |  |       |
       |     file1    -->    file2    -->TRACK_PROWLER-->    DROP     --->|       |
       |______ V ______|______ V ______|______ V ______|_______________|  | BLOCK |
Layer3 |                                                               |  |       |
       |                          LOCAL_COUNTRY                       --->|       |
       |______________________________ V ______________________________|  |       |
Layer4 |                                                               |  |       |
       |                            FIERWALL  ( --> TRACK_ATTACKER )  --->|       |
       |______________________________ V ______________________________|  |       |
Layer5 |                                                               |  |       |
       |                              IPF  ( ANTI_PROWLER/ATTACKER )  --->|       |
       |______________ V ______________________________________________|  |       |
Layer6 |                               |               |               |  |       |
       |            IDS/IPS           -->     LOG     -->     DROP    --->|       |
       |                               |               |               |  |       |
       |============== | ==============================================|  |_______|
       |============== V ==============================================|
SERVICE|                                                               |
       |                      === SSH SERVICE ===                      |
       |_______________________________________________________________|

特徴

ロールベースコントロール

ロールにより適用するルールをまとめられるため、用途にあわせてルールを設定する現実の実務モデルに則した運用を手軽に実施できます。

初期設定ではGLOBAL/LOCAL/CONNECTION/SYSTEM/NETWORK/AUTH/PRIVATE/CUSTOMER/PUBLICロールが定義されています。

# TESTロールを作成
ROLES=(TEST)
...
......
# TESTロールを適用
MAP=("${MAP[@]}" "INPUT -p tcp --dport 8080 -j TEST")

マルチレイヤフィルタリング

ロールに設定するルールセットは、ホワイトリスト、国別制限、Firewall、IDS/IPSなどから選択した各種フィルタを組み合わせた順に適用していくマルチレイヤフィルタとして動作します。

# TESTロールにルールを設定
TEST=(whitelist/private LOCAL_COUNTRY FIREWALL IPF IPS ACCEPT)
# 1. whitelist/private
# ファイルに記述されたIPのみ通過させ、ほかは遮断する。
#
# 2. LOCAL_COUNTRY
# 許可した国のIPのみ通過させ、ほかは遮断する。
#
# 3. FIREWALL
# Firewallを適用し接続を検疫する。
#
# 4. IPF
# 攻撃行為または不審行為のあったIPを遮断する。
#
# 5. IPS
# 指定のパケットをIPSへ渡し処理を終える。
#
# 6. ACCEPT
# 渡されなかった残りのパケットをすべて許可し処理を終える。
#

機能

ホワイトリスト

IPを記載したファイルから記載されているIPのみを通過させるフィルタを生成し、ホワイトリストによる厳格なアクセス制限を行います。

# 1. whitelist/private
# ファイルに記載されたIPのみ通過させ、ほかは遮断する。
#

国別フィルタ(特定国禁止/日本国内限定等制限)

アクセス可能な国を日本国内のみ等特定の国のみに制限、および特定の国からの全アクセスを禁止遮断します。IPと国との対応は割り当ての実施組織である地域レジストリから自動的に取得し適用されます。

# 許可 日本
LOCAL_COUNTRY_CODE="JP"

# 拒否 中国|香港|マカオ|韓国|北朝鮮
BLOCK_COUNTRY_CODE="CN|HK|MO|KR|KP"
# 2. LOCAL_COUNTRY
# 許可した国のIPのみ通過させ、ほかは遮断する。。
#

Firewall

各種Firewall機能を利用できます。

# 3. FIREWALL
# Firewallを適用し接続を検疫する。
#

PortscanTrap

公開していないポートにアクセスを試みたIPをIPFにより遮断するIPとして追跡します。

# 4. IPF
# 攻撃行為または不審行為のあったIPを遮断する。
#

IDS/IPS

IDSまたはIPSを導入している場合、これに処理を引き渡します。

# 5. IPS
# 指定のパケットをIPSへ渡し処理を終える。
#
# 6. ACCEPT
# 渡されなかった残りのパケットをすべて許可し処理を終える。
#

運用例

iptables-firewallはサーバーを利用する際に要求されるセキュリティ機能の確保に寄与します。

ポートスキャンの追跡

iptables-firewallはさくらのVPSでテスト運用されていますが、このサーバーは管理者自身しか利用していないにもかかわらず、ユニキャストによるポートスキャンを約10分に1回、1日に100回以上受けています。

Nov 17 19:59:37 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=178.33.x.x DST=133.242.x.x LEN=44 TOS=0x00 PREC=0x00 TTL=48 ID=38796 PROTO=TCP SPT=80 DPT=28612 WINDOW=16384 RES=0x00 ACK SYN URGP=0 
Nov 17 20:00:01 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=104.192.x.x DST=133.242.x.x LEN=28 TOS=0x08 PREC=0x00 TTL=234 ID=16288 PROTO=UDP SPT=40790 DPT=53413 LEN=8 
Nov 17 20:07:08 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=114.38.x.x DST=133.242.x.x LEN=60 TOS=0x00 PREC=0x00 TTL=50 ID=23942 DF PROTO=TCP SPT=59270 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0 
Nov 17 20:07:11 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=114.38.x.x DST=133.242.x.x LEN=60 TOS=0x00 PREC=0x00 TTL=50 ID=23943 DF PROTO=TCP SPT=59270 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0 
Nov 17 20:07:17 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=114.38.x.x DST=133.242.x.x LEN=60 TOS=0x00 PREC=0x00 TTL=50 ID=23944 DF PROTO=TCP SPT=59270 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0 
Nov 17 20:08:33 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=31.148.x.x DST=133.242.x.x LEN=40 TOS=0x10 PREC=0x00 TTL=245 ID=54321 PROTO=TCP SPT=46530 DPT=9064 WINDOW=65535 RES=0x00 SYN URGP=0 
Nov 17 20:18:34 www kernel: [IPTABLES INVALID] : IN=eth0 OUT= MAC=xx SRC=66.150.x.x DST=133.242.x.x LEN=76 TOS=0x00 PREC=0x00 TTL=50 ID=12979 PROTO=ICMP TYPE=3 CODE=3 [SRC=133.242.x.x DST=66.150.x.x LEN=48 TOS=0x00 PREC=0x00 TTL=125 ID=27360 PROTO=UDP SPT=27005 DPT=27015 LEN=28 ] 
Nov 17 20:33:11 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=66.114.x.x DST=133.242.x.x LEN=60 TOS=0x00 PREC=0x00 TTL=50 ID=9599 DF PROTO=TCP SPT=3618 DPT=23 WINDOW=5840 RES=0x00 SYN URGP=0 
Nov 17 20:33:17 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=66.114.x.x DST=133.242.x.x LEN=60 TOS=0x00 PREC=0x00 TTL=50 ID=9600 DF PROTO=TCP SPT=3618 DPT=23 WINDOW=5840 RES=0x00 SYN URGP=0 
Nov 17 20:35:12 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=178.33.x.x DST=133.242.x.x LEN=44 TOS=0x00 PREC=0x00 TTL=48 ID=50103 PROTO=TCP SPT=80 DPT=25596 WINDOW=16384 RES=0x00 ACK SYN URGP=0 
Nov 17 20:41:09 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=5.196.x.x DST=133.242.x.x LEN=44 TOS=0x00 PREC=0x00 TTL=46 ID=30348 PROTO=TCP SPT=443 DPT=55323 WINDOW=16384 RES=0x00 ACK SYN URGP=0 
Nov 17 20:43:19 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=111.249.x.x DST=133.242.x.x LEN=40 TOS=0x00 PREC=0x00 TTL=111 ID=256 DF PROTO=TCP SPT=12200 DPT=21320 WINDOW=8192 RES=0x00 SYN URGP=0 
Nov 17 20:43:41 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=8.8.x.x DST=133.242.x.x LEN=44 TOS=0x00 PREC=0x00 TTL=39 ID=48886 PROTO=TCP SPT=53 DPT=51501 WINDOW=42900 RES=0x00 ACK SYN URGP=0 

ポートスキャンからクラッキング

このような一見穏やかに見えるポートスキャンであっても、ポートを発見すると途端に秒間数回から数十回の総当たり攻撃や辞書攻撃を行いサーバーへ侵入しようとしてくるため放置すると非常に危険です。過去に8080番ポートでサーバー監視ツールを使用していた際に攻撃を受けました。

ホワイトリストの作成が困難な要件でのセキュリティ対応

サービスを少ない資本で運営している場合、こうした攻撃を避けようとSSHポートなどの重要機能へ接続可能なIPを制限しようとしてもプロバイダレベルまででしかIPの範囲を絞り込めず、社員の外出先や自宅からの接続を許可したい場合はそれすらも困難となります。

攻撃の遮断およびポートスキャンからのポート隠蔽

このような要件においても、国別フィルタで接続を日本国内に限定するとともに、ポートスキャンや攻撃を行ったIPを遮断するファイアウォールのオプション機能であるFW_INTRUDERによりポートを隠蔽することができます。また、攻撃を受けた場合でも攻撃を検知して以降の攻撃とアクセスを遮断します(※いずれも0-1023番以外のポートである必要がある)。

# e.g.
# 公開していないポートへのポートスキャンといった不審行為や攻撃を検知してIPを追跡
Nov 17 20:43:19 www kernel: [IPTABLES PORTSCAN] : IN=eth0 OUT= MAC=xx SRC=111.249.x.x DST=133.242.x.x LEN=40 TOS=0x00 PREC=0x00 TTL=111 ID=256 DF PROTO=TCP SPT=12200 DPT=21320 WINDOW=8192 RES=0x00 SYN URGP=0 
# 追跡中の不審なIPからの重要機能へのアクセスを遮断して公開ポートを保護・隠蔽
Nov 17 20:43:19 www kernel: [IPTABLES INTRUDER] : IN=eth0 OUT= MAC=xx SRC=111.249.x.x DST=133.242.x.x LEN=40 TOS=0x00 PREC=0x00 TTL=111 ID=256 DF PROTO=TCP SPT=12200 DPT=10022 WINDOW=8192 RES=0x00 SYN URGP=0 

サーバーのネットワークセキュリティ向上に

以上のように、iptables-firewallは実用的なネットワークセキュリティの導入を容易にします。

iptablesの設定でサーバー攻撃対策と海外からのアクセスを制限

中国韓国北朝鮮からのアクセスを禁止、SSHなど重要なポートへのアクセスを日本国内からのみに制限しつつ日本国内とその他の海外に対してウェブサイトを公開する設定例を紹介。Firewall機能を実装する各種攻撃対策も組み込み済み。

このスクリプト実行しとくだけでサーバーの侵入難易度が跳ね上がります。日本のボットサーバー削減にお役立てください。

最新版はGitHubで公開しています。

falsandtru/iptables-firewall · GitHub

大幅に改良した新バージョンをリリースしていますのでこちらをご利用ください。仕様を刷新しているためこのページ内容は最新版と互換性がありません。

iptables firewall

iptablesにFirewallとしての機能を実装します。

設定

  • 特定の外国からのアクセス拒否
  • 特定の外国を除くすべての国からのHTTPポートへのアクセスを許可(海外からアクセスできるのはHTTPポートのみ)
  • 日本国内からのみ特定のポートへのアクセスを許可
  • サーバーへの攻撃を防御

国別フィルタ機能

  • IPリストを自動更新
  • 全体で拒否する国を設定可能
  • 特定のポートにアクセス可能な国を別途制限可能

Firewall機能

  • BruteForce攻撃対策
  • PingOfDeath攻撃対策
  • DoS攻撃対策(TCP/UDP/ICMP全対応)
  • Spoofing攻撃対策
  • Ingress攻撃対策
  • ポートスキャン対策
  • ステルススキャン対策
  • ポートスキャントラップ
  • ブロードキャスト通信を遮断
  • マルチキャスト通信を遮断
  • 断片化パケットを遮断
  • NetBIOSとの通信を遮断
  • 過剰なロギングを防止

防御機能はチェーンごとにモジュール化されているため自由に組み替え可能。 ポートスキャントラップ機能は1時間以上の長い間隔でのポートスキャンも追跡防御できます。

ブラックリスト

ブラックリストのIPからのアクセスを拒否

ホワイトリスト

ブラックリスト、国別のIPによる制限から除外

厳格モード

ホワイトリストのIP以外からのアクセスを拒否

IDS/IPS防御連携

  • IDS/IPSとの接続設定を用意(Snort)

その他

  • 可読性の高い実行結果を出力
$ sudo sh /var/iptables/rule.sh
iptables firewall
UPDATE:         NO
NAMESERVER:     XX.XX.XX.XX
NTPSERVER:      XX.XX.XX.XX
FIREWALL:       ANTI_SPY                ACCEPT_FILTER
FIREWALL:       DENY_BROADCAST          INPUT
FIREWALL:       DENY_BROADCAST          FORWARD
FIREWALL:       ANTI_INGRESS            FORWARD
FIREWALL:       ANTI_SPOOFING           ACCEPT_FILTER
FIREWALL:       DENY_NETBIOS            ACCEPT_FILTER
FIREWALL:       DENY_FRAGMENT           ACCEPT_FILTER
FIREWALL:       ANTI_STEALTHSCAN        ACCEPT_FILTER
FIREWALL:       ANTI_PINGDEATH          ACCEPT_FILTER
FIREWALL:       ANTI_SYNFLOOD           ACCEPT_FILTER[TCP:80]
FIREWALL:       ANTI_SYNFLOOD_SSL       ACCEPT_FILTER[TCP:443]
FIREWALL:       ANTI_UDPFLOOD           ACCEPT_FILTER[UDP]
FIREWALL:       ANTI_ICMPFLOOD          ACCEPT_FILTER[ICMP]
FIREWALL:       ANTI_BRUTEFORCE         ACCEPT_FILTER[TCP]
IDS/IPS:        DISABLE
REUSE:          Chain COUNTRY_FILTER
REUSE:          Chain DROP_FILTER
OPEN:           HTTP[TCP:80]
OPEN:           HTTPS[TCP:443]
FIREWALL:       TRAP_PORTSCAN           INPUT[TCP/UDP/ICMP]
FIREWALL:       TRAP_PORTSCAN           FORWARD[TCP/UDP/ICMP]
iptables: ファイアウォールのルールを /etc/sysconfig/iptable[  OK  ]中: 
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
kernel.sysrq = 0
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.eth1.accept_redirects = 0
net.ipv4.conf.eth2.accept_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.eth1.accept_source_route = 0
net.ipv4.conf.eth2.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
complete
  • 可読性の高いルールを生成
$ sudo vi /etc/sysconfig/iptables
...
:TRAP_PORTSCAN - [0:0]
-A INPUT -i lo -j ACCEPT_FILTER
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT_FILTER
-A INPUT -s XX.XX.XX.XX/32 -p udp -m udp --dport 53 -j ACCEPT_FILTER
-A INPUT -s XX.XX.XX.XX/32 -p udp -m udp --dport 123 -j ACCEPT_FILTER
-A INPUT -j DROP_FILTER
-A INPUT -j FW_BROADCAST
-A INPUT -p icmp -m icmp --icmp-type 3 -j COUNTRY_FILTER
-A INPUT -p icmp -m icmp --icmp-type 4 -j COUNTRY_FILTER
-A INPUT -p icmp -m icmp --icmp-type 5 -j COUNTRY_FILTER
-A INPUT -p icmp -m icmp --icmp-type 11 -j COUNTRY_FILTER
-A INPUT -p icmp -m icmp --icmp-type 12 -j COUNTRY_FILTER
-A INPUT -p tcp -m multiport --dports 22 -j COUNTRY_FILTER
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT_FILTER
-A INPUT -p tcp -m tcp --dport 443 -j COUNTRY_FILTER
-A INPUT -j FW_PORTSCAN
-A FORWARD -i lo -j ACCEPT_FILTER
-A FORWARD -o lo -j ACCEPT_FILTER
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT_FILTER
-A FORWARD -s XX.XX.XX.XX/32 -p udp -m udp --dport 53 -j ACCEPT_FILTER
-A FORWARD -d XX.XX.XX.XX/32 -p udp -m udp --sport 53 -j ACCEPT_FILTER
-A FORWARD -s XX.XX.XX.XX/32 -p udp -m udp --dport 123 -j ACCEPT_FILTER
-A FORWARD -d XX.XX.XX.XX/32 -p udp -m udp --sport 123 -j ACCEPT_FILTER
-A FORWARD -j DROP_FILTER
-A FORWARD -j FW_BROADCAST
-A FORWARD -j FW_INGRESS
-A FORWARD -j FW_PORTSCAN
-A OUTPUT -o lo -j ACCEPT_FILTER
-A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT_FILTER
-A OUTPUT -d XX.XX.XX.XX/32 -p udp -m udp --sport 53 -j ACCEPT_FILTER
-A OUTPUT -d XX.XX.XX.XX/32 -p udp -m udp --sport 123 -j ACCEPT_FILTER
-A OUTPUT -j DROP_FILTER
-A ACCEPT_FILTER -j FW_SPY
-A ACCEPT_FILTER -j FW_SPOOFING
-A ACCEPT_FILTER -j FW_NETBIOS
-A ACCEPT_FILTER -j FW_FRAGMENT
-A ACCEPT_FILTER -j FW_STEALTHSCAN
-A ACCEPT_FILTER -j FW_PINGDEATH
-A ACCEPT_FILTER -j FW_SYNFLOOD
-A ACCEPT_FILTER -j FW_SYNFLOOD_SSL
-A ACCEPT_FILTER -j FW_UDPFLOOD
-A ACCEPT_FILTER -j FW_ICMPFLOOD
-A ACCEPT_FILTER -j FW_BRUTEFORCE
-A ACCEPT_FILTER -j ACCEPT
...

導入手順

$ sudo mkdir /var/cache/iptables
$ sudo touch /etc/cron.daily/iptables
$ sudo chmod 700 /etc/cron.daily/iptables
$ sudo vi /etc/cron.daily/iptables
$ sudo sh /etc/cron.daily/iptables

/etc/cron.daily/iptables

#!/bin/sh

#
# iptables firewall
# 
# @version 0.1.4
# @author falsandtru https://github.com/falsandtru/iptables-firewall/
# @copyright 2014, falsandtru
# @license MIT
#

#----------------------------------------------------------#
# Config                                                   #
#----------------------------------------------------------#

# 管理用ポート番号
LOGIN=0

# IPの更新間隔(日)
INTERVAL=7

# インタフェース名定義
LAN=eth0

# IPSの使用
IPS=

# 許可 日本
ACCEPT_COUNTRY_CODE="JP"

# 拒否 中国|香港|マカオ|韓国|北朝鮮
DROP_COUNTRY_CODE="CN|HK|MO|KR|KP"

# ブラックリスト/ホワイトリスト/厳格モード
BLACKLIST=
WHITELIST=
STRICT=false

# ログの最大生成間隔
LOG_LIMIT=6/m
LOG_LIMIT_BURST=10

# コマンド
IPTABLES=iptables

# IPリスト保存先ディレクトリ
CACHE_DIR=/var/cache/iptables/


#----------------------------------------------------------#
# AutoConfig                                               #
#----------------------------------------------------------#

echo "iptables firewall"

# SSHポート取得
[[ ! $LOGIN -gt 0 ]] && LOGIN=`cat /etc/ssh/sshd_config | grep '^Port ' | tail -n 1 | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/'`
echo "LOGIN:        $LOGIN"

# IPS設定
if [ ! $IPS ] || [ $IPS != false ]; then
    if [ `ps alx | grep -v grep | grep /snort | head -n 1 | cut -c1` ]; then
        IPS=Snort
    else
        IPS=false
    fi
fi

LOCALNET_MASK=`ifconfig $LAN|sed -e 's/^.*Mask:\([^ ]*\)$/\1/p' -e d`

# 内部ネットワークのネットマスク取得
LOCALNET_MASK=`ifconfig $LAN|sed -e 's/^.*Mask:\([^ ]*\)$/\1/p' -e d`

# 内部ネットワークアドレス取得
LOCALNET_ADDR=`netstat -rn|grep $LAN|grep $LOCALNET_MASK|cut -f1 -d' '`
LOCALNET=$LOCALNET_ADDR/$LOCALNET_MASK

# IP設定
NAMESERVERS=($(grep '^nameserver' /etc/resolv.conf | cut -d' ' -f2))
NTPSERVERS=($(grep '^server' /etc/ntp.conf | cut -d' ' -f2 | awk '{system("dig +short "$1)}'))


#----------------------------------------------------------#
# Download                                                 #
#----------------------------------------------------------#

WGET="/usr/bin/wget -N --retr-symlinks -P ${CACHE_DIR}"

if [ $STRICT = true ] || [[ $(find ${CACHE_DIR} -name delegated-*-extended-latest -ctime -$INTERVAL 2>&1) ]]; then
    UPDATE=0
    echo "UPDATE:       NO"
else
    UPDATE=1
    echo "UPDATE:       YES"
    $WGET ftp://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest
    $WGET ftp://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest
    $WGET ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-extended-latest
    $WGET ftp://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-extended-latest
    $WGET ftp://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest
fi


#----------------------------------------------------------#
# Initialize                                               #
#----------------------------------------------------------#

if [ 0 -ne $UPDATE ] && [[ $(find ${CACHE_DIR} -name delegated-*-extended-latest -mtime -$INTERVAL 2>&1) ]]; then
    RESET=1
else
    RESET=0
fi

$IPTABLES -D DROP_FILTER -g WHITELIST 2>/dev/null
for CHAIN in `$IPTABLES -nL | grep ^Chain | cut -d " " -f 2`; do
    if [ $RESET -ne 0 ]; then
        echo "DELETE:   All Chains"
        $IPTABLES -F
        $IPTABLES -X
        break
    fi

    if [ $CHAIN != COUNTRY_FILTER ] && [ $CHAIN != DROP_FILTER ]; then
        $IPTABLES -F $CHAIN
    fi
done
for CHAIN in `$IPTABLES -nL | grep ^Chain | cut -d " " -f 2`; do
    if [ $RESET -ne 0 ]; then
        break
    fi

    if [ $CHAIN != COUNTRY_FILTER ] && [ $CHAIN != DROP_FILTER ] && [ $CHAIN != ACCEPT_FILTER ]; then
        if [ $CHAIN != INPUT ] && [ $CHAIN != FORWARD ] && [ $CHAIN != OUTPUT ]; then
            $IPTABLES -X $CHAIN
        fi
    fi
done

$IPTABLES -Z
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD DROP

$IPTABLES -N ACCEPT_FILTER 2>/dev/null
$IPTABLES -A ACCEPT_FILTER -j ACCEPT


#----------------------------------------------------------#
# Preprocess                                               #
#----------------------------------------------------------#

# ループバック(自身)のアクセスをすべて許可
$IPTABLES -A INPUT -i lo -j ACCEPT_FILTER
$IPTABLES -A OUTPUT -o lo -j ACCEPT_FILTER
$IPTABLES -A FORWARD -i lo -j ACCEPT_FILTER
$IPTABLES -A FORWARD -o lo -j ACCEPT_FILTER

# 確立した接続を切断しない
# 設定完了まで切断されてもよいなら除外
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT_FILTER
$IPTABLES -A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT_FILTER
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT_FILTER

# 名前解決できるようにする
for nameserver in ${NAMESERVERS[@]}; do
    $IPTABLES -A INPUT -s $nameserver -p udp --dport 53 -j ACCEPT_FILTER
    $IPTABLES -A OUTPUT -d $nameserver -p udp --sport 53 -j ACCEPT_FILTER
    $IPTABLES -A FORWARD -s $nameserver -p udp --dport 53 -j ACCEPT_FILTER
    $IPTABLES -A FORWARD -d $nameserver -p udp --sport 53 -j ACCEPT_FILTER
    echo "NAMESERVER:   $nameserver"
done

# NTPサーバと同期できるようにする
for ntpserver in ${NTPSERVERS[@]}; do
    $IPTABLES -A INPUT -s $ntpserver -p udp --dport 123 -j ACCEPT_FILTER
    $IPTABLES -A OUTPUT -d $ntpserver -p udp --sport 123 -j ACCEPT_FILTER
    $IPTABLES -A FORWARD -s $ntpserver -p udp --dport 123 -j ACCEPT_FILTER
    $IPTABLES -A FORWARD -d $ntpserver -p udp --sport 123 -j ACCEPT_FILTER
    echo "NTPSERVER:    $ntpserver"
done


#----------------------------------------------------------#
# CountryFilter                                            #
#----------------------------------------------------------#

BUILD_COUNTRY(){
  if [ ! -s $CACHE_DIR$1 ] || [ ! $2 ] || [ ! $3 ];then return;fi
  echo "LOAD:   $1"
  for line in `cat $CACHE_DIR$1 | grep -E "\|($2|$3)\|ipv4\|"`
  do
    CODE=`echo $line | cut -d "|" -f 2`
    ADDR=`echo $line | cut -d "|" -f 4`
    TEMP=`echo $line | cut -d "|" -f 5`
    CIDR=32
    while [ $TEMP -ne 1 ]; do
      TEMP=`expr "$TEMP" / 2`
      CIDR=`expr "$CIDR" - 1`
    done
    if [ `echo $line | grep -E "\|($3)\|ipv4\|"` ]; then
      $IPTABLES -A COUNTRY_FILTER -s $ADDR/$CIDR -j ACCEPT_FILTER
      printf "%-10s%-4s%-20s%s\n" ACCEPT $CODE $ADDR/$CIDR $line
    else
      $IPTABLES -A DROP_FILTER -s $ADDR/$CIDR -j DROP
      printf "%-10s%-4s%-20s%s\n" DROP   $CODE $ADDR/$CIDR $line
    fi
  done
}

if [ $STRICT != true ]; then
  if [ $RESET -ne 0 ] || [[ 3 > $($IPTABLES -nL COUNTRY_FILTER 2>/dev/null | awk 'END{print NR}') ]] || [[ 3 > $($IPTABLES -nL DROP_FILTER 2>/dev/null | awk 'END{print NR}') ]]; then
    echo "BUILD:        Chain COUNTRY_FILTER"
    echo "BUILD:        Chain DROP_FILTER"

    $IPTABLES -F COUNTRY_FILTER 2>/dev/null
    $IPTABLES -X COUNTRY_FILTER 2>/dev/null
    $IPTABLES -N COUNTRY_FILTER 2>/dev/null

    $IPTABLES -F DROP_FILTER 2>/dev/null
    $IPTABLES -X DROP_FILTER 2>/dev/null
    $IPTABLES -N DROP_FILTER 2>/dev/null

    BUILD_COUNTRY "delegated-apnic-extended-latest"   $DROP_COUNTRY_CODE $ACCEPT_COUNTRY_CODE
    BUILD_COUNTRY "delegated-arin-extended-latest"    $DROP_COUNTRY_CODE $ACCEPT_COUNTRY_CODE
    BUILD_COUNTRY "delegated-ripencc-extended-latest" $DROP_COUNTRY_CODE $ACCEPT_COUNTRY_CODE
    BUILD_COUNTRY "delegated-lacnic-extended-latest"  $DROP_COUNTRY_CODE $ACCEPT_COUNTRY_CODE
    BUILD_COUNTRY "delegated-afrinic-extended-latest" $DROP_COUNTRY_CODE $ACCEPT_COUNTRY_CODE

    $IPTABLES -A COUNTRY_FILTER -j DROP
  else
    echo "REUSE:        Chain COUNTRY_FILTER"
    echo "REUSE:        Chain DROP_FILTER"
  fi

  $IPTABLES -A INPUT -j DROP_FILTER
  $IPTABLES -A OUTPUT -j DROP_FILTER
  $IPTABLES -A FORWARD -j DROP_FILTER
else
  $IPTABLES -N COUNTRY_FILTER 2>/dev/null
  $IPTABLES -N DROP_FILTER 2>/dev/null
  $IPTABLES -A COUNTRY_FILTER -j ACCEPT_FILTER
fi


#----------------------------------------------------------#
# Firewall                                                 #
#----------------------------------------------------------#

# 送信元IPの偽装防止
sed -i '/net.ipv4.conf.*.rp_filter/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
    sysctl -w net.ipv4.conf.$dev.rp_filter=1 > /dev/null
    echo "net.ipv4.conf.$dev.rp_filter=1" >> /etc/sysctl.conf
done

# ICMP Redirectパケットを拒否
sed -i '/net.ipv4.conf.*.accept_redirects/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
    sysctl -w net.ipv4.conf.$dev.accept_redirects=0 > /dev/null
    echo "net.ipv4.conf.$dev.accept_redirects=0" >> /etc/sysctl.conf
done

# Source Routedパケットを拒否
sed -i '/net.ipv4.conf.*.accept_source_route/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
    sysctl -w net.ipv4.conf.$dev.accept_source_route=0 > /dev/null
    echo "net.ipv4.conf.$dev.accept_source_route=0" >> /etc/sysctl.conf
done

# ブロードキャストアドレス宛pingには応答しない
# ※Smurf攻撃対策
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null
sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.conf
echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.conf

# SYN Cookiesを有効にする
# ※TCP SYN Flood攻撃対策
sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null
sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.conf

# システムの連続稼働時間を通知しない
# ※カーネルバージョン特定対策
sysctl -w net.ipv4.tcp_timestamps=1 > /dev/null
sed -i '/net.ipv4.tcp_timestamps/d' /etc/sysctl.conf
echo "net.ipv4.tcp_timestamps=1" >> /etc/sysctl.conf

# 不正なアクセスを行ったIPからのすべてのアクセスをログを記録して破棄
# ※調査的アクセスから公開ポートを隠蔽する
# ※公開サーバーでは無効にしてよい
$IPTABLES -N ANTI_SPY
$IPTABLES -A ANTI_SPY -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES SPY] : '
$IPTABLES -A ANTI_SPY -j DROP
$IPTABLES -N FW_SPY
# 公開サーバーでは既知のポートはフィルタしない
$IPTABLES -A FW_SPY -p tcp --dport 0:1023 -j RETURN
$IPTABLES -A FW_SPY -p tcp -m state --state ESTABLISHED,RELATED -j RETURN
$IPTABLES -A FW_SPY -m limit --limit 1000/s --limit-burst 10000 -m recent --name spy-rapid --update --rttl -j ANTI_SPY
$IPTABLES -A FW_SPY -m limit --limit 1000/s --limit-burst 10000 -m recent --name spy-fast --update --rttl -j ANTI_SPY
$IPTABLES -A FW_SPY -m limit --limit 1000/s --limit-burst 10000 -m recent --name spy-medium --update --rttl -j ANTI_SPY
$IPTABLES -A FW_SPY -m limit --limit 1000/s --limit-burst 10000 -m recent --name spy-slow --update --rttl -j ANTI_SPY
$IPTABLES -A ACCEPT_FILTER -j FW_SPY && echo "FIREWALL: ANTI_SPY        ACCEPT_FILTER"
# recentモジュールは初期値で100IPしか記憶できない
# 送信元を偽装したパケットを大量に送りつけるか調査元の絶対数が増えると容易に無効化されるため対処されれば効果はない
# 攻撃価値の不明なIPの存在確認とポートスキャンに必要となる最小コストを上げる防御としては有効
# 管理機能を持つサーバーは攻撃価値を特定され本格的な攻撃を受けないよう非公開サーバーに分離隠蔽する必要がある
# $ vi /etc/modprobe.d/iptables-recent.conf
# options ip_list_hash_size=0 xt_recent ip_list_tot=1000
# $ reboot
# $ cat /sys/module/xt_recent/parameters/ip_list_tot
# $ ls /proc/net/xt_recent/

# 不審なアクセスを行っているIPをスパイとして記録
# ※不審なアクセスを長時間追跡する
# ※正規の通信のフィルタとして使用不可
# ※公開サーバーでは無効にしてよい
$IPTABLES -N ANTI_PROWLER_RAPID
$IPTABLES -A ANTI_PROWLER_RAPID -m recent --name spy-rapid --update --rttl -j DROP
$IPTABLES -A ANTI_PROWLER_RAPID -m recent --name spy-rapid --set -j DROP
$IPTABLES -N ANTI_PROWLER_FAST
$IPTABLES -A ANTI_PROWLER_FAST -m recent --name spy-fast --update --rttl -j DROP
$IPTABLES -A ANTI_PROWLER_FAST -m recent --name spy-fast --set -j DROP
$IPTABLES -N ANTI_PROWLER_MEDIUM
$IPTABLES -A ANTI_PROWLER_MEDIUM -m recent --name spy-medium --update --rttl -j DROP
$IPTABLES -A ANTI_PROWLER_MEDIUM -m recent --name spy-medium --set -j DROP
$IPTABLES -N ANTI_PROWLER_SLOW
$IPTABLES -A ANTI_PROWLER_SLOW -m recent --name spy-slow --update --rttl -j DROP
$IPTABLES -A ANTI_PROWLER_SLOW -m recent --name spy-slow --set -j DROP
$IPTABLES -N FW_PROWLER
$IPTABLES -A FW_PROWLER \
          -m hashlimit \
          --hashlimit-name prowler-limit \
          --hashlimit-above 1/s \
          --hashlimit-burst 1 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 800 \
          -j DROP
$IPTABLES -N FW_PROWLER_LIMIT
$IPTABLES -A FW_PROWLER_LIMIT -m limit --limit 1000/s --limit-burst 10000 -j RETURN
$IPTABLES -A FW_PROWLER_LIMIT -j DROP
$IPTABLES -A FW_PROWLER -j FW_PROWLER_LIMIT
$IPTABLES -A FW_PROWLER \
          -m hashlimit \
          --hashlimit-name prowler-rapid \
          --hashlimit-above 1/s \
          --hashlimit-burst 1 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 1000 \
          -j ANTI_PROWLER_RAPID
$IPTABLES -A FW_PROWLER -m recent --name spy-rapid --set
$IPTABLES -A FW_PROWLER \
          -m hashlimit \
          --hashlimit-name prowler-fast \
          --hashlimit-above 1/h \
          --hashlimit-burst 1 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 100000 \
          -j ANTI_PROWLER_FAST
$IPTABLES -A FW_PROWLER -m recent --name spy-fast --set
$IPTABLES -A FW_PROWLER \
          -m hashlimit \
          --hashlimit-name prowler-medium \
          --hashlimit-above 1/h \
          --hashlimit-burst 1 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 1000000 \
          -j ANTI_PROWLER_MEDIUM
$IPTABLES -A FW_PROWLER -m recent --name spy-medium --set
$IPTABLES -A FW_PROWLER \
          -m hashlimit \
          --hashlimit-name prowler-slow \
          --hashlimit-above 1/d \
          --hashlimit-burst 1 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 10000000 \
          -j ANTI_PROWLER_SLOW
$IPTABLES -A FW_PROWLER -m recent --name spy-slow --set
$IPTABLES -A FW_PROWLER -j DROP

# 全ホスト(ブロードキャストアドレス、マルチキャストアドレス)宛パケットをログを記録せずに破棄
$IPTABLES -N DENY_BROADCAST
$IPTABLES -A DENY_BROADCAST -j DROP
$IPTABLES -N FW_BROADCAST
$IPTABLES -A FW_BROADCAST -m pkttype --pkt-type broadcast -j DENY_BROADCAST
$IPTABLES -A FW_BROADCAST -m pkttype --pkt-type multicast -j DENY_BROADCAST
$IPTABLES -A INPUT -j FW_BROADCAST && echo "FIREWALL:   DENY_BROADCAST      INPUT"
$IPTABLES -A FORWARD -j FW_BROADCAST && echo "FIREWALL: DENY_BROADCAST      FORWARD"

# 送信元IPアドレスがLANネットワーク範囲外のパケットをログを記録して破棄してNG
# ※Ingress攻撃対策
$IPTABLES -N ANTI_INGRESS
$IPTABLES -A ANTI_INGRESS -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES INGRESS] : '
$IPTABLES -A ANTI_INGRESS -j FW_PROWLER
$IPTABLES -A ANTI_INGRESS -j DROP
$IPTABLES -N FW_INGRESS
$IPTABLES -A FW_INGRESS -i $LAN ! -s $LOCALNET -j ANTI_INGRESS
$IPTABLES -A FORWARD -j FW_INGRESS && echo "FIREWALL:   ANTI_INGRESS        FORWARD"

# WANからの送信元がプライベートIPアドレスのパケットをログを記録して破棄してNG
# ※IP spoofing攻撃対策
$IPTABLES -N ANTI_SPOOFING
$IPTABLES -A ANTI_SPOOFING -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES SPOOFING] : '
$IPTABLES -A ANTI_SPOOFING -j FW_PROWLER
$IPTABLES -A ANTI_SPOOFING -j DROP
$IPTABLES -N FW_SPOOFING
$IPTABLES -A FW_SPOOFING -i eth+ -s 127.0.0.0/8    -j ANTI_SPOOFING
$IPTABLES -A FW_SPOOFING -i eth+ -s 10.0.0.0/8     -j ANTI_SPOOFING
$IPTABLES -A FW_SPOOFING -i eth+ -s 172.16.0.0/12  -j ANTI_SPOOFING
$IPTABLES -A FW_SPOOFING -i eth+ -s 192.168.0.0/16 -j ANTI_SPOOFING
$IPTABLES -A FW_SPOOFING -i ppp+ -s 127.0.0.0/8    -j ANTI_SPOOFING
$IPTABLES -A FW_SPOOFING -i ppp+ -s 10.0.0.0/8     -j ANTI_SPOOFING
$IPTABLES -A FW_SPOOFING -i ppp+ -s 172.16.0.0/12  -j ANTI_SPOOFING
$IPTABLES -A FW_SPOOFING -i ppp+ -s 192.168.0.0/16 -j ANTI_SPOOFING
$IPTABLES -A ACCEPT_FILTER -j FW_SPOOFING && echo "FIREWALL:    ANTI_SPOOFING       ACCEPT_FILTER"

# 外部とのNetBIOS関連のアクセスはログを記録せずに破棄してNG
$IPTABLES -N DENY_NETBIOS
$IPTABLES -A DENY_NETBIOS -j FW_PROWLER
$IPTABLES -A DENY_NETBIOS -j DROP
$IPTABLES -N FW_NETBIOS
$IPTABLES -A FW_NETBIOS -i eth+ -p tcp -m multiport --dports 135,137,138,139,445 -j DENY_NETBIOS
$IPTABLES -A FW_NETBIOS -i eth+ -p udp -m multiport --dports 135,137,138,139,445 -j DENY_NETBIOS
$IPTABLES -A FW_NETBIOS -o eth+ -p tcp -m multiport --sports 135,137,138,139,445 -j DENY_NETBIOS
$IPTABLES -A FW_NETBIOS -o eth+ -p udp -m multiport --sports 135,137,138,139,445 -j DENY_NETBIOS
$IPTABLES -A FW_NETBIOS -i ppp+ -p tcp -m multiport --dports 135,137,138,139,445 -j DENY_NETBIOS
$IPTABLES -A FW_NETBIOS -i ppp+ -p udp -m multiport --dports 135,137,138,139,445 -j DENY_NETBIOS
$IPTABLES -A FW_NETBIOS -o ppp+ -p tcp -m multiport --sports 135,137,138,139,445 -j DENY_NETBIOS
$IPTABLES -A FW_NETBIOS -o ppp+ -p udp -m multiport --sports 135,137,138,139,445 -j DENY_NETBIOS
$IPTABLES -A ACCEPT_FILTER -j FW_NETBIOS && echo "FIREWALL: DENY_NETBIOS        ACCEPT_FILTER"

# フラグメント化されたパケットをログを記録して破棄してNG
$IPTABLES -N DENY_FRAGMENT
$IPTABLES -A DENY_FRAGMENT -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES FRAGMENT] : '
$IPTABLES -A DENY_FRAGMENT -j FW_PROWLER
$IPTABLES -A DENY_FRAGMENT -j DROP
$IPTABLES -N FW_FRAGMENT
$IPTABLES -A FW_FRAGMENT -f -j DENY_FRAGMENT
$IPTABLES -A ACCEPT_FILTER -j FW_FRAGMENT && echo "FIREWALL:    DENY_FRAGMENT       ACCEPT_FILTER"

# 不正なパケットをログを記録して破棄してNG
$IPTABLES -N DENY_INVALID
$IPTABLES -A DENY_INVALID -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES INVALID] : '
$IPTABLES -A DENY_INVALID -j DROP
$IPTABLES -N FW_INVALID
$IPTABLES -A FW_INVALID -m state --state INVALID -j DENY_INVALID
$IPTABLES -A ACCEPT_FILTER -j FW_INVALID && echo "FIREWALL: DENY_INVALID        ACCEPT_FILTER"

# フラグの不正なパケットを破棄、16分間に3回を超えたらログを記録してNG
# ※ステルススキャン対策
# ※既知のポートはもともと隠密性がないため保護せず誤作動の回避を優先
# ※SSHの終了処理をしないで切断されると簡単に自爆するので注意
# ※FW_PORTSCANとFW_SPYが機能しているうちは有効にする必要性は低い
# ※フラグパターンの妥当性未検証
# ※公開サーバーでは無効にしてよい
$IPTABLES -N ANTI_STEALTHSCAN
$IPTABLES -A ANTI_STEALTHSCAN \
          -m hashlimit \
          --hashlimit-name scan \
          --hashlimit 1/h \
          --hashlimit-burst 3 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 960000 \
          -j DROP
$IPTABLES -A ANTI_STEALTHSCAN -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES STEALTHSCAN] : '
$IPTABLES -A ANTI_STEALTHSCAN -j FW_PROWLER
$IPTABLES -A ANTI_STEALTHSCAN -j DROP
$IPTABLES -N FW_STEALTHSCAN
$IPTABLES -A FW_STEALTHSCAN -o lo -j RETURN
$IPTABLES -A FW_STEALTHSCAN -o eth+ -j RETURN
$IPTABLES -A FW_STEALTHSCAN -o ppp+ -j RETURN
$IPTABLES -A FW_STEALTHSCAN ! -p tcp -j RETURN
$IPTABLES -A FW_STEALTHSCAN -p tcp --dport 0:1023 -j RETURN
$IPTABLES -A FW_STEALTHSCAN -p tcp -m state ! --state NEW -j RETURN
# SYN + ACK when NEW
$IPTABLES -A FW_STEALTHSCAN -p tcp -m state --state NEW --tcp-flags SYN,ACK SYN,ACK -j ANTI_STEALTHSCAN
# FIN/PSH/URG without ACK
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ACK,FIN FIN -j ANTI_STEALTHSCAN
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ACK,PSH PSH -j ANTI_STEALTHSCAN
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ACK,URG URG -j ANTI_STEALTHSCAN
# SYN + FIN
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags SYN,FIN SYN,FIN -j ANTI_STEALTHSCAN
# SYN + RST
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags SYN,RST SYN,RST -j ANTI_STEALTHSCAN
# FIN + RST
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags FIN,RST FIN,RST -j ANTI_STEALTHSCAN
# ALL
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ALL ALL -j ANTI_STEALTHSCAN
# nmap Null scans / no flags
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ALL NONE -j ANTI_STEALTHSCAN
# nmap FIN stealth scan
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ALL FIN -j ANTI_STEALTHSCAN
# FIN + URG + PSH
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ALL FIN,PSH,URG -j ANTI_STEALTHSCAN
# XMAS
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j ANTI_STEALTHSCAN
$IPTABLES -A FW_STEALTHSCAN -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG,PSH -j ANTI_STEALTHSCAN
$IPTABLES -A ACCEPT_FILTER -j FW_STEALTHSCAN && echo "FIREWALL: ANTI_STEALTHSCAN    ACCEPT_FILTER"

# pingは1秒間に4回を超えたらログを記録して破棄してNG
# ※Ping of Death攻撃対策
$IPTABLES -N ANTI_PINGDEATH
$IPTABLES -A ANTI_PINGDEATH \
          -m hashlimit \
          --hashlimit-name scan \
          --hashlimit 1/s \
          --hashlimit-burst 4 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 1000 \
          -j RETURN
$IPTABLES -A ANTI_PINGDEATH -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES PINGDEATH] : '
$IPTABLES -A ANTI_PINGDEATH -j FW_PROWLER
$IPTABLES -A ANTI_PINGDEATH -j DROP
$IPTABLES -N FW_PINGDEATH
$IPTABLES -A FW_PINGDEATH -i eth+ -p icmp --icmp-type echo-request -j ANTI_PINGDEATH
$IPTABLES -A FW_PINGDEATH -i ppp+ -p icmp --icmp-type echo-request -j ANTI_PINGDEATH
$IPTABLES -A ACCEPT_FILTER -j FW_PINGDEATH && echo "FIREWALL:   ANTI_PINGDEATH      ACCEPT_FILTER"

# 過大なアクセスをIP単位で制限
# ※SYN Flood攻撃対策(数値は適宜調整)
#
# -m hashlimit                 :hashlimitモジュールを利用
# --hashlimit-name name        :ハッシュテーブル名
# --hashlimit n                :パケット回復量
# --hashlimit-burst n          :パケット容量
# --hashlimit-mode hash        :同一アクセスとしてカウントする識別基準
# --hashlimit-htable-expire ms :ハッシュテーブル内のレコードの有効期間(単位:ミリ秒)
#
# HTTPポートへの過大なアクセスを拒否
$IPTABLES -N ANTI_SYNFLOOD
$IPTABLES -A ANTI_SYNFLOOD \
          -m hashlimit \
          --hashlimit-name http \
          --hashlimit 10/m \
          --hashlimit-burst 60 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 60000 \
          -j RETURN
$IPTABLES -A ANTI_SYNFLOOD -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES SYNFLOOD] : '
$IPTABLES -A ANTI_SYNFLOOD -j DROP
$IPTABLES -N FW_SYNFLOOD
$IPTABLES -A FW_SYNFLOOD -i eth+ -p tcp --dport 80 -m state --state NEW -j ANTI_SYNFLOOD
$IPTABLES -A FW_SYNFLOOD -i ppp+ -p tcp --dport 80 -m state --state NEW -j ANTI_SYNFLOOD
$IPTABLES -A ACCEPT_FILTER -j FW_SYNFLOOD && echo "FIREWALL:    ANTI_SYNFLOOD       ACCEPT_FILTER[TCP:80]"
#
# HTTPSポートへの過大なアクセスを拒否
$IPTABLES -N ANTI_SYNFLOOD_SSL
$IPTABLES -A ANTI_SYNFLOOD_SSL \
          -m hashlimit \
          --hashlimit-name https \
          --hashlimit 30/m \
          --hashlimit-burst 60 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 60000 \
          -j RETURN
$IPTABLES -A ANTI_SYNFLOOD_SSL -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES SYNFLOOD(SSL)] : '
$IPTABLES -A ANTI_SYNFLOOD_SSL -j DROP
$IPTABLES -N FW_SYNFLOOD_SSL
$IPTABLES -A FW_SYNFLOOD_SSL -i eth+ -p tcp --dport 443 -m state --state NEW -j ANTI_SYNFLOOD_SSL
$IPTABLES -A FW_SYNFLOOD_SSL -i ppp+ -p tcp --dport 443 -m state --state NEW -j ANTI_SYNFLOOD_SSL
$IPTABLES -A ACCEPT_FILTER -j FW_SYNFLOOD_SSL && echo "FIREWALL:    ANTI_SYNFLOOD_SSL   ACCEPT_FILTER[TCP:443]"
#
# UDPによる過大なアクセスを拒否
$IPTABLES -N ANTI_UDPFLOOD
$IPTABLES -A ANTI_UDPFLOOD \
          -m hashlimit \
          --hashlimit-name udp \
          --hashlimit 30/m \
          --hashlimit-burst 60 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 60000 \
          -j RETURN
$IPTABLES -A ANTI_UDPFLOOD -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES UDPFLOOD] : '
$IPTABLES -A ANTI_UDPFLOOD -j DROP
$IPTABLES -N FW_UDPFLOOD
$IPTABLES -A FW_UDPFLOOD -i eth+ -p udp -m state --state NEW -j ANTI_UDPFLOOD
$IPTABLES -A FW_UDPFLOOD -i ppp+ -p udp -m state --state NEW -j ANTI_UDPFLOOD
$IPTABLES -A ACCEPT_FILTER -j FW_UDPFLOOD && echo "FIREWALL:    ANTI_UDPFLOOD       ACCEPT_FILTER[UDP]"
#
# ICMPによる過大なアクセスを拒否
$IPTABLES -N ANTI_ICMPFLOOD
$IPTABLES -A ANTI_ICMPFLOOD \
          -m hashlimit \
          --hashlimit-name icmp \
          --hashlimit 30/m \
          --hashlimit-burst 60 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 60000 \
          -j RETURN
$IPTABLES -A ANTI_ICMPFLOOD -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES ICMPFLOOD] : '
$IPTABLES -A ANTI_ICMPFLOOD -j DROP
$IPTABLES -N FW_ICMPFLOOD
$IPTABLES -A FW_ICMPFLOOD -i eth+ -p icmp --icmp-type echo-request -j ANTI_ICMPFLOOD
$IPTABLES -A FW_ICMPFLOOD -i ppp+ -p icmp --icmp-type echo-request -j ANTI_ICMPFLOOD
$IPTABLES -A ACCEPT_FILTER -j FW_ICMPFLOOD && echo "FIREWALL:   ANTI_ICMPFLOOD      ACCEPT_FILTER[ICMP]"

# 管理用ポートへ3分間に10回を超えて接続試行しているIPを拒否してNG
# ※Brute Force攻撃対策
$IPTABLES -N ANTI_BRUTEFORCE
$IPTABLES -A ANTI_BRUTEFORCE \
          -m hashlimit \
          --hashlimit-name bruteforce \
          --hashlimit 1/m \
          --hashlimit-burst 7 \
          --hashlimit-mode srcip \
          --hashlimit-htable-expire 180000 \
          -j RETURN
$IPTABLES -A ANTI_BRUTEFORCE -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES BRUTEFORCE] : '
$IPTABLES -A ANTI_BRUTEFORCE -j DROP
$IPTABLES -N FW_BRUTEFORCE
$IPTABLES -A FW_BRUTEFORCE -i eth+ -p tcp -m multiport --dports $LOGIN -m state --syn --state NEW -j ANTI_BRUTEFORCE
$IPTABLES -A FW_BRUTEFORCE -i ppp+ -p tcp -m multiport --dports $LOGIN -m state --syn --state NEW -j ANTI_BRUTEFORCE
$IPTABLES -A ACCEPT_FILTER -j FW_BRUTEFORCE && echo "FIREWALL:  ANTI_BRUTEFORCE     ACCEPT_FILTER[TCP]"


#----------------------------------------------------------#
# BLACKLIST/WHITELIST                                      #
#----------------------------------------------------------#

# ブラックリストに一致するIPをDROPする
if [ $BLACKLIST ] && [ -s $BLACKLIST ]; then
  $IPTABLES -N BLACKLIST 2>/dev/null
  for line in `cat $BLACKLIST | grep ^[0-9]`
  do
    $IPTABLES -A BLACKLIST -s $line -j DROP
  done
  
  $IPTABLES -A INPUT -j BLACKLIST
  $IPTABLES -A FORWARD -j BLACKLIST
  $IPTABLES -A OUTPUT -j BLACKLIST
fi

# ホワイトリストに一致しないIPをDROPする
if [ $WHITELIST ] && [ -s $WHITELIST ]; then
  $IPTABLES -N WHITELIST 2>/dev/null
  for line in `cat $WHITELIST | grep ^[0-9]`
  do
    $IPTABLES -A WHITELIST -s $line -j RETURN
  done
  
  $IPTABLES -I BLACKLIST -g WHITELIST 2>/dev/null
  $IPTABLES -I DROP_FILTER -g WHITELIST
  if [ $STRICT = true ]; then
    $IPTABLES -A WHITELIST -j DROP
    $IPTABLES -A INPUT -j WHITELIST
    $IPTABLES -A FORWARD -j WHITELIST
    $IPTABLES -A OUTPUT -j WHITELIST
  fi
fi


#----------------------------------------------------------#
# IDS/IPS                                                  #
#----------------------------------------------------------#

$IPTABLES -D ACCEPT_FILTER 1

if [ $IPS = Snort ]; then

    # ICMPパケットをすべて解析
    $IPTABLES -A ACCEPT_FILTER -p icmp -j NFQUEUE --queue-num 2

    # UDPパケットをすべて解析
    $IPTABLES -A ACCEPT_FILTER -p udp -j NFQUEUE --queue-num 2

    # TCPパケットを外部通信分のみ解析
    $IPTABLES -A ACCEPT_FILTER -i eth+ -p tcp -j NFQUEUE --queue-num 2
    $IPTABLES -A ACCEPT_FILTER -i ppp+ -p tcp -j NFQUEUE --queue-num 2
    $IPTABLES -A ACCEPT_FILTER -o eth+ -p tcp -j NFQUEUE --queue-num 2
    $IPTABLES -A ACCEPT_FILTER -o ppp+ -p tcp -j NFQUEUE --queue-num 2

    # バックエンドサーバーとの内部通信パケットを解析
    $IPTABLES -A ACCEPT_FILTER -i lo -p tcp --dport 9000 -j NFQUEUE --queue-num 2
    $IPTABLES -A ACCEPT_FILTER -o lo -p tcp --dport 9000 -j NFQUEUE --queue-num 2

    # 解析しないパケットはすべて許可
    $IPTABLES -A ACCEPT_FILTER -j ACCEPT

    echo "IDS/IPS:  Snort"

else
    $IPTABLES -A ACCEPT_FILTER -j ACCEPT
    echo "IDS/IPS:  DISABLE"
fi


#----------------------------------------------------------#
# Port                                                     #
#----------------------------------------------------------#

# 最小限のICMPのみ許可
$IPTABLES -A INPUT -p icmp --icmp-type destination-unreachable -j COUNTRY_FILTER
$IPTABLES -A INPUT -p icmp --icmp-type source-quench -j COUNTRY_FILTER
$IPTABLES -A INPUT -p icmp --icmp-type redirect -j COUNTRY_FILTER
$IPTABLES -A INPUT -p icmp --icmp-type time-exceeded -j COUNTRY_FILTER
$IPTABLES -A INPUT -p icmp --icmp-type parameter-problem -j COUNTRY_FILTER

# 管理用ポート(SSH等)を開放
$IPTABLES -A INPUT -p tcp -m multiport --dports $LOGIN -j COUNTRY_FILTER

# SNMP[UDP:160,161]ポートを開放
#$IPTABLES -A INPUT -p udp --dport 160 -j COUNTRY_FILTER && echo "OPEN:       SNMP[UDP:160]"
#$IPTABLES -A INPUT -p udp --dport 161 -j COUNTRY_FILTER && echo "OPEN:       SNMP[UDP:161]"

# DNS[TCP/UDP:53]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 53 -j COUNTRY_FILTER && echo "OPEN:        DNS[TCP:53]"
#$IPTABLES -A INPUT -p udp --dport 53 -j COUNTRY_FILTER && echo "OPEN:        DNS[UDP:53]"

# HTTP[TCP:80]ポートを開放
$IPTABLES -A INPUT -p tcp --dport 80 -j ACCEPT_FILTER && echo "OPEN:       HTTP[TCP:80]"

# HTTPS[TCP:443]ポートを開放
$IPTABLES -A INPUT -p tcp --dport 443 -j COUNTRY_FILTER && echo "OPEN:     HTTPS[TCP:443]"

# FTP[TCP:21]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 21 -j COUNTRY_FILTER

# PASV(FTP-DATA)ポートを開放 ※PASV用ポート60000:60030は設定例
#$IPTABLES -A INPUT -p tcp --dport 60000:60030 -j COUNTRY_FILTER && echo "OPEN:       PASV[TCP:60000-60030]"

# IDENT[TCP:113]ポートを開放
# ※IDENTを使用せずメールサーバーを公開する場合はメールサーバ等のレスポンス低下防止のため拒否応答
#$IPTABLES -A INPUT -p tcp --dport 113 -j COUNTRY_FILTER && echo "OPEN:       IDENT[TCP:113]"
#$IPTABLES -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset && echo "REJECT: IDENT[TCP:113]"

# SMTP[TCP:25]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 25 -j COUNTRY_FILTER && echo "OPEN:        SMTP[TCP:25]"

# SMTPS[TCP:465]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 465 -j COUNTRY_FILTER && echo "OPEN:       SMTPS[TCP:465]"

# POP3[TCP:110]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 110 -j COUNTRY_FILTER && echo "OPEN:       POP3[TCP:110]"

# POP3S[TCP:995]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 995 -j COUNTRY_FILTER && echo "OPEN:       POP3S[TCP:995]"

# IMAP[TCP:143]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 143 -j COUNTRY_FILTER && echo "OPEN:       IMAP[TCP:143]"

# IMAPS[TCP:993]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 993 -j COUNTRY_FILTER && echo "OPEN:       IMAPS[TCP:993]"

# OpenVPN[UDP:1194]ポートを開放
#$IPTABLES -A INPUT -p udp --dport 1194 -j COUNTRY_FILTER && echo "OPEN:      OpenVPN[UDP:1194]"

# IPsec[TCP/UDP:50,51]ポートを開放
#$IPTABLES -A INPUT -p 50 -j COUNTRY_FILTER && echo "OPEN:        IPsec[TCP/UDP:50]"
#$IPTABLES -A INPUT -p 51 -j COUNTRY_FILTER && echo "OPEN:        IPsec[TCP/UDP:51]"

# Submission[TCP:587]ポートを開放
#$IPTABLES -A INPUT -p tcp --dport 587 -j COUNTRY_FILTER && echo "OPEN:       Submission[TCP:587]"

# VPNインタフェース用ファイアウォール設定
#[ -f /etc/openvpn/openvpn-startup ] && /etc/openvpn/openvpn-startup

# 公開していないポートへのパケットをログを記録して破棄してNG
# ※ポートスキャン対策
# ※開けていないポートに1度でも触ったらアウト
# ※公開サーバーでは無効にしてよい
$IPTABLES -N TRAP_PORTSCAN
$IPTABLES -A TRAP_PORTSCAN -m limit --limit $LOG_LIMIT --limit-burst $LOG_LIMIT_BURST -j LOG --log-level debug --log-prefix '[IPTABLES PORTSCAN] : '
$IPTABLES -A TRAP_PORTSCAN -j FW_PROWLER
$IPTABLES -A TRAP_PORTSCAN -j DROP
$IPTABLES -N FW_PORTSCAN
$IPTABLES -A FW_PORTSCAN -j TRAP_PORTSCAN
$IPTABLES -A INPUT -j FW_PORTSCAN && echo "FIREWALL:    TRAP_PORTSCAN       INPUT[TCP/UDP/ICMP]"
$IPTABLES -A FORWARD -j FW_PORTSCAN && echo "FIREWALL:  TRAP_PORTSCAN       FORWARD[TCP/UDP/ICMP]"


#----------------------------------------------------------#
# Finalize                                                 #
#----------------------------------------------------------#

# 設定保存(/etc/sysconfig/iptablesの既存の設定は削除)
service iptables save
sysctl -p 2>&1 | grep -v -E "^error:.*(ipv6|bridge-nf-call)"
service rsyslog restart

echo complete

BLACKLIST/WHITELIST

BLACKLIST=/etc/iptables/blacklist
WHITELIST=/etc/iptables/whitelist
STRICT=false
# BLACKLIST
1.2.3.0/24
# WHITELIST
1.2.3.4

STRICT

BLACKLIST=
WHITELIST=/etc/iptables/whitelist
STRICT=true

ログローテート

$ sudo vi /etc/rsyslog.conf
kern.=debug /var/log/iptables.log
$ sudo service rsyslog restart
$ sudo vi /etc/logrotate.d/iptables
/var/log/iptables.log {
  rotate 14
  daily
  compress
  missing ok
  notifempty

  postrotate
    service rsyslog restart
  endscript
}

ipv6無効化

$ sudo vi /etc/sysctl.conf
# ipv6 disable
net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
$ sudo vi /etc/modprobe.d/disable-ipv6.conf
options ipv6 disable=1
$ sudo vi /etc/hosts
#::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
$ sudo chkconfig ip6tables off

$ sudo /sbin/sysctl -p
$ sudo service network restart
$ sudo reboot

$ ifconfig
$ netstat -an -A inet6
$ lsmod | grep ipv6 # モジュール自体はロードさせる

参考・引用