#!/bin/sh

# iptablesコマンドのパス
IPTABLES="/sbin/iptables"

# デフォルト外部(WAN側)インターフェース
DEFAULT_EXTIF="eth0"

# デフォルト内部(LAN側)インターフェース
DEFAULT_INTIF="eth1"

# 参照するNTPサーバ
NTP1="yyy.yyy.yyy.yyy"
NTP2="zzz.zzz.zzz.zzz"

# 非特権ポート
UNPRIVPORTS="1024:65535"

# TCP-SYN-Flood検出で一秒あたりに許される平均マッチ回数の最大値
TCPSYNLIMIT="5/s"
# TCP-SYN-Flood検出の最大バースト値
TCPSYNLIMITBURST="10"

# ログチェインで一秒あたりに許される平均マッチ回数の最大値
LOGLIMIT="2/s"
# ログチェインの最大バースト値
LOGLIMITBURST="10"

# Ping-Flood検出で一秒あたりに許される平均マッチ回数の最大値
PINGLIMIT="5/s"
# Ping-Flood検出の最大バースト値
PINGLIMITBURST="10"


## 外部インターフェース
# 検出
if [ "x$2" != "x" ]; then
  EXTIF=$2
else
  EXTIF=$DEFAULT_EXTIF
fi

# IPアドレスの取得
EXTIP="`/sbin/ifconfig $EXTIF | grep inet | cut -d : -f 2 | cut -d \  -f 1`"
if [ "$EXTIP" = '' ]; then
  echo "Aborting: Unable to determine the IP-address of $EXTIF !"
  exit 1
fi

# ゲートウェイ(ルータ)の検出
EXTGW=`/sbin/route -n | grep -A 4 UG | awk '{ print $2}'`


## 内部インターフェース
# 検出
if [ "x$3" != "x" ]; then
  INTIF=$3
else
  INTIF=$DEFAULT_INTIF
fi

# IPアドレスの取得
INTIP="`/sbin/ifconfig $INTIF | grep inet | cut -d : -f 2 | cut -d \  -f 1`"
if [ "$INTIP" = '' ]; then
  echo "Aborting: Unable to determine the IP-address of $INTIF !"
  exit 1
fi  

# ネットマスクの取得
INTMASK="`/sbin/ifconfig $INTIF | grep Mask | cut -d : -f 4`"

# ネットワークアドレスの取得
INTLAN=$INTIP'/'$INTMASK


# iptablesの初期化
$IPTABLES -F
$IPTABLES -F -t mangle
$IPTABLES -F -t nat
$IPTABLES -X
$IPTABLES -X -t mangle
$IPTABLES -X -t nat

# デフォルトポリシをDROPに設定
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP


# パケットをインターフェース間でフォワード
echo 1 > /proc/sys/net/ipv4/ip_forward

# IP Spoofing attacksの拒否(ソースの妥当性確認)
echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter

# ICMP ECHO requestのブロードキャストとマルチキャストを無視
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

# SRR オプションを持ったパケットを受け取らない
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route

# タイムスタンプを無効
echo 0 > /proc/sys/net/ipv4/tcp_timestamps

# ソケットの syn backlog queue があふれたときにsyncookieを送出
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

# ICMP redirect message を受け取らない
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects

# ブロードキャストフレームに対する偽物の応答の警告を抑止
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

# 有り得ないアドレスを持ったパケットをカーネルのログに記録
echo 1 > /proc/sys/net/ipv4/conf/all/log_martians

# ローカルポートの範囲
echo "32768 61000" > /proc/sys/net/ipv4/ip_local_port_range

## 対DoS
# FIN-WAIT-2 状態を維持する時間
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
# TCP がキープアライブメッセージを送出する間隔
echo 2400 > /proc/sys/net/ipv4/tcp_keepalive_time
# ウィンドウ調整を無効
echo 0 > /proc/sys/net/ipv4/tcp_window_scaling
# SACKを無効
echo 0 > /proc/sys/net/ipv4/tcp_sack


## ログチェイン

# 既知の接続に結び付けられないパケット
$IPTABLES -N LINVALID
$IPTABLES -A LINVALID -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables INVALID DROP "
$IPTABLES -A LINVALID -j DROP

