mirror of https://github.com/apache/cloudstack.git
VPC : add vpc_nat. sh for port_forwarding and static nat
This commit is contained in:
parent
e56dbdf78e
commit
f99c203aa0
|
|
@ -0,0 +1,255 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2012 Citrix Systems, Inc. Licensed under the
|
||||
# Apache License, Version 2.0 (the "License"); you may not use this
|
||||
# file except in compliance with the License. Citrix Systems, Inc.
|
||||
# reserves all rights not expressly granted by 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.
|
||||
#
|
||||
# Automatically generated by addcopyright.py at 04/03/2012
|
||||
# @VERSION@
|
||||
|
||||
source /root/func.sh
|
||||
|
||||
lock="biglock"
|
||||
locked=$(getLockFile $lock)
|
||||
if [ "$locked" != "1" ]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
usage() {
|
||||
printf "Usage: %s: (-A|-D) -r <target-instance-ip> -P protocol (-p port_range | -t icmp_type_code) -l <public ip address> -d <target port> -s <source cidrs> [-G] \n" $(basename $0) >&2
|
||||
}
|
||||
|
||||
#set -x
|
||||
|
||||
#Port (address translation) forwarding for tcp or udp
|
||||
tcp_or_udp_nat() {
|
||||
local instIp=$1
|
||||
local dport0=$2
|
||||
local dport=$(echo $2 | sed 's/:/-/')
|
||||
local publicIp=$3
|
||||
local port=$4
|
||||
local op=$5
|
||||
local proto=$6
|
||||
local cidrs=$7
|
||||
|
||||
logger -t cloud "$(basename $0): creating port fwd entry for PAT: public ip=$publicIp \
|
||||
instance ip=$instIp proto=$proto port=$port dport=$dport op=$op"
|
||||
|
||||
#if adding, this might be a duplicate, so delete the old one first
|
||||
[ "$op" == "-A" ] && tcp_or_udp_entry $instIp $dport0 $publicIp $port "-D" $proto $cidrs
|
||||
# the delete operation may have errored out but the only possible reason is
|
||||
# that the rules didn't exist in the first place
|
||||
# shortcircuit the process if error and it is an append operation
|
||||
# continue if it is delete
|
||||
(sudo iptables -t nat $op PREROUTING --proto $proto -d $publicIp \
|
||||
--destination-port $port -j DNAT \
|
||||
--to-destination $instIp:$dport &>> $OUTFILE || [ "$op" == "-D" ]) &&
|
||||
|
||||
local result=$?
|
||||
logger -t cloud "$(basename $0): done port fwd entry for PAT: public ip=$publicIp op=$op result=$result"
|
||||
return $result
|
||||
}
|
||||
|
||||
#Forward icmp
|
||||
icmp_entry() {
|
||||
local instIp=$1
|
||||
local icmptype=$2
|
||||
local publicIp=$3
|
||||
local op=$4
|
||||
|
||||
logger -t cloud "$(basename $0): creating port fwd entry for PAT: public ip=$publicIp \
|
||||
instance ip=$instIp proto=icmp port=$port dport=$dport op=$op"
|
||||
#if adding, this might be a duplicate, so delete the old one first
|
||||
[ "$op" == "-A" ] && icmp_entry $instIp $icmpType $publicIp "-D"
|
||||
# the delete operation may have errored out but the only possible reason is
|
||||
# that the rules didn't exist in the first place
|
||||
sudo iptables -t nat $op PREROUTING --proto icmp -d $publicIp --icmp-type $icmptype -j DNAT --to-destination $instIp &>> $OUTFILE
|
||||
|
||||
result=$?
|
||||
logger -t cloud "$(basename $0): done port fwd entry for PAT: public ip=$publicIp op=$op result=$result"
|
||||
return $result
|
||||
}
|
||||
|
||||
one_to_one_fw_entry() {
|
||||
local publicIp=$1
|
||||
local instIp=$2
|
||||
local proto=$3
|
||||
local portRange=$4
|
||||
local op=$5
|
||||
logger -t cloud "$(basename $0): create firewall entry for static nat: public ip=$publicIp \
|
||||
instance ip=$instIp proto=$proto portRange=$portRange op=$op"
|
||||
|
||||
#if adding, this might be a duplicate, so delete the old one first
|
||||
[ "$op" == "-A" ] && one_to_one_fw_entry $publicIp $instIp $proto $portRange "-D"
|
||||
# the delete operation may have errored out but the only possible reason is
|
||||
# that the rules didn't exist in the first place
|
||||
|
||||
# shortcircuit the process if error and it is an append operation
|
||||
# continue if it is delete
|
||||
sudo iptables -t nat $op PREROUTING -d $publicIp --proto $proto \
|
||||
--destination-port $portRange -j DNAT \
|
||||
--to-destination $instIp &>> $OUTFILE || [ "$op" == "-D" ]
|
||||
|
||||
result=$?
|
||||
logger -t cloud "$(basename $0): done firewall entry public ip=$publicIp op=$op result=$result"
|
||||
return $result
|
||||
}
|
||||
|
||||
static_nat() {
|
||||
local publicIp=$1
|
||||
local instIp=$2
|
||||
local op=$3
|
||||
local op2="-D"
|
||||
local rulenum=
|
||||
local proto="all"
|
||||
local tableNo = ""
|
||||
logger -t cloud "$(basename $0): static nat: public ip=$publicIp \
|
||||
instance ip=$instIp op=$op"
|
||||
|
||||
|
||||
#if adding, this might be a duplicate, so delete the old one first
|
||||
[ "$op" == "-A" ] && static_nat $publicIp $instIp "-D"
|
||||
# the delete operation may have errored out but the only possible reason is
|
||||
# that the rules didn't exist in the first place
|
||||
[ "$op" == "-A" ] && rulenum=1
|
||||
[ "$op" == "-A" ] && op2="-I"
|
||||
DEV_LIST = `ls /sys/class/net/ | grep eth`
|
||||
for dev in $DEV_LIST; do
|
||||
ip addr show dev $dev | grep inet | grep $ip &>> /dev/null
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
tableNo=$(echo $dev | awk -F'eth' '{print $2}')
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "$tableNo" ]
|
||||
then
|
||||
logger -t cloud "$(basename $0): failed due to cannot find eth device for public IP $publicIp"
|
||||
return 3
|
||||
fi
|
||||
|
||||
# shortcircuit the process if error and it is an append operation
|
||||
# continue if it is delete
|
||||
(sudo iptables -t nat $op PREROUTING -d $publicIp -j DNAT \
|
||||
--to-destination $instIp &>> $OUTFILE || [ "$op" == "-D" ]) &&
|
||||
# add mark to force the package go out through the eth the public IP is on
|
||||
(sudo iptables -t mangle $op PREROUTING -s $instIp -j MARK \
|
||||
--set-mark $tableNo &> $OUTFILE || [ "$op" == "-D" ]) &&
|
||||
(sudo iptables -t nat $op2 POSTROUTING $rulenum -s $instIp -j SNAT \
|
||||
--to-source $publicIp &>> $OUTFILE )
|
||||
result=$?
|
||||
logger -t cloud "$(basename $0): done static nat entry public ip=$publicIp op=$op result=$result"
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
|
||||
rflag=
|
||||
Pflag=
|
||||
pflag=
|
||||
tflag=
|
||||
lflag=
|
||||
dflag=
|
||||
sflag=
|
||||
Gflag=
|
||||
op=""
|
||||
|
||||
while getopts 'ADr:P:p:t:l:d:s:G' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
A) op="-A"
|
||||
;;
|
||||
D) op="-D"
|
||||
;;
|
||||
r) rflag=1
|
||||
instanceIp="$OPTARG"
|
||||
;;
|
||||
P) Pflag=1
|
||||
protocol="$OPTARG"
|
||||
;;
|
||||
p) pflag=1
|
||||
ports="$OPTARG"
|
||||
;;
|
||||
t) tflag=1
|
||||
icmptype="$OPTARG"
|
||||
;;
|
||||
l) lflag=1
|
||||
publicIp="$OPTARG"
|
||||
;;
|
||||
s) sflag=1
|
||||
cidrs="$OPTARG"
|
||||
;;
|
||||
d) dflag=1
|
||||
dport="$OPTARG"
|
||||
;;
|
||||
G) Gflag=1
|
||||
;;
|
||||
?) usage
|
||||
unlock_exit 2 $lock $locked
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
DEV_LIST=$(get_dev_list)
|
||||
OUTFILE=$(mktemp)
|
||||
|
||||
#Firewall ports for one-to-one/static NAT
|
||||
if [ "$Gflag" == "1" ]
|
||||
then
|
||||
if [ "$protocol" == "" ]
|
||||
then
|
||||
static_nat $publicIp $instanceIp $op
|
||||
else
|
||||
one_to_one_fw_entry $publicIp $instanceIp $protocol $dport $op
|
||||
fi
|
||||
result=$?
|
||||
if [ "$result" -ne 0 ] && [ "$op" != "-D" ]; then
|
||||
cat $OUTFILE >&2
|
||||
fi
|
||||
rm -f $OUTFILE
|
||||
if [ "$op" == "-D" ];then
|
||||
result=0
|
||||
fi
|
||||
unlock_exit $result $lock $locked
|
||||
fi
|
||||
|
||||
if [ "$sflag" != "1" ]
|
||||
then
|
||||
cidrs="0/0"
|
||||
fi
|
||||
|
||||
case $protocol in
|
||||
tcp|udp)
|
||||
tcp_or_udp_entry $instanceIp $dport $publicIp $ports $op $protocol $cidrs
|
||||
result=$?
|
||||
if [ "$result" -ne 0 ] && [ "$op" != "-D" ];then
|
||||
cat $OUTFILE >&2
|
||||
fi
|
||||
rm -f $OUTFILE
|
||||
if [ "$op" == "-D" ];then
|
||||
result=0
|
||||
fi
|
||||
unlock_exit $result $lock $locked
|
||||
;;
|
||||
"icmp")
|
||||
|
||||
icmp_entry $instanceIp $icmptype $publicIp $op
|
||||
if [ "$op" == "-D" ];then
|
||||
result=0
|
||||
fi
|
||||
unlock_exit $? $lock $locked
|
||||
;;
|
||||
*)
|
||||
printf "Invalid protocol-- must be tcp, udp or icmp\n" >&2
|
||||
unlock_exit 5 $lock $locked
|
||||
;;
|
||||
esac
|
||||
|
||||
unlock_exit 0 $lock $locked
|
||||
Loading…
Reference in New Issue