#!/usr/bin/env bash # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # firewall_rule.sh -- allow some ports / protocols to vm instances # @VERSION@ source /root/func.sh lock="biglock" locked=$(getLockFile $lock) if [ "$locked" != "1" ] then exit 1 fi usage() { printf "Usage: %s: -a \n" $(basename $0) >&2 printf "sourcecidrs format: cidr1-cidr2-cidr3-...\n" } #set -x #FIXME: eating up the error code during execution of iptables fw_remove_backup() { local pubIp=$1 sudo iptables -t mangle -F _FIREWALL_$pubIp 2> /dev/null sudo iptables -t mangle -D PREROUTING -d $pubIp -j _FIREWALL_$pubIp 2> /dev/null sudo iptables -t mangle -X _FIREWALL_$pubIp 2> /dev/null } fw_restore() { local pubIp=$1 sudo iptables -t mangle -F FIREWALL_$pubIp 2> /dev/null sudo iptables -t mangle -D PREROUTING -d $pubIp -j FIREWALL_$pubIp 2> /dev/null sudo iptables -t mangle -X FIREWALL_$pubIp 2> /dev/null sudo iptables -t mangle -E _FIREWALL_$pubIp FIREWALL_$pubIp 2> /dev/null } fw_chain_for_ip () { local pubIp=$1 fw_remove_backup $1 sudo iptables -t mangle -E FIREWALL_$pubIp _FIREWALL_$pubIp 2> /dev/null sudo iptables -t mangle -N FIREWALL_$pubIp 2> /dev/null # drop if no rules match (this will be the last rule in the chain) sudo iptables -t mangle -A FIREWALL_$pubIp -j DROP> /dev/null # ensure outgoing connections are maintained (first rule in chain) sudo iptables -t mangle -I FIREWALL_$pubIp -m state --state RELATED,ESTABLISHED -j ACCEPT> /dev/null #ensure that this table is after VPN chain sudo iptables -t mangle -I PREROUTING 2 -d $pubIp -j FIREWALL_$pubIp success=$? if [ $success -gt 0 ] then # if VPN chain is not present for various reasons, try to add in to the first slot */ sudo iptables -t mangle -I PREROUTING -d $pubIp -j FIREWALL_$pubIp fi } fw_entry_for_public_ip() { local rules=$1 local pubIp=$(echo $rules | cut -d: -f1) local prot=$(echo $rules | cut -d: -f2) local sport=$(echo $rules | cut -d: -f3) local eport=$(echo $rules | cut -d: -f4) local scidrs=$(echo $rules | cut -d: -f5 | sed 's/-/ /g') logger -t cloud "$(basename $0): enter apply firewall rules for public ip $pubIp:$prot:$sport:$eport:$scidrs" # note that rules are inserted after the RELATED,ESTABLISHED rule # but before the DROP rule for src in $scidrs do [ "$prot" == "reverted" ] && continue; if [ "$prot" == "icmp" ] then typecode="$sport/$eport" [ "$eport" == "-1" ] && typecode="$sport" [ "$sport" == "-1" ] && typecode="any" sudo iptables -t mangle -I FIREWALL_$pubIp 2 -s $src -p $prot \ --icmp-type $typecode -j RETURN else sudo iptables -t mangle -I FIREWALL_$pubIp 2 -s $src -p $prot \ --dport $sport:$eport -j RETURN fi result=$? [ $result -gt 0 ] && logger -t cloud "Error adding iptables entry for $pubIp:$prot:$sport:$eport:$src" && break done logger -t cloud "$(basename $0): exit apply firewall rules for public ip $pubIp" return $result } get_vif_list() { local vif_list="" for i in /sys/class/net/eth*; do vif=$(basename $i); if [ "$vif" != "eth0" ] && [ "$vif" != "eth1" ] then vif_list="$vif_list $vif"; fi done if [ "$vif_list" == "" ] then vif_list="eth0" fi logger -t cloud "FirewallRule public interfaces = $vif_list" echo $vif_list } shift rules= while getopts 'a:' OPTION do case $OPTION in a) aflag=1 rules="$OPTARG" ;; ?) usage unlock_exit 2 $lock $locked ;; esac done VIF_LIST=$(get_vif_list) if [ "$rules" == "" ] then rules="none" fi #-a 172.16.92.44:tcp:80:80:0.0.0.0/0:,172.16.92.44:tcp:220:220:0.0.0.0/0:,172.16.92.44:tcp:222:222:192.168.10.0/24-75.57.23.0/22-88.100.33.1/32 # if any entry is reverted , entry will be in the format :reverted:0:0:0 # example : 172.16.92.44:tcp:80:80:0.0.0.0/0:,172.16.92.44:tcp:220:220:0.0.0.0/0:,200.1.1.2:reverted:0:0:0 # The reverted entries will fix the following partially #FIXME: rule leak: when there are multiple ip address, there will chance that entry will be left over if the ipadress does not appear in the current execution when compare to old one # example : In the below first transaction have 2 ip's whereas in second transaction it having one ip, so after the second trasaction 200.1.2.3 ip will have rules in mangle table. # 1) -a 172.16.92.44:tcp:80:80:0.0.0.0/0:,200.16.92.44:tcp:220:220:0.0.0.0/0:, # 2) -a 172.16.92.44:tcp:80:80:0.0.0.0/0:,172.16.92.44:tcp:220:220:0.0.0.0/0:, success=0 publicIps= rules_list=$(echo $rules | cut -d, -f1- --output-delimiter=" ") for r in $rules_list do pubIp=$(echo $r | cut -d: -f1) publicIps="$pubIp $publicIps" done unique_ips=$(echo $publicIps| tr " " "\n" | sort | uniq | tr "\n" " ") for u in $unique_ips do fw_chain_for_ip $u done for r in $rules_list do pubIp=$(echo $r | cut -d: -f1) fw_entry_for_public_ip $r success=$? if [ $success -gt 0 ] then logger -t cloud "$(basename $0): failure to apply fw rules for ip $pubIp" break else logger -t cloud "$(basename $0): successful in applying fw rules for ip $pubIp" fi done if [ $success -gt 0 ] then for p in $unique_ips do logger -t cloud "$(basename $0): restoring from backup for ip: $p" fw_restore $p done fi for p in $unique_ips do logger -t cloud "$(basename $0): deleting backup for ip: $p" fw_remove_backup $p done unlock_exit $success $lock $locked