# 不正なtcp-flags
$IPTABLES -N LBADFLAG
$IPTABLES -A LBADFLAG -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables BADFLAG DROP "
$IPTABLES -A LBADFLAG -j DROP

# TCP-SYN-Floods
$IPTABLES -N LSYNFLOOD
$IPTABLES -A LSYNFLOOD -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables SYNFLOOD DROP "
$IPTABLES -A LSYNFLOOD -j DROP

# Ping-Floods
$IPTABLES -N LPINGFLOOD
$IPTABLES -A LPINGFLOOD -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables PINGFLOOD DROP "
$IPTABLES -A LPINGFLOOD -j DROP


# その他のDROPパケット
$IPTABLES -N LDROP
$IPTABLES -A LDROP -p tcp -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables TCP DROP "
$IPTABLES -A LDROP -p udp -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables UDP DROP "
$IPTABLES -A LDROP -p icmp -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables ICMP DROP "
$IPTABLES -A LDROP -f -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables FRAGMENT DROP "
$IPTABLES -A LDROP -j DROP

# その他REJECTパケット
$IPTABLES -N LREJECT
$IPTABLES -A LREJECT -p tcp -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables TCP REJECT "
$IPTABLES -A LREJECT -p udp -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables UDP REJECT "
$IPTABLES -A LREJECT -p icmp -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables ICMP REJECT "
$IPTABLES -A LREJECT -f -m limit --limit $LOGLIMIT --limit-burst $LOGLIMITBURST -j LOG --log-prefix "iptables FRAGMENT REJECT "
$IPTABLES -A LREJECT -p tcp -j REJECT --reject-with tcp-reset
$IPTABLES -A LREJECT -p udp -j REJECT --reject-with icmp-port-unreachable
$IPTABLES -A LREJECT -j REJECT


# TCPACCEPT
$IPTABLES -N TCPACCEPT
$IPTABLES -A TCPACCEPT -p tcp --syn -m limit --limit $TCPSYNLIMIT --limit-burst $TCPSYNLIMITBURST -j ACCEPT
$IPTABLES -A TCPACCEPT -p tcp --syn -j LSYNFLOOD
$IPTABLES -A TCPACCEPT -p tcp ! --syn -j ACCEPT


# 不正なフラグの組み合わせ
$IPTABLES -N CHECKBADFLAG
$IPTABLES -A CHECKBADFLAG -p tcp --tcp-flags ALL FIN,URG,PSH -j LBADFLAG
$IPTABLES -A CHECKBADFLAG -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LBADFLAG
$IPTABLES -A CHECKBADFLAG -p tcp --tcp-flags ALL ALL -j LBADFLAG
$IPTABLES -A CHECKBADFLAG -p tcp --tcp-flags ALL NONE -j LBADFLAG
$IPTABLES -A CHECKBADFLAG -p tcp --tcp-flags SYN,RST SYN,RST -j LBADFLAG
$IPTABLES -A CHECKBADFLAG -p tcp --tcp-flags SYN,FIN SYN,FIN -j LBADFLAG
$IPTABLES -A CHECKBADFLAG -p tcp --tcp-option 64 -j LBADFLAG
$IPTABLES -A CHECKBADFLAG -p tcp --tcp-option 128 -j LBADFLAG


# SMB
$IPTABLES -N SMB
$IPTABLES -A SMB -p tcp --dport 137:139 -j DROP
$IPTABLES -A SMB -p tcp --dport 445 -j DROP
$IPTABLES -A SMB -p udp --dport 137:139 -j DROP
$IPTABLES -A SMB -p udp --dport 445 -j DROP
$IPTABLES -A SMB -p tcp --sport 137:139 -j DROP
$IPTABLES -A SMB -p tcp --sport 445 -j DROP
$IPTABLES -A SMB -p udp --sport 137:139 -j DROP
$IPTABLES -A SMB -p udp --sport 445 -j DROP


## Inbound ICMP/Traceroute
$IPTABLES -N ICMPINBOUND

# Ping Flood対策
$IPTABLES -A ICMPINBOUND -p icmp --icmp-type echo-request -m limit --limit $PINGLIMIT --limit-burst $PINGLIMITBURST -j ACCEPT
$IPTABLES -A ICMPINBOUND -p icmp --icmp-type echo-request -j LPINGFLOOD

