Commit b64ca400 authored by Branko Mikić's avatar Branko Mikić
Browse files

~ BugFix! The FORWARD_PORT target host argument didn't handle the optional...

~ BugFix! The FORWARD_PORT target host argument didn't handle the optional port correctly when omitted. This has been fixed.
~ ALLOW_PORT and FORWARD_PORT now have an optional protocol argument. When omitted ALLOW_PORT creates rules for both protocols (tcp|udp) while FORWARD_PORT defaults to tcp only.
~ checkProtocol() function added for argument check.
~ formatSubnetAsHexID() function renamed to formatAsHexID() as the function can be used on either an IP address or a subnet mask.
parent fc9a37d3
......@@ -15,10 +15,10 @@ printAbout()
[ALLOW_LINK_LOCAL on_link]
[ALLOW_SERVICE_DISCOVERY on_link]
[ALLOW_TUNNEL mode on_link from_address]
[ALLOW_PORT|ALLOW_SERVICE port[,port,port,...] ip|link]
[ALLOW_PORT|ALLOW_SERVICE port[,port,port,...] ip|link [tcp|udp]]
[FORWARD_SUBNET subnet/mask to_link]
[FORWARD_SUBNET_PROTECTIVE subnet/mask to_link]
[FORWARD_PORT|FORWARD_ROUTING ip|link port(s) to_address[:to_port]]
[FORWARD_PORT|FORWARD_ROUTING ip|link port(s) to_address[:to_port] [tcp|udp]]
[MAC_FILTER chain mac_address]
[POSTROUTING_MASQUERADE subnet/mask to_link]
[DEBUG_CHAIN chain_name]
......@@ -313,6 +313,22 @@ checkSubnetArgFormat()
return $?
}
###
### $1: Either tcp or udp
###
### Returns a string either 'tcp', 'udp'
### or 'any' if none of the other
###
checkProtocol()
{
echo $1 | grep -iP "(tcp|udp)" 1>/dev/nul 2>/dev/nul
if (($? == 0)); then
printf $1
else
printf "any"
fi
}
###
### $1: chain to search for device occurence in any rule
###
......@@ -451,7 +467,7 @@ deallocChain()
###
### Prints a hexadecimal representation (eg: 0xC0A8000010)
###
formatSubnetAsHexID() {
formatAsHexID() {
local sz; local sy;
# sed using bash! ${1//REPLACE_ME/WITH_THIS}
if [ $ENVID -eq 4 ]; then
......@@ -853,6 +869,9 @@ formatSubnetAsHexID() {
(( $? != 0 )) && error 70 "ALLOW_PORT expects a destination port or ports argument (eg: 80,443)"
done
# $3 == protocol?
PROTO=$(checkProtocol $3)
# $2 == device node or IP address?
checkIPArgFormat "$2"
if (( $? != 0 )); then
......@@ -862,23 +881,30 @@ formatSubnetAsHexID() {
(( $? != 0 )) && printf "# WARNING! '$2' currently not available. Maybe invoked later?\n"
FILTER_BY="-i $2"
printf "# allow port(s): %s to reach %s\n (WARNING! Ports reachable for any address configured on this device! Maybe this is unintended?)\n" $1 $2
printf "# allow port(s): %s (%s) to reach %s\n (WARNING! Ports reachable for any address configured on this device! Maybe this is unintended?)\n" $1 $PROTO $2
sz="$2"
else
sz=$(obtainNetPrefix $2)
[ -z $sz ] && error 73 "ALLOW_PORT has no route to '$2' or argument has malformed IP format"
sz=$(obtainLinkFromSubnetPrefix $sz)
FILTER_BY="-d $2"
printf "# allow port(s): %s to reach %s on %s\n" $1 $2 $sz
printf "# allow port(s): %s (%s) to reach %s on %s\n" $1 $PROTO $2 $(obtainLinkFromSubnetPrefix $sz)
sz="$(formatAsHexID $2)"
fi
ID="ALLOW_PORT_$1_$(formatSubnetAsHexID $2)_$sz"
ID="ALLOW_PORT_$1_$sz"
deleteRules USER-IN "$ID"
$IPTABLES -A USER-IN $FILTER_BY -p tcp -m multiport --dports $1 -j ACCEPT -m comment --comment "$ID"
if [[ $PROTO =~ any ]]; then
$IPTABLES -A USER-IN $FILTER_BY -p tcp -m multiport --ports $1 -j ACCEPT -m comment --comment "$ID"
$IPTABLES -A USER-IN $FILTER_BY -p udp -m multiport --ports $1 -j ACCEPT -m comment --comment "$ID"
else
$IPTABLES -A USER-IN $FILTER_BY -p $PROTO -m multiport --ports $1 -j ACCEPT -m comment --comment "$ID"
shift;
fi
shift; shift;
unset FILTER_BY; unset ay; unset ID;
unset FILTER_BY; unset PROTO; unset ay; unset ID;
;;
FORWARD_SUBNET)
......@@ -930,12 +956,12 @@ formatSubnetAsHexID() {
(( $? != 0 )) && sz=" (WARNING! '$2' currently not available. Maybe invoked later?)"
printf "# forwarding protectively %s (%s) to %s.%s\n" $1 $DEV $2 "$sz"
ID=$(printf "FORWARD_SUBNET_PROTECTIVE_%s_%s_%s" $DEV $(formatSubnetAsHexID "$1") $2)
ID=$(printf "FORWARD_SUBNET_PROTECTIVE_%s_%s_%s" $DEV $(formatAsHexID "$1") $2)
deleteRules FORWARD "$ID"
# for IPv6 subnets the max chain name length can
# be easily exceeded so we need a shorter name
#CHAIN=$(printf "%s-%s-%s" $(formatSubnetAsHexID "$1") $2 $DEV)
#CHAIN=$(printf "%s-%s-%s" $(formatAsHexID "$1") $2 $DEV)
CHAIN=$(printf "%X-IN" $(cksum <<<"$ID" | grep -oP "^\d*"))
allocChain $CHAIN
......@@ -965,8 +991,6 @@ formatSubnetAsHexID() {
$IPTABLES -I FORWARD $n -i $2 -o $DEV -d $1 -j $CHAIN -m comment --comment "$ID"
# for IPv6 subnets the max chain name length can
# be easily exceeded so we need a shorter name
CHAIN=$(printf "%X-OUT" $(cksum <<<"$ID" | grep -oP "^\d*"))
allocChain $CHAIN
......@@ -1011,7 +1035,11 @@ formatSubnetAsHexID() {
# create a mark ID (cksum)
MARK_ID=$(printf "0x%x" $(cksum <<<"$1$2$3" | grep -oP "^\d*"))
printf "# prerouting port fowarding from %s:%s to %s (MARK_ID: %s)\n" $1 $2 $3 $MARK_ID
# $4 == protocol (tcp|udp) with 'tcp' as default when not specified
PROTO=$(checkProtocol $4)
[[ $PROTO =~ any ]] && PROTO=tcp
printf "# prerouting port fowarding from %s:%s to %s (ID: %s)\n" $1 $2 $3 $MARK_ID
ID="FORWARD_ROUTING $MARK_ID"
deleteRules FORWARD "$ID"
......@@ -1023,8 +1051,8 @@ formatSubnetAsHexID() {
# This may look complicated but makes absolutely sense since our POSTROUTING
# needs to distinguish from traffic carrying our MARK_ID _and_ traffic on the
# corresponding port returned from the forwarded host.
$IPTABLES -t nat -A PREROUTING $FILTER_BY -p tcp -m multiport --dports $2 -j MARK --set-mark $MARK_ID -m comment --comment "$ID"
$IPTABLES -t nat -A PREROUTING -m mark --mark $MARK_ID -p tcp -j DNAT --to $3 -m comment --comment "$ID"
$IPTABLES -t nat -A PREROUTING $FILTER_BY -p $PROTO -m multiport --dports $2 -j MARK --set-mark $MARK_ID -m comment --comment "$ID"
$IPTABLES -t nat -A PREROUTING -m mark --mark $MARK_ID -p $PROTO -j DNAT --to $3 -m comment --comment "$ID"
# prerouting rewrites destination address for marked packets therefore these
# go through the FORWARD chain instead of INPUT, to avoid having other rules
......@@ -1035,16 +1063,16 @@ formatSubnetAsHexID() {
# allow packets back & forth from the forwarded host
# Attention! >> These response packets are _not_ carrying our MARK_ID
# therefore these rules are all inserted at index 1 so order matters!
sz=${3#*:}
[ -z $sz ] && sz=$2
$IPTABLES -I FORWARD 1 -p tcp -s ${3%:*}/32 -m multiport --sports $sz -j ACCEPT -m comment --comment "$ID"
$IPTABLES -I FORWARD 1 -p tcp -d ${3%:*}/32 -m multiport --dports $sz -j ACCEPT -m comment --comment "$ID"
[[ $3 =~ : ]] && sz=${3#*:} || sz=$2
$IPTABLES -I FORWARD 1 -p $PROTO -s ${3%:*}/32 -m multiport --sports $sz -j ACCEPT -m comment --comment "$ID"
$IPTABLES -I FORWARD 1 -p $PROTO -d ${3%:*}/32 -m multiport --dports $sz -j ACCEPT -m comment --comment "$ID"
# Masquerade only those carrying our MARK_ID!
$IPTABLES -t nat -I POSTROUTING 1 -m mark --mark $MARK_ID -d ${3%:*}/32 -j MASQUERADE -m comment --comment "$ID"
shift; shift; shift;
unset FILTER_BY; unset MARK_ID;
[[ $(checkProtocol $4) =~ any ]] && shift
unset FILTER_BY; unset PROTO; unset MARK_ID;
unset ID;
;;
......@@ -1082,7 +1110,7 @@ formatSubnetAsHexID() {
(( $? != 0 )) && sz=" (WARNING! '$2' currently not available. Maybe invoked later?)"
printf "# masquerading %s when leaving through %s.%s\n" $1 $2 "$sz"
ID=$(printf "POSTROUTING_MASQUERADE %s_%s_%s" $(obtainLinkFromSubnetPrefix $1) $(formatSubnetAsHexID "$1") $2)
ID=$(printf "POSTROUTING_MASQUERADE %s_%s_%s" $(obtainLinkFromSubnetPrefix $1) $(formatAsHexID "$1") $2)
deleteRules -t nat POSTROUTING "$ID"
$IPTABLES -t nat -A POSTROUTING -s $1 -o $2 -j MASQUERADE -m comment --comment "$ID"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment