기본 iptables 방화벽 스크립트

#!/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
위로 스크롤