# ICMP-Redirectsを破棄
$IPTABLES -A ICMPINBOUND -p icmp --icmp-type redirect -j LDROP

# ICMP-Timestampを破棄
$IPTABLES -A ICMPINBOUND -p icmp --icmp-type timestamp-request -j LDROP
$IPTABLES -A ICMPINBOUND -p icmp --icmp-type timestamp-reply -j LDROP

# ICMP-address-maskを破棄
$IPTABLES -A ICMPINBOUND -p icmp --icmp-type address-mask-request -j LDROP
$IPTABLES -A ICMPINBOUND -p icmp --icmp-type address-mask-reply -j LDROP

# その他のICMPをACCEPT
$IPTABLES -A ICMPINBOUND -p icmp -j ACCEPT

## Outbound ICMP/Traceroute
$IPTABLES -N ICMPOUTBOUND

# ICMP-Redirectsを破棄
$IPTABLES -A ICMPOUTBOUND -p icmp --icmp-type redirect -j LDROP

# ICMP-TTL-Expiredを破棄
$IPTABLES -A ICMPOUTBOUND -p icmp --icmp-type ttl-zero-during-transit -j LDROP
$IPTABLES -A ICMPOUTBOUND -p icmp --icmp-type ttl-zero-during-reassembly -j LDROP

# ICMP-Parameter-Problemを破棄
$IPTABLES -A ICMPOUTBOUND -p icmp --icmp-type parameter-problem -j LDROP

# ICMP-Timestampを破棄
$IPTABLES -A ICMPOUTBOUND -p icmp --icmp-type timestamp-request -j LDROP
$IPTABLES -A ICMPOUTBOUND -p icmp --icmp-type timestamp-reply -j LDROP

# ICMP-address-maskを破棄
$IPTABLES -A ICMPOUTBOUND -p icmp --icmp-type address-mask-request -j LDROP
$IPTABLES -A ICMPOUTBOUND -p icmp --icmp-type address-mask-reply -j LDROP

# その他のICMPを許可
$IPTABLES -A ICMPOUTBOUND -p icmp -j ACCEPT


## INPUT-Chain

# 既知の接続に結び付けられないパケットを破棄
$IPTABLES -A INPUT -m state --state INVALID -j LINVALID

# 不正なフラグの組み合わせを破棄
$IPTABLES -A INPUT -p tcp -j CHECKBADFLAG

# ローカルのループバックトラフィックは許可
$IPTABLES -A INPUT -i lo -j ACCEPT

# ローカルアドレス宛をリジェクト
$IPTABLES -A INPUT -d 127.0.0.0/8 -j LREJECT

# 内部LANからファイアウォールまでのトラフィックを許可
$IPTABLES -A INPUT -i $INTIF -s $INTLAN -j ACCEPT

# 偽の内部LANを騙るトラフィックをリジェクト
$IPTABLES -A INPUT -s $INTLAN -j LREJECT

# ICMPフィルタ
$IPTABLES -A INPUT -i $EXTIF -p icmp -j ICMPINBOUND

# UDPのtracerouteを許可
$IPTABLES -A INPUT -p udp --dport 33434:33523 -j ACCEPT

# SMBのトラフィックを破棄
$IPTABLES -A INPUT -i $EXTIF -j SMB

# IDENT
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 113 -j REJECT --reject-with tcp-reset

# SSH
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 22 -j TCPACCEPT

# SMTP
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 25 -j TCPACCEPT

# DNS
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 53 -j TCPACCEPT
$IPTABLES -A INPUT -i $EXTIF -p udp --dport 53 -j ACCEPT

# NTP
$IPTABLES -A INPUT -i $EXTIF -s $NTP1 -p udp --sport 123 --dport 123 -j ACCEPT
$IPTABLES -A INPUT -i $EXTIF -s $NTP2 -p udp --sport 123 --dport 123 -j ACCEPT

# HTTP
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 80 -j TCPACCEPT

# HTTPS
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 443 -j TCPACCEPT

# POP-3
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 110 -j TCPACCEPT

# IMAP
#$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 143 -j TCPACCEPT

# ルータからのSYSLOGを受信
$IPTABLES -A INPUT -i $EXTIF -s $EXTGW -p udp --dport 514 -j ACCEPT

