CentOS7、firewalldを止めてiptablesにする際のドハマり解決

CentOS7ではいわゆるファイアウォールとしてfirewalldが実装されていますが、よく解らないので、昔から使い慣れたiptablesを使うといった方が数多く見受けられます。
「なんちゃって管理者」の私もその一人、そもそもiptablesは全く理解出来てない知見・力量レベルですが、他人様が作られたスクリプトなどを転用して使わせていただいてます。
しかし、丸コピーでは動かない(これは当然)だけでなく、サーバと外部ネットワークの通信が遮断される(全くできなくなってしまう)といったドハマりポイントもあり、1wほど悩んでました。

結果として、少しずつトライアンドエラーで試していく事でハマリポイントからは脱出できたようなので、その内容を備忘録として残しておきます。
他の方々の環境で正しく動くか、また、この内容が妥当かどうかは不明・無保証なのでご注意下さい。

参考にしたルートコンテンツはこちら
「俺史上最強のiptablesをさらす」
https://qiita.com/suin/items/5c4e21fa284497782f71
(2021年時点ではメンテナンスされていない模様)

----以下、当家自鯖用にアレンジしたシェルスクリプト。

#!bin/bash


# パス
PATH=/sbin:/usr/sbin:/bin:/usr/bin

###########################################################
# IPの定義
# 必要に応じて定義する。定義しなくても動作する。
###########################################################

# 内部ネットワークとして許可する範囲
# LOCAL_NET="xxx.xxx.xxx.xxx/xx"
LOCAL_NET="192.168.0.0/24"

# 内部ネットワークとして一部制限付きで許可する範囲
# LIMITED_LOCAL_NET="xxx.xxx.xxx.xxx/xx"

# ZabbixサーバーIP
# ZABBIX_IP="xxx.xxx.xxx.xxx"
ZABBIX_IP="192.168.0.5"

# 全てのIPを表す設定を定義
ANY="0.0.0.0/0"

# 信頼可能ホスト(配列)
# ALLOW_HOSTS=(
# 	"xxx.xxx.xxx.xxx"
# 	"xxx.xxx.xxx.xxx"
# 	"xxx.xxx.xxx.xxx"
# )

#2nd DNS
ALLOW_HOSTS=(
#SELF
        "127.0.0.1"
        "192.168.0.5"
#       win10pc
        "192.168.0.51"
#       /* 2nd name server 1/3 */
        "(2nd name server 1/3のip)"

#       /* 2nd name server 2/3 */
        "(2nd name server 2/3のip)"

#       /* 2nd name server 3/3 */
        "(2nd name server 3/3のip)"
)


# 無条件破棄するリスト(配列)
# DENY_HOSTS=(
# 	"xxx.xxx.xxx.xxx"
# 	"xxx.xxx.xxx.xxx"
# 	"xxx.xxx.xxx.xxx"
# )

###########################################################
# ポート定義
###########################################################

SSH=20022
FTP=20,21
DNS=53
SMTP=25,465,587
POP3=110,995
IMAP=143,993

#http2812はmonit、10000はwebmin、10024,10026はamavis用
HTTP=80,443,2812,10000,10024,10026
IDENT=113
NTP=123
MYSQL=3306
NET_BIOS=135,137,138,139,445
DHCP=67,68

###########################################################
# 関数
###########################################################

# iptablesの初期化, すべてのルールを削除
initialize() 
{

##Assertion failed on job for iptables.service.エラー対策
iptables -S
service iptables save
##

# テーブル初期化
	iptables -F

# チェーンを削除
	iptables -X

# パケットカウンタ・バイトカウンタをクリア
	iptables -Z

	iptables -P INPUT   ACCEPT
	iptables -P OUTPUT  ACCEPT
	iptables -P FORWARD ACCEPT
}

# ルール適用後の処理
finailize()
{
# 設定の保存
# 保存したもので再起動してみる
	return 0
	/usr/libexec/iptables/iptables.init save&&
#	iptables-save &&
	systemctl restart iptables &&
	return 1
}

# 開発用
if [ "$1" == "dev" ]
then
	iptables() { echo "iptables $@"; }
	finailize() { echo "finailize"; }
fi

###########################################################
# iptablesの初期化
###########################################################
initialize


###########################################################
# ポリシーの決定
###########################################################

# すべてDROP。すべての穴をふさいでから必要なポートを空けていくのが良い。
iptables -P INPUT   DROP

iptables -P OUTPUT  ACCEPT
iptables -P FORWARD DROP

###########################################################
# 信頼可能なホストは許可
###########################################################

# ローカルホスト
# lo はローカルループバックのことで自分自身のホストを指す

# SELF -> SELF
iptables -A INPUT -i lo -j ACCEPT

# ローカルネットワーク
# $LOCAL_NET が設定されていれば LAN上の他のサーバとのやり取りを許可する
if [ "$LOCAL_NET" ]
then

# LOCAL_NET -> SELF
	iptables -A INPUT -p tcp -s $LOCAL_NET -j ACCEPT

fi

# 信頼可能ホスト
# $ALLOW_HOSTS が設定されていれば そのホストとのやり取りを許可する
if [ "${ALLOW_HOSTS}" ]
then
	for allow_host in ${ALLOW_HOSTS[@]}
	do

# allow_host -> SELF
		iptables -A INPUT -p tcp -s $allow_host -j ACCEPT
	done
fi

###########################################################
# $DENY_HOSTSからのアクセスは破棄
###########################################################
if [ "${DENY_HOSTS}" ]
then
	for deny_host in ${DENY_HOSTS[@]}
	do
		iptables -A INPUT -s $deny_host -m limit --limit 1/s -j LOG --log-prefix "deny_host: "
		iptables -A INPUT -s $deny_host -j DROP
	done
fi

###########################################################
# セッション確立後のパケット疎通は許可
###########################################################
iptables -A INPUT  -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT

###########################################################
# 攻撃対策: Stealth Scan
###########################################################

# "STEALTH_SCAN" という名前でチェーンを作る
iptables -N STEALTH_SCAN
iptables -A STEALTH_SCAN -j LOG --log-prefix "stealth_scan_attack: "
iptables -A STEALTH_SCAN -j DROP

# ステルススキャンらしきパケットは "STEALTH_SCAN" チェーンへジャンプする
iptables -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j STEALTH_SCAN
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j STEALTH_SCAN

iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN         -j STEALTH_SCAN
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST         -j STEALTH_SCAN
iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j STEALTH_SCAN

iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j STEALTH_SCAN
iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN     -j STEALTH_SCAN
iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH     -j STEALTH_SCAN
iptables -A INPUT -p tcp --tcp-flags ACK,URG URG     -j STEALTH_SCAN

###########################################################
# 攻撃対策: フラグメントパケットによるポートスキャン,DOS攻撃
# namap -v -sF などの対策
###########################################################
iptables -A INPUT -f -j LOG --log-prefix 'fragment_packet:'
iptables -A INPUT -f -j DROP
 


###########################################################
# 攻撃対策: Ping of Death
###########################################################
# 毎秒1回を超えるpingが10回続いたら破棄

# "PING_OF_DEATH" という名前でチェーンを作る
iptables -N PING_OF_DEATH
iptables -A PING_OF_DEATH -p icmp --icmp-type echo-request \
         -m hashlimit \
         --hashlimit 1/s \
         --hashlimit-burst 10 \
         --hashlimit-htable-expire 300000 \
         --hashlimit-mode srcip \
         --hashlimit-name t_PING_OF_DEATH \
         -j RETURN

# 制限を超えたICMPを破棄
iptables -A PING_OF_DEATH -j LOG --log-prefix "ping_of_death_attack: "
iptables -A PING_OF_DEATH -j DROP

# ICMP は "PING_OF_DEATH" チェーンへジャンプ
iptables -A INPUT -p icmp --icmp-type echo-request -j PING_OF_DEATH



###########################################################
# 攻撃対策: SYN Flood Attack
# この対策に加えて Syn Cookie を有効にすべし。
###########################################################

# "SYN_FLOOD" という名前でチェーンを作る
iptables -N SYN_FLOOD
iptables -A SYN_FLOOD -p tcp --syn \
         -m hashlimit \
         --hashlimit 200/s \
         --hashlimit-burst 3 \
         --hashlimit-htable-expire 300000 \
         --hashlimit-mode srcip \
         --hashlimit-name t_SYN_FLOOD \
         -j RETURN

# 解説
# -m hashlimit                       ホストごとに制限するため limit ではなく hashlimit を利用する
# --hashlimit 200/s                  秒間に200接続を上限にする
# --hashlimit-burst 3                上記の上限を超えた接続が3回連続であれば制限がかかる
# --hashlimit-htable-expire 300000   管理テーブル中のレコードの有効期間(単位:ms
# --hashlimit-mode srcip             送信元アドレスでリクエスト数を管理する
# --hashlimit-name t_SYN_FLOOD       /proc/net/ipt_hashlimit に保存されるハッシュテーブル名
# -j RETURN                          制限以内であれば、親チェーンに戻る

# 制限を超えたSYNパケットを破棄
iptables -A SYN_FLOOD -j LOG --log-prefix "syn_flood_attack: "
iptables -A SYN_FLOOD -j DROP

# SYNパケットは "SYN_FLOOD" チェーンへジャンプ
iptables -A INPUT -p tcp --syn -j SYN_FLOOD


###########################################################
# 攻撃対策: HTTP DoS/DDoS Attack
###########################################################

# "HTTP_DOS" という名前でチェーンを作る
iptables -N HTTP_DOS
iptables -A HTTP_DOS -p tcp -m multiport --dports $HTTP \
         -m hashlimit \
         --hashlimit 1/s \
         --hashlimit-burst 100 \
         --hashlimit-htable-expire 300000 \
         --hashlimit-mode srcip \
         --hashlimit-name t_HTTP_DOS \
         -j RETURN

# 解説
# -m hashlimit                       ホストごとに制限するため limit ではなく hashlimit を利用する
# --hashlimit 1/s                    秒間1接続を上限とする
# --hashlimit-burst 100              上記の上限を100回連続で超えると制限がかかる
# --hashlimit-htable-expire 300000   管理テーブル中のレコードの有効期間(単位:ms
# --hashlimit-mode srcip             送信元アドレスでリクエスト数を管理する
# --hashlimit-name t_HTTP_DOS        /proc/net/ipt_hashlimit に保存されるハッシュテーブル名
# -j RETURN                          制限以内であれば、親チェーンに戻る

# 制限を超えた接続を破棄
iptables -A HTTP_DOS -j LOG --log-prefix "http_dos_attack: "
iptables -A HTTP_DOS -j DROP

# HTTPへのパケットは "HTTP_DOS" チェーンへジャンプ
iptables -A INPUT -p tcp -m multiport --dports $HTTP -j HTTP_DOS




###########################################################
# 攻撃対策: IDENT port probe
# identを利用し攻撃者が将来の攻撃に備えるため、あるいはユーザーの
# システムが攻撃しやすいかどうかを確認するために、ポート調査を実行
# する可能性があります。
# DROP ではメールサーバ等のレスポンス低下になるため REJECTする
###########################################################
iptables -A INPUT -p tcp -m multiport --dports $IDENT -j REJECT --reject-with tcp-reset

###########################################################
# 攻撃対策: SSH Brute Force
# SSHはパスワード認証を利用しているサーバの場合、パスワード総当り攻撃に備える。
# 1分間に5回しか接続トライをできないようにする。
# SSHクライアント側が再接続を繰り返すのを防ぐためDROPではなくREJECTにする。
# SSHサーバがパスワード認証ONの場合、以下をアンコメントアウトする
###########################################################
iptables -A INPUT -p tcp --syn -m multiport --dports $SSH -m recent --name ssh_attack --set
iptables -A INPUT -p tcp --syn -m multiport --dports $SSH -m recent --name ssh_attack --rcheck --seconds 60 --hitcount 5 -j LOG --log-prefix "ssh_brute_force: "
iptables -A INPUT -p tcp --syn -m multiport --dports $SSH -m recent --name ssh_attack --rcheck --seconds 60 --hitcount 5 -j REJECT --reject-with tcp-reset


###########################################################
# 攻撃対策: FTP Brute Force
# FTPはパスワード認証のため、パスワード総当り攻撃に備える。
# 1分間に5回しか接続トライをできないようにする。
# FTPクライアント側が再接続を繰り返すのを防ぐためDROPではなくREJECTにする。
# FTPサーバを立ち上げている場合、以下をアンコメントアウトする
###########################################################
iptables -A INPUT -p tcp --syn -m multiport --dports $FTP -m recent --name ftp_attack --set
iptables -A INPUT -p tcp --syn -m multiport --dports $FTP -m recent --name ftp_attack --rcheck --seconds 60 --hitcount 5 -j LOG --log-prefix "ftp_brute_force: "
iptables -A INPUT -p tcp --syn -m multiport --dports $FTP -m recent --name ftp_attack --rcheck --seconds 60 --hitcount 5 -j REJECT --reject-with tcp-reset

###########################################################
# 全ホスト(ブロードキャストアドレス、マルチキャストアドレス)宛パケットは破棄
###########################################################
iptables -A INPUT -d 192.168.0.255   -j LOG --log-prefix "drop_broadcast: "
iptables -A INPUT -d 192.168.0.255   -j DROP
iptables -A INPUT -d 255.255.255.255 -j LOG --log-prefix "drop_broadcast: "
iptables -A INPUT -d 255.255.255.255 -j DROP
iptables -A INPUT -d 224.0.0.1       -j LOG --log-prefix "drop_broadcast: "
iptables -A INPUT -d 224.0.0.1       -j DROP



###########################################################
# 全ホスト(ANY)からの入力許可
###########################################################

# ICMP: ping に応答する設定

# ANY -> SELF
iptables -A INPUT -p icmp -j ACCEPT

# HTTP, HTTPS
# ANY -> SELF
iptables -A INPUT -p tcp -m multiport --dports $HTTP -j ACCEPT

# SSH: ホストを制限する場合は TRUST_HOSTS に信頼ホストを書き下記をコメントアウトする
# ANY -> SELF
iptables -A INPUT -p tcp -m multiport --dports $SSH -j ACCEPT

# FTP
# ANY -> SELF
iptables -A INPUT -p tcp -m multiport --dports $FTP -j ACCEPT

# DNS
# ANY -> SELF
iptables -A INPUT -p tcp -m multiport --sports $DNS -j ACCEPT

# SMTP
# ANY -> SELF
iptables -A INPUT -p tcp -m multiport --sports $SMTP -j ACCEPT

# POP3
# ANY -> SELF
iptables -A INPUT -p tcp -m multiport --sports $POP3 -j ACCEPT

# IMAP
# ANY -> SELF
iptables -A INPUT -p tcp -m multiport --sports $IMAP -j ACCEPT


###########################################################
# ローカルネットワーク(制限付き)からの入力許可
###########################################################

if [ "$LIMITED_LOCAL_NET" ]
then
	# SSH

# LIMITED_LOCAL_NET -> SELF
	iptables -A INPUT -p tcp -s $LIMITED_LOCAL_NET -m multiport --dports $SSH -j ACCEPT
	
	# FTP
# LIMITED_LOCAL_NET -> SELF
	iptables -A INPUT -p tcp -s $LIMITED_LOCAL_NET -m multiport --dports $FTP -j ACCEPT

	# MySQL
# LIMITED_LOCAL_NET -> SELF
	iptables -A INPUT -p tcp -s $LIMITED_LOCAL_NET -m multiport --dports $MYSQL -j ACCEPT
fi

###########################################################
# 特定ホストからの入力許可
###########################################################

if [ "$ZABBIX_IP" ]
then
	# Zabbix関連を許可
# Zabbix -> SELF
	iptables -A INPUT -p tcp -s $ZABBIX_IP --dport 10050 -j ACCEPT
fi





#iptables -A INPUT -p tcp --dport 20 -j ACCEPT
#iptables -A INPUT -p tcp --dport 21 -j ACCEPT
#iptables -A INPUT -p tcp --dport 53 -j ACCEPT
#iptables -A INPUT -p tcp --dport 25 -j ACCEPT
#iptables -A INPUT -p tcp --dport 465 -j ACCEPT
#iptables -A INPUT -p tcp --dport 587 -j ACCEPT
#iptables -A INPUT -p tcp --dport 110 -j ACCEPT
#iptables -A INPUT -p tcp --dport 995 -j ACCEPT
#iptables -A INPUT -p tcp --dport 80 -j ACCEPT
#iptables -A INPUT -p tcp --dport 443 -j ACCEPT
#iptables -A INPUT -p tcp --dport 2812 -j ACCEPT
#iptables -A INPUT -p tcp --dport 10000 -j ACCEPT
#iptables -A INPUT -p tcp --dport 10024 -j ACCEPT
#iptables -A INPUT -p tcp --dport 10026 -j ACCEPT
#iptables -A INPUT -p tcp --dport 123 -j ACCEPT
#iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
#iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 20022 -j ACCEPT

# ほかACCEPTやDROPなどユーザによる設定
 
#ローカルループバックの接続を許可する。
#iptables -A INPUT -i lo -j ACCEPT

#以下、こちらから求めたパケットは許可する。←このセクション非常に重要******
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
#以上、こちらから求めたパケットは許可する。←このセクション非常に重要******
##
##この2行が無いと、ローカルホストから外部サーバへのpingや名前解決での接続が出来なくなる


#それ以外はログを残す。
#iptables -A INPUT -j LOG --log-prefix "drop_packet:" 

###########################################################
# それ以外
# 上記のルールにも当てはまらなかったものはロギングして破棄
###########################################################
iptables -A INPUT  -j LOG --log-prefix "drop_packet_IPTABLES:"
iptables -A INPUT  -j DROP


###########################################################
# SSH 締め出し回避策
# 30秒間スリープしてその後 iptables をリセットする。
# SSH が締め出されていなければ、 Ctrl-C を押せるはず。
###########################################################
trap 'finailize && exit 0' 2 # Ctrl-C をトラップする
echo "In 30 seconds iptables will be automatically reset."
echo "Don't forget to test new SSH connection!"
echo "If there is no problem then press Ctrl-C to finish."
echo "このメッセージが見られたなら Ctrl-C を押下して終了して下さい。そのまま放置するとiptablesを再度初期化して終了します。"
sleep 30
echo "rollback..."
initialize


カテゴリー: 未分類 パーマリンク

コメントを残す

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

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください