#!/bin/bash
####################################################################
#
# iptables Firewall Script
#
# by hasu0707@gmail.com
#
####################################################################
IS_DEBUG=1
######################################################################
# 화이트 리스트 (,로 구분한다)
######################################################################
WHITE_LIST="10.202.18.161,10.202.207.59,10.202.205.209"
######################################################################
# 기본 정책
######################################################################
#DEFAULT_POLICY="DROP"
DEFAULT_POLICY="ACCEPT"
######################################################################
# Linux Command Path
######################################################################
IP6TABLES_CMD="ip6tables"
IPTABLES_CMD="iptables"
######################################################################
# Usage
######################################################################
func_usage() {
echo
echo "Usage (as root): $0 [start | restart | stop]"
echo
echo "Examples:"
echo " # ${0} start"
echo " # ${0} restart"
echo " # ${0} stop"
echo
}
######################################################################
# 디버깅 메세지 출력
######################################################################
func_debug_msg() {
if [[ ${IS_DEBUG} -eq 1 ]]
then
echo "DEBUG:${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9}"
fi
}
######################################################################
# 커맨드 디버깅 메세지 출력
######################################################################
func_run_cmd() {
if [[ ${IS_DEBUG} -eq 1 ]]
then
echo "CMD: ${1}"
eval "${1}"
echo
else
eval "${1}"
fi
}
#############################
# 시스템 IP주소 알아내기
#############################
get_system_ip_addr() {
SYSTEM_IP_ADDR=$(hostname -I | awk '{print $1}')
if [ -z ${SYSTEM_IP_ADDR} ]
then
echo "ERROR: Unknown IP Address."
exit 1
fi
echo "IP_ADDR: ${SYSTEM_IP_ADDR}"
}
######################################################################
# 기본 정책 셋팅
######################################################################
func_set_default_policy() {
func_debug_msg ${FUNCNAME[0]}
${IPTABLES_CMD} -P INPUT ${DEFAULT_POLICY}
${IPTABLES_CMD} -P OUTPUT ${DEFAULT_POLICY}
${IPTABLES_CMD} -P FORWARD ${DEFAULT_POLICY}
}
######################################################################
# Clean rules
######################################################################
func_clean_rules() {
func_debug_msg ${FUNCNAME[0]}
# Remove any existing rules form all chains
${IPTABLES_CMD} -F
${IPTABLES_CMD} -F -t nat
${IPTABLES_CMD} -F -t mangle
${IPTABLES_CMD} -F -t raw
${IPTABLES_CMD} -F -t filter
# Remove any pre-existing user-defined chains
${IPTABLES_CMD} -X
${IPTABLES_CMD} -X -t nat
${IPTABLES_CMD} -X -t mangle
${IPTABLES_CMD} -X -t raw
${IPTABLES_CMD} -X -t filter
# Zero all packet and byte counters
${IPTABLES_CMD} -Z
${IPTABLES_CMD} -Z -t nat
${IPTABLES_CMD} -Z -t mangle
${IPTABLES_CMD} -Z -t raw
${IPTABLES_CMD} -Z -t filter
}
func_block_ipv6_traffic() {
func_debug_msg ${FUNCNAME[0]}
# If the ip6tables command is available, try to block all IPv6 traffic.
if [ -x ${IP6TABLES_CMD} ]; then
# Set the default policies (drop everything).
${IP6TABLES_CMD} -P INPUT ${DEFAULT_POLICY} 2>/dev/null
${IP6TABLES_CMD} -P FORWARD ${DEFAULT_POLICY} 2>/dev/null
${IP6TABLES_CMD} -P OUTPUT ${DEFAULT_POLICY} 2>/dev/null
# Delete all rules.
${IP6TABLES_CMD} -F 2>/dev/null
${IP6TABLES_CMD} -t mangle -F 2>/dev/null
# Delete all (non-builtin) user-defined chains.
${IP6TABLES_CMD} -X 2>/dev/null
${IP6TABLES_CMD} -t mangle -X 2>/dev/null
# Zero all packet and byte counters.
${IP6TABLES_CMD} -Z 2>/dev/null
${IP6TABLES_CMD} -t mangle -Z 2>/dev/null
else
echo "${IP6_TABLES} not available"
fi
}
######################################################################
# Input rules
######################################################################
func_set_default_lo_rules() {
func_debug_msg ${FUNCNAME[0]}
#######################################################
# Allow unlimited traffic on loopback interface
#######################################################
${IPTABLES_CMD} -A INPUT -i lo -j ACCEPT
${IPTABLES_CMD} -A OUTPUT -o lo -j ACCEPT
}
######################################################################
# 외부에서 방화벽으로 접근 (WAN→this device)
# ${1} : 외부 서버 주소
# ex) "-s 123.123.123.12/32" : 특정 외부 주소
# "-m geoip --src-cc KR" : geoip 적용
# "-s ${ANY_NET}" : 모든 주소
# ${2} : 목적지
# ${3} : 프로토콜
# ${4} : 포트 번호
# ${5} : comment
# ${6} : ACCEPT (1=ACCEPT, 0=DENY, *=REJECT)
# ex) "-s ${WHITE_LIST}" "tcp" "52400:52450" "WAN->this device:ftp-data" "1"
######################################################################
func_add_user_incoming() {
func_debug_msg ${FUNCNAME[0]} "${1}" "${2}" "${3}" "${4}" "${5}" "${6}"
RULE_CMD="${IPTABLES_CMD} -A INPUT ${1} -d ${2} -p ${3} -m ${3} --dport ${4} -m conntrack --ctstate NEW,ESTABLISHED -m comment --comment \"${5}\""
case "${6}" in
"0")
RULE_CMD="${RULE_CMD} -j DROP"
;;
"1")
RULE_CMD="${RULE_CMD} -j ACCEPT"
;;
*)
RULE_CMD="${RULE_CMD} -j REJECT"
;;
esac
func_run_cmd "${RULE_CMD}"
RULE_CMD="${IPTABLES_CMD} -A OUTPUT -p ${3} -m ${3} --sport ${4} -m conntrack --ctstate ESTABLISHED -m comment --comment \"${5}\""
case "${6}" in
"0")
RULE_CMD="${RULE_CMD} -j DROP"
;;
"1")
RULE_CMD="${RULE_CMD} -j ACCEPT"
;;
*)
RULE_CMD="${RULE_CMD} -j REJECT"
;;
esac
func_run_cmd "${RULE_CMD}"
}
######################################################################
# 외부에서 들어오는 트래픽을 추가한다.
######################################################################
func_add_incoming_rules() {
func_debug_msg ${FUNCNAME[0]} "${1}" "${2}" "${3}" "${4}" "${5}" "${6}"
# nslookup 내부에서 외부로 통신 가능하게 셋팅
${IPTABLES_CMD} -A INPUT -p udp --dport 53 -j ACCEPT
${IPTABLES_CMD} -A INPUT -p udp --sport 53 -j ACCEPT
${IPTABLES_CMD} -A OUTPUT -p udp --sport 53 -j ACCEPT
${IPTABLES_CMD} -A OUTPUT -p udp --sport 53 -j ACCEPT
# https 내부에서 외부로 통신 가능하게 셋팅
${IPTABLES_CMD} -A INPUT -p tcp --dport 443 -j ACCEPT
${IPTABLES_CMD} -A INPUT -p tcp --sport 443 -j ACCEPT
${IPTABLES_CMD} -A OUTPUT -p tcp --sport 443 -j ACCEPT
${IPTABLES_CMD} -A OUTPUT -p tcp --sport 443 -j ACCEPT
# http 내부에서 외부로 통신 가능하게 셋팅
${IPTABLES_CMD} -A INPUT -p tcp --dport 80 -j ACCEPT
${IPTABLES_CMD} -A INPUT -p tcp --sport 80 -j ACCEPT
${IPTABLES_CMD} -A OUTPUT -p tcp --sport 80 -j ACCEPT
${IPTABLES_CMD} -A OUTPUT -p tcp --sport 80 -j ACCEPT
# icmp 허용
#${IPTABLES_CMD} -A INPUT -p icmp -j ACCEPT
#${IPTABLES_CMD} -A OUTPUT -p icmp -j ACCEPT
func_add_user_incoming "-s ${WHITE_LIST}" "${SYSTEM_IP_ADDR}" "tcp" "22" "Incoming Rule:ssh" "1"
func_add_user_incoming "-s ${WHITE_LIST}" "${SYSTEM_IP_ADDR}" "tcp" "8080" "Incoming Rule:ssc2" "1"
func_add_user_incoming "-s ${WHITE_LIST}" "${SYSTEM_IP_ADDR}" "tcp" "9090" "Incoming Rule:ssc1" "1"
}
######################################################################
# 모두 차단
######################################################################
func_final_rules() {
func_debug_msg ${FUNCNAME[0]} "${1}" "${2}" "${3}" "${4}" "${5}" "${6}"
${IPTABLES_CMD} -A INPUT -j DROP
${IPTABLES_CMD} -A OUTPUT -j ACCEPT
${IPTABLES_CMD} -A FORWARD -j DROP
}
######################################################################
# Main
######################################################################
if [ "$2" != "" ]; then
echo
echo "Argument \"$2\" not recognized."
func_usage
echo
exit 1
fi
get_system_ip_addr
case "$1" in
start|restart)
func_clean_rules
func_set_default_policy
func_set_default_lo_rules
DEFAULT_POLICY="DROP"
func_block_ipv6_traffic
func_add_incoming_rules
func_final_rules
;;
stop)
DEFAULT_POLICY="ACCEPT"
func_clean_rules
func_set_default_policy
func_block_ipv6_traffic
;;
*)
func_usage
;;
esac
exit 0