|
|
937446 |
diff -uNr a/heartbeat/portblock b/heartbeat/portblock
|
|
|
937446 |
--- a/heartbeat/portblock 2013-06-18 15:22:27.000000000 +0200
|
|
|
937446 |
+++ b/heartbeat/portblock 2016-02-29 13:51:22.205860012 +0100
|
|
|
937446 |
@@ -24,8 +24,10 @@
|
|
|
937446 |
|
|
|
937446 |
# Defaults
|
|
|
937446 |
OCF_RESKEY_ip_default="0.0.0.0/0"
|
|
|
937446 |
+OCF_RESKEY_reset_local_on_unblock_stop_default="false"
|
|
|
937446 |
|
|
|
937446 |
: ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}}
|
|
|
937446 |
+: ${OCF_RESKEY_reset_local_on_unblock_stop=${OCF_RESKEY_reset_local_on_unblock_stop_default}}
|
|
|
937446 |
#######################################################################
|
|
|
937446 |
CMD=`basename $0`
|
|
|
937446 |
TICKLETCP=$HA_BIN/tickle_tcp
|
|
|
937446 |
@@ -37,16 +39,22 @@
|
|
|
937446 |
|
|
|
937446 |
$CMD is used to temporarily block ports using iptables.
|
|
|
937446 |
|
|
|
937446 |
- It can be used to turn off a port before bringing
|
|
|
937446 |
+ It can be used to blackhole a port before bringing
|
|
|
937446 |
up an IP address, and enable it after a service is started.
|
|
|
937446 |
- To do that for samba, the following resource line can be used:
|
|
|
937446 |
+ To do that for samba, the following can be used:
|
|
|
937446 |
|
|
|
937446 |
- $CMD::tcp::137,138::block \\
|
|
|
937446 |
- 10.10.10.20 \\
|
|
|
937446 |
- nmbd smbd \\
|
|
|
937446 |
- $CMD::tcp::137,138::unblock
|
|
|
937446 |
+ crm configure <
|
|
|
937446 |
+ primitive portblock-samba ocf:heartbeat:portblock \\
|
|
|
937446 |
+ params protocol=tcp portno=137,138 action=block
|
|
|
937446 |
+ primitive portunblock-samba ocf:heartbeat:portblock \\
|
|
|
937446 |
+ params protocol=tcp portno=137,138 action=unblock
|
|
|
937446 |
+ primitive samba-vip ocf:heartbeat:IPaddr2 \\
|
|
|
937446 |
+ params ip=10.10.10.20
|
|
|
937446 |
+ group g-samba \\
|
|
|
937446 |
+ portblock-samba samba-vip nmbd smbd portunblock-samba
|
|
|
937446 |
+ EOF
|
|
|
937446 |
|
|
|
937446 |
- This will do the follwing things:
|
|
|
937446 |
+ This will do the following things:
|
|
|
937446 |
|
|
|
937446 |
- DROP all incoming packets for TCP ports 137 and 138
|
|
|
937446 |
- Bring up the IP alias 10.10.10.20
|
|
|
937446 |
@@ -54,13 +62,16 @@
|
|
|
937446 |
- Re-enable TCP ports 137 and 138
|
|
|
937446 |
(enable normal firewall rules on those ports)
|
|
|
937446 |
|
|
|
937446 |
- This prevents clients from getting ICMP port unreachable
|
|
|
937446 |
- if they try to reconnect to the service after the alias is
|
|
|
937446 |
- enabled but before nmbd and smbd are running. These packets
|
|
|
937446 |
- will cause some clients to give up attempting to reconnect to
|
|
|
937446 |
- the server.
|
|
|
937446 |
+ This prevents clients from getting TCP RST if they try to reconnect
|
|
|
937446 |
+ to the service after the alias is enabled but before nmbd and smbd
|
|
|
937446 |
+ are running. These packets will cause some clients to give up
|
|
|
937446 |
+ attempting to reconnect to the server.
|
|
|
937446 |
+
|
|
|
937446 |
+ Attempts to connect to UDP and other non-TCP ports which have nothing
|
|
|
937446 |
+ listening can result in ICMP port unreachable responses, which can
|
|
|
937446 |
+ have the same undesirable affect on some clients.
|
|
|
937446 |
|
|
|
937446 |
- NOTE: iptables is linux-specific...
|
|
|
937446 |
+ NOTE: iptables is Linux-specific.
|
|
|
937446 |
|
|
|
937446 |
An additional feature in the portblock RA is the tickle ACK function
|
|
|
937446 |
enabled by specifying the tickle_dir parameter. The tickle ACK
|
|
|
937446 |
@@ -138,7 +149,7 @@
|
|
|
937446 |
The port number used to be blocked/unblocked.
|
|
|
937446 |
</longdesc>
|
|
|
937446 |
<shortdesc lang="en">portno</shortdesc>
|
|
|
937446 |
-<content type="integer" default="" />
|
|
|
937446 |
+<content type="string" default="" />
|
|
|
937446 |
</parameter>
|
|
|
937446 |
|
|
|
937446 |
<parameter name="action" unique="0" required="1">
|
|
|
937446 |
@@ -149,6 +160,26 @@
|
|
|
937446 |
<content type="string" default="" />
|
|
|
937446 |
</parameter>
|
|
|
937446 |
|
|
|
937446 |
+<parameter name="reset_local_on_unblock_stop" unique="0" required="0">
|
|
|
937446 |
+<content type="boolean" default="${OCF_RESKEY_reset_local_on_unblock_stop_default}" />
|
|
|
937446 |
+<shortdesc lang="en">(try to) reset server TCP sessions when unblock stops</shortdesc>
|
|
|
937446 |
+<longdesc>
|
|
|
937446 |
+If for some reason the long lived server side TCP sessions won't be cleaned up
|
|
|
937446 |
+by a reconfiguration/flush/stop of whatever services this portblock protects,
|
|
|
937446 |
+they would linger in the connection table, even after the IP is gone
|
|
|
937446 |
+and services have been switched over to an other node.
|
|
|
937446 |
+
|
|
|
937446 |
+An example would be the default NFS kernel server.
|
|
|
937446 |
+
|
|
|
937446 |
+These "known" connections may seriously confuse and delay a later switchback.
|
|
|
937446 |
+
|
|
|
937446 |
+Enabling this option will cause this agent to try to get rid of these connections
|
|
|
937446 |
+by injecting a temporary iptables rule to TCP-reset outgoing packets from the
|
|
|
937446 |
+blocked ports, and additionally tickle them locally,
|
|
|
937446 |
+just before it starts to DROP incoming packets on "unblock stop".
|
|
|
937446 |
+</longdesc>
|
|
|
937446 |
+</parameter>
|
|
|
937446 |
+
|
|
|
937446 |
<parameter name="ip" unique="0" required="0">
|
|
|
937446 |
<longdesc lang="en">
|
|
|
937446 |
The IP address used to be blocked/unblocked.
|
|
|
937446 |
@@ -233,12 +264,34 @@
|
|
|
937446 |
fi
|
|
|
937446 |
}
|
|
|
937446 |
|
|
|
937446 |
-run_tickle_tcp()
|
|
|
937446 |
+tickle_remote()
|
|
|
937446 |
{
|
|
|
937446 |
[ -z "$OCF_RESKEY_tickle_dir" ] && return
|
|
|
937446 |
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
|
|
|
937446 |
f=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
|
|
|
937446 |
- [ -f $f ] && cat $f | $TICKLETCP -n 3
|
|
|
937446 |
+ [ -r $f ] || return
|
|
|
937446 |
+ $TICKLETCP -n 3 < $f
|
|
|
937446 |
+}
|
|
|
937446 |
+
|
|
|
937446 |
+tickle_local()
|
|
|
937446 |
+{
|
|
|
937446 |
+ [ -z "$OCF_RESKEY_tickle_dir" ] && return
|
|
|
937446 |
+ f=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
|
|
|
937446 |
+ [ -r $f ] || return
|
|
|
937446 |
+ # swap "local" and "remote" address,
|
|
|
937446 |
+ # so we tickle ourselves.
|
|
|
937446 |
+ # We set up a REJECT with tcp-reset before we do so, so we get rid of
|
|
|
937446 |
+ # the no longer wanted potentially long lived "ESTABLISHED" connection
|
|
|
937446 |
+ # entries on the IP we are going to delet in a sec. These would get in
|
|
|
937446 |
+ # the way if we switch-over and then switch-back in quick succession.
|
|
|
937446 |
+ local i
|
|
|
937446 |
+ awk '{ print $2, $1; }' $f | $TICKLETCP
|
|
|
937446 |
+ netstat -tn | grep -Fw $OCF_RESKEY_ip || return
|
|
|
937446 |
+ for i in 0.1 0.5 1 2 4 ; do
|
|
|
937446 |
+ sleep $i
|
|
|
937446 |
+ awk '{ print $2, $1; }' $f | $TICKLETCP
|
|
|
937446 |
+ netstat -tn | grep -Fw $OCF_RESKEY_ip || break
|
|
|
937446 |
+ done
|
|
|
937446 |
}
|
|
|
937446 |
|
|
|
937446 |
SayActive()
|
|
|
937446 |
@@ -304,15 +357,30 @@
|
|
|
937446 |
#IptablesBLOCK {udp|tcp} portno,portno ip
|
|
|
937446 |
IptablesBLOCK()
|
|
|
937446 |
{
|
|
|
937446 |
+ local rc=0
|
|
|
937446 |
+ local try_reset=false
|
|
|
937446 |
+ if [ "$1/$4/$__OCF_ACTION" = tcp/unblock/stop ] &&
|
|
|
937446 |
+ ocf_is_true $reset_local_on_unblock_stop
|
|
|
937446 |
+ then
|
|
|
937446 |
+ try_reset=true
|
|
|
937446 |
+ fi
|
|
|
937446 |
if
|
|
|
937446 |
chain_isactive "$1" "$2" "$3"
|
|
|
937446 |
then
|
|
|
937446 |
: OK -- chain already active
|
|
|
937446 |
else
|
|
|
937446 |
+ if $try_reset ; then
|
|
|
937446 |
+ $IPTABLES -I OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
|
|
937446 |
+ tickle_local
|
|
|
937446 |
+ fi
|
|
|
937446 |
$IPTABLES -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP
|
|
|
937446 |
+ rc=$?
|
|
|
937446 |
+ if $try_reset ; then
|
|
|
937446 |
+ $IPTABLES -D OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
|
|
937446 |
+ fi
|
|
|
937446 |
fi
|
|
|
937446 |
|
|
|
937446 |
- return $?
|
|
|
937446 |
+ return $rc
|
|
|
937446 |
}
|
|
|
937446 |
|
|
|
937446 |
#IptablesUNBLOCK {udp|tcp} portno,portno ip
|
|
|
937446 |
@@ -338,7 +406,7 @@
|
|
|
937446 |
unblock)
|
|
|
937446 |
IptablesUNBLOCK "$@"
|
|
|
937446 |
rc=$?
|
|
|
937446 |
- run_tickle_tcp
|
|
|
937446 |
+ tickle_remote
|
|
|
937446 |
#ignore run_tickle_tcp exit code!
|
|
|
937446 |
return $rc
|
|
|
937446 |
;;
|
|
|
937446 |
@@ -411,6 +479,17 @@
|
|
|
937446 |
exit $OCF_ERR_CONFIGURED
|
|
|
937446 |
;;
|
|
|
937446 |
esac
|
|
|
937446 |
+
|
|
|
937446 |
+ if ocf_is_true $reset_local_on_unblock_stop; then
|
|
|
937446 |
+ if [ $action != unblock ] ; then
|
|
|
937446 |
+ ocf_log err "reset_local_on_unblock_stop is only relevant with action=unblock"
|
|
|
937446 |
+ exit $OCF_ERR_CONFIGURED
|
|
|
937446 |
+ fi
|
|
|
937446 |
+ if [ -z $OCF_RESKEY_tickle_dir ] ; then
|
|
|
937446 |
+ ocf_log warn "reset_local_on_unblock_stop works best with tickle_dir enabled as well"
|
|
|
937446 |
+ fi
|
|
|
937446 |
+ fi
|
|
|
937446 |
+
|
|
|
937446 |
return $OCF_SUCCESS
|
|
|
937446 |
}
|
|
|
937446 |
|
|
|
937446 |
@@ -451,6 +530,7 @@
|
|
|
937446 |
portno=$OCF_RESKEY_portno
|
|
|
937446 |
action=$OCF_RESKEY_action
|
|
|
937446 |
ip=$OCF_RESKEY_ip
|
|
|
937446 |
+reset_local_on_unblock_stop=$OCF_RESKEY_reset_local_on_unblock_stop
|
|
|
937446 |
|
|
|
937446 |
case $1 in
|
|
|
937446 |
start)
|