# ESTABLISHED/RELATED接続を許可
$IPTABLES -A INPUT -i $EXTIF -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport $UNPRIVPORTS -m state --state RELATED -j TCPACCEPT
$IPTABLES -A INPUT -i $EXTIF -p udp --dport $UNPRIVPORTS -m state --state RELATED -j ACCEPT

# 上記以外は破棄
$IPTABLES -A INPUT -j LDROP


## Output-Chain

# ローカルのループバックトラフィックは許可
$IPTABLES -A OUTPUT -o lo -j ACCEPT

# 内部LANからのトラフィックを許可
$IPTABLES -A OUTPUT -o $INTIF -d $INTLAN -j ACCEPT

# ICMPフィルタ
$IPTABLES -A OUTPUT -o $EXTIF -p icmp -j ICMPOUTBOUND

# SMBのトラフィックを破棄
$IPTABLES -A OUTPUT -o $EXTIF -j SMB

# IDENT
$IPTABLES -A OUTPUT -o $EXTIF -p tcp --sport 113 -j REJECT --reject-with tcp-reset

# SSH
$IPTABLES -A OUTPUT -o $EXTIF -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

# SMTP
$IPTABLES -A OUTPUT -o $EXTIF -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT

# DNS
$IPTABLES -A OUTPUT -o $EXTIF -p tcp --sport 53 -j ACCEPT
$IPTABLES -A OUTPUT -o $EXTIF -p udp --sport 53 -j ACCEPT

# NTP
$IPTABLES -A OUTPUT -o $EXTIF -d $NTP1 -p udp --sport 123 --dport 123 -j ACCEPT
$IPTABLES -A OUTPUT -o $EXTIF -d $NTP2 -p udp --sport 123 --dport 123 -j ACCEPT

# HTTP
$IPTABLES -A OUTPUT -o $EXTIF -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

# HTTPS
$IPTABLES -A OUTPUT -o $EXTIF -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT

# POP-3
$IPTABLES -A OUTPUT -o $EXTIF -p tcp --sport 110 -m state --state ESTABLISHED -j ACCEPT

# IMAP
#$IPTABLES -A OUTPUT -o $EXTIF -p tcp --sport 143 -m state --state ESTABLISHED -j ACCEPT


# 非特権ポートからのTCP/UDPトラフィックを許可
$IPTABLES -A OUTPUT -o $EXTIF -s $EXTIP -p tcp --sport $UNPRIVPORTS -j ACCEPT
$IPTABLES -A OUTPUT -o $EXTIF -s $EXTIP -p udp --sport $UNPRIVPORTS -j ACCEPT

# 上記以外は破棄
$IPTABLES -A OUTPUT -j LDROP

## FORWARD-Chain

# 既知の接続に結び付けられないパケットを破棄
$IPTABLES -A FORWARD -m state --state INVALID -j LINVALID

# 不正なフラグの組み合わせを破棄
$IPTABLES -A FORWARD -p tcp -j CHECKBADFLAG

# SMBのトラフィックを破棄
$IPTABLES -A FORWARD -o $EXTIF -j SMB

# 内部LANから外部ネットまでの非特権ポートからの転送を許可
$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -s $INTLAN -p tcp --sport $UNPRIVPORTS -j ACCEPT
$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -s $INTLAN -p udp --sport $UNPRIVPORTS -j ACCEPT
$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -s $INTLAN -p icmp -j ACCEPT

# 内部LANから外部ネットまでの非特権ポートへの転送を許可
$IPTABLES -A FORWARD -i $EXTIF -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A FORWARD -i $EXTIF -p tcp --dport $UNPRIVPORTS -m state --state RELATED -j TCPACCEPT
$IPTABLES -A FORWARD -i $EXTIF -p udp --dport $UNPRIVPORTS -m state --state RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $EXTIF -p icmp -m state --state RELATED -j ACCEPT
  
# Path MTU Discovery Black Hole
#$IPTABLES -A FORWARD -o $EXTIF -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

# 上記以外は破棄
$IPTABLES -A FORWARD -j LDROP


## PREROUTING


## POSTROUTING

# Masquerade
$IPTABLES -A POSTROUTING -t nat -o $EXTIF -j MASQUERADE