CentOS7になってから結構経ちましたが
Firewallの設定が未だにめんどくさいと思っていたので
思い切って必要最低限勝手にできるやつ作りました。
という個人的メモ的な
やりたいこと
・publicゾーンは、サービスとポートで制限をかける
・ssh用のゾーンを1つ作成し、SSHに対してIP制限をかける
・できれば、長ったらしいコマンドは書かないようにしたい
・こうしたいって思ったら修正変えやすい形がいい
必要そうなコマンドを流れに合わせて書いてみる
流れ
firewallが動いているかを確認する
↓
現在のアクティブのゾーンは何かを確認する
↓
アクティブのゾーンに追加したいサービスを追加する
↓
アクティブのゾーンに追加したいポートを追加する
↓
SSH用のゾーンを作成する
↓
SSH用のゾーンをACCEPTのゾーンとして登録する
↓
SSH用のゾーンにSSHサービスを追加する
↓
SSH用のゾーンに接続を許可するIPを追加する
↓
アクティブのゾーンからSSHを削除する
↓
設定をリロードする
↓
(必要ないけど)サービスを再起動する
コマンド
長いのでおりこみ
そもそも動いているかを確認する
]# systemctl status firewalld
※動いていなかった場合
]# systemctl start firewalld
現在のアクティブのゾーンを確認する
]# firewall-cmd --get-active-zone
public
interfaces: enp0s3
出てきたゾーン名(public)が現在firewallでアクティブになっているゾーン
アクティブのゾーンに設定されている状態を確認する
]# firewall-cmd --list-all
public (active)
target: default
icmp-block....
ここに出てくるのが、現在アクティブのゾーンに設定されている内容
publicゾーンにhttpサービスを追加する
]# firewall-cmd --add-service=HTTP --zone=public --permanent
--add-service : 追加を行うサービス名
--zone= : サービスを追加するゾーン、このオプションがない場合デフォルトのゾーンが指定される(大体は追加するゾーンは決まっているので、書いてあったほうがいい)
--permanent : このオプションが付くと、firewallが再起動されても有効な状態になる
publicゾーンに8080/tcpポートを追加する(TCPポート)
]# firewall-cmd --add-port=8080/tcp --zone=public --permanent
publicゾーンに8080/udpポートを追加する(UDPポート)
]# firewall-cmd --add-port=8080/udp --zone=public --permanent
この様に、ポート番号/ポートタイプ を「--add-port=」に指定する
SSH用のゾーンを作成する
]# firewall-cmd --new-zone=ssh --permanent
念のため、追加した時点で一度リロードを行う
]# firewall-cmd --reload
作成したゾーンをACCEPTとして登録する
]# firewall-cmd --zone=ssh --set-target=ACCEPT --permanent
--set-target : SSHゾーンの登録をどのような形でするのかを設定する
ACCEPT : 接続の許可
REJECT : 接続の拒否
sshゾーンにサービスとしてSSHを登録する
]# firewall-cmd --add-service=ssh --zone=ssh --permanent
SSH接続を許可するIPを登録する
]# firewall-cmd --add-source=192.168.1.123/32 --zone=ssh --permanent
--add-source : 今回の場合は、接続を許可するIPアドレス
192.168.1.123/32 という形で登録する
登録が終わったら再度リロードを行う
]# firewall-cmd --reload
publicゾーンからSSHを削除する
]# firewall-cmd remove-service=ssh --zone=public --permanent
SSHのゾーンを削除する前に行っても大丈夫ですが、ミスったときにSSH接続ができなくなるのである程度問題なくなってから削除するのをおすすめします
リロードをしてから、サービスを再起動する
]# firewall-cmd --reload
]# systemctl restart firewalld
長い
iptableのときよりやることが増えた感がすごい
あるものを使いたい精神なので、そう行ってもこれから離れられないんです…
そこでシェルスクリプト
書いたようなコマンドを全て内包して、ある程度自動でやってくれるように書いてしまおう!
あれもこれもと欲張った結果がこちらです
# !/bin/sh
## ==============================================================
## firewall setting
## ==============================================================
LINE="============================================================"
O_LINE="------------------------------------------------------------"
# public zone setting
PUBLIC_SERVICE=("ssh false" "http true" "https true" "dhcpv6-client true")
PUBLIC_PORT=("8080/tcp true" "8080/ucp true")
PUBLIC_SOURCE=("")
# ssh zone setting
SSH_SERIVECE=("ssh true")
SSH_PORT=("")
SSH_SOURCE=("127.0.0.1/32 true" "192.168.59.111/32 true")
# * when adding a new zone
#
## ==============================================================
## result
## ==============================================================
result_success () {
echo -e "${1} : [\e[34m success \e[m]"
}
# result_success "aaaa"
result_warning () {
echo -e "${1} : [\e[31m failure \e[m]";
}
result_q () {
if [ "${2}" = "success" ]; then
result_success "${1}"
elif [ "${2}" = "failure" ]; then
result_warning "${1}"
else
echo -e "${1} : [\e[35m ${2} \e[m]"
fi
}
cmd () {
result=`${2}`
result_q "${1}" "${result}"
}
## ==============================================================
## firewall cmd
## ==============================================================
firewall_service () {
service=`firewall-cmd --list-service --zone=${1} | grep "${2} "`
if [ "${?}" -eq 0 ]; then
result1=`firewall-cmd --remove-service=${2} --zone=${1} --permanent`
result_q "delete service ${2}" ${result1}
fi
if [ "${3}" = "true" ]; then
result2=`firewall-cmd --add-service=${2} --zone=${1} --permanent`
result_q "add service ${2}" ${result2}
fi
}
firewall_port () {
port=`firewall-cmd --list-port --zone=${1} | grep "${2} "`
if [ "${?}" -eq 0 ]; then
result1=`firewall-cmd --remove-port=${2} --zone=${1} --permanent`
result_q "delete port ${2}" ${result1}
fi
if [ "${3}" = "true" ]; then
result2=`firewall-cmd --add-port=${2} --zone=${1} --permanent`
result_q "add port ${2}" ${result2}
fi
}
firewall_ip () {
ip=`firewall-cmd --list-sources --zone=${1} | grep "${2} "`
if [ "${?}" -eq 0 ]; then
result1=`firewall-cmd --remove-source=${2} --zone=${1} --permanent`
result_q "remove ip ${2}" ${result1}
fi
if [ "${3}" = "true" ]; then
result2=`firewall-cmd --add-source=${2} --zone=${1} --permanent`
result_q "add ip ${2}" ${result2}
fi
}
zone_accept () {
echo ""
echo "${O_LINE}"
echo "${1} settings"
echo "${O_LINE}"
cmd "delete zone ${1}" "firewall-cmd --permanent --delete-zone=${1}"
cmd "new zone ${1}" "firewall-cmd --permanent --new-zone=${1}"
cmd "firewall reload" "firewall-cmd --reload"
cmd "ACCEPT zone" "firewall-cmd --permanent --zone=${1} --set-target=ACCEPT"
}
firewall_zone () {
# firewall public zone is default active zone
echo "${O_LINE}"
echo "public settings"
echo "${O_LINE}"
for (( I = 0; I < ${#PUBLIC_SERVICE[@]}; ++I )); do
set -- ${PUBLIC_SERVICE[I]}
firewall_service "public" ${1} ${2}
done
for (( I = 0; I < ${#PUBLIC_PORT[@]}; ++I )); do
set -- ${PUBLIC_PORT[I]}
firewall_port "public" ${1} ${2}
done
for (( I = 0; I < ${#PUBLIC_SOURCE[@]}; ++I )); do
set -- ${PUBLIC_SOURCE[I]}
firewall_ip "public" ${1} ${2}
done
# firewall ssh zone is add active zone
ssh="ssh"
zone_accept "${ssh}"
for (( I = 0; I < ${#SSH_SERVICE[@]}; ++I )); do
set -- ${SSH_SERVICE[I]}
firewall_service "${ssh}" ${1} ${2}
done
for (( I = 0; I < ${#SSH_PORT[@]}; ++I )); do
set -- ${SSH_PORT[I]}
firewall_port "${ssh}" ${1} ${2}
done
for (( I = 0; I < ${#SSH_SOURCE[@]}; ++I )); do
set -- ${SSH_SOURCE[I]}
firewall_ip "${ssh}" ${1} ${2}
done
# new zone status added below
# end a "zone" setting
cmd "firewall reload" "firewall-cmd --reload"
}
firewall_status () {
C_S="\e[37;41;1m"
C_E="\e[m"
cat << EOF
${O_LINE}
ZONE:${1}
service:
`firewall-cmd --list-service --zone=${1}`
port:
`firewall-cmd --list-port --zone=${1}`
sources:
`firewall-cmd --list-sources --zone=${1}`
${O_LINE}
EOF
}
view_status () {
echo ""
echo "${LINE}"
echo "setting firewall view"
echo "${LINE}"
firewall_status "public"
firewall_status "ssh"
# new zone status added below
}
## ==============================================================
## firewalld check
##
## return code
## -1 : running iptables
## ==============================================================
firewalld_check () {
echo "${LINE}"
echo "firewall running check"
echo "${LINE}"
r01=`systemctl status firewalld | grep running`
if [ -n "${r01}" ]; then
result_success "firewalld"
return 0
else
result_warning "firewalld"
r02=`systemctl status iptables | grep running`
if [ -n "${r02}" ]; then
result_success "iptables"
echo "# is running iptables system"
return 1
fi
result_warning "iptables"
echo "\e[31m*** No Resistance Tactice ***\e[m"
fi
return 2
}
## ==============================================================
## update command
## ==============================================================
update_line () {
r01=`firewalld_check`
if [ "${?}" -eq 1]; then
printf "${r01}\n"
exit 1
elif [ "${?}" -eq 2]; then
printf "${r01}\n"
echo "${O_LINE}"
echo "start firewalld"
echo "${O_LINE}"
eval "systemctl start firewalld"
if [ "${?}" -ne 0]; then
exit 1
fi
else
printf "${r01}\n"
fi
firewall_zone
cmd "restart service" "systemctl restart firewalld"
view_status
}
## ==============================================================
## check command
## ==============================================================
check_line () {
r01=`firewalld_check`
if [ "${?}" -eq 0 ]; then
printf "${r01}\n"
view_status
else
printf "${r01}\n"
fi
}
## ==============================================================
## help command
## ==============================================================
help_line () {
cat << EOF
this script was created to
automatically update the Firewalld of CentOS 7.
command.
[-h] : script help
[-c] : check firewall setting
[-u] : update firewall
EOF
}
usage_exit () {
echo "Usage: ${0} [-h] [-c] [-u]"
exit 1
}
while getopts hcu option
do
case $option in
h)
help_line
exit 0 ;;
c)
check_line
exit 0 ;;
u)
update_line
exit 0 ;;
\?)
usage_exit ;;
esac
done
usage_exit
public ゾーンに登録したいサービス
PUBLIC_SERVICE=("ssh false" "http true" "https true" "dhcpv6-client true")
public ゾーンに登録したいポート
PUBLIC_PORT=("8080/tcp true" "8080/ucp true")
public ゾーンに登録したいIP(publicゾーンでは使用しないが念のため)
PUBLIC_SOURCE=("")
SSH用のゾーンに登録したいサービス
SSH_SERIVECE=("ssh true")
SSH用のゾーンに登録したいポート
SSH_PORT=("")
SSH用のゾーンに登録したいIP
SSH_SOURCE=("127.0.0.1/32 true" "192.168.59.111/32 true")
全ての入力内容に共通しているものとして、スペース区切りでtrueかfalseか入れるようにしてあります。
trueなら、登録
falseなら、削除はするが登録はしない(いらなくなったものとか)
呼び出し方は
]# ./firewall_settngs.sh [-h] [-c] [-u]
[-h] : よくあるコマンドのヘルプ
[-c] : 現在設定されている項目の出力(public, ssh)
[-u] : 設定されている内容で、Firewallを更新する
終わりに
このシェルスクリプトでは、activeになっているゾーンはpublicという決め打ちになっているので、そうじゃなかった時が修正めんどくさそうだけど、そうなっているのは基本的にいじっている後なので、これ使う必要あるのかなぁと思います。
これでサーバを適当に作ったときのめんどくさい作業が少しでも減れば…