#!/bin/sh # Script to set up one of the nodes as a NAT gateway for all other nodes. # This is used to ensure that all nodes in the cluster can still originate # traffic to the external network even if there are no public addresses # available. # [ -n "$CTDB_BASE" ] || \ export CTDB_BASE=$(cd -P $(dirname "$0") ; dirname "$PWD") . $CTDB_BASE/functions loadconfig [ -z "$CTDB_NATGW_NODES" ] && exit 0 set_natgw_capability () { # Set NATGW capability depending on configuration if [ "$CTDB_NATGW_SLAVE_ONLY" = "yes" ] ; then ctdb setnatgwstate off else ctdb setnatgwstate on fi } delete_all() { _ip="${CTDB_NATGW_PUBLIC_IP%/*}" _maskbits="${CTDB_NATGW_PUBLIC_IP#*/}" [ -z "$CTDB_NATGW_PUBLIC_IFACE" ] || { delete_ip_from_iface $CTDB_NATGW_PUBLIC_IFACE $_ip $_maskbits >/dev/null 2>&1 } ip route del 0.0.0.0/0 metric 10 >/dev/null 2>/dev/null # Delete the masquerading setup from a previous iteration where we # were the NAT-GW iptables -D POSTROUTING -t nat -s $CTDB_NATGW_PRIVATE_NETWORK ! -d $CTDB_NATGW_PRIVATE_NETWORK -j MASQUERADE >/dev/null 2>/dev/null # remove any iptables rule we may have on this address iptables -D INPUT -p tcp --syn -d $_ip/32 -j REJECT 2>/dev/null } ensure_natgwmaster () { _event="$1" set -- $(ctdb natgwlist) natgwmaster="${1:--1}" # Default is -1 if natgwlist fails natgwip="$2" if [ "$natgwmaster" = "-1" ]; then echo "There is no NATGW master node" # The recovered event should never fail - we'll catch this # failure in the monitor event. if [ "$_event" = "recovered" ] ; then exit 0 else exit 1 fi fi } case "$1" in setup) set_natgw_capability ;; startup) # Error if CTDB_NATGW_PUBLIC_IP is listed in public addresses grep -q "^$CTDB_NATGW_PUBLIC_IP[[:space:]]" "${CTDB_PUBLIC_ADDRESSES:-/etc/ctdb/public_addresses}" && \ die "ERROR: NATGW configured to use a public address. NATGW must not use a public address." # do not send out arp requests from loopback addresses echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce ;; recovered|updatenatgw|ipreallocated) mypnn=$(ctdb pnn | cut -d: -f2) set_natgw_capability ensure_natgwmaster "$1" delete_all if [ "$mypnn" = "$natgwmaster" ]; then # This is the NAT GW echo 1 >/proc/sys/net/ipv4/ip_forward iptables -A POSTROUTING -t nat -s $CTDB_NATGW_PRIVATE_NETWORK ! -d $CTDB_NATGW_PRIVATE_NETWORK -j MASQUERADE # block all incoming connections to the natgw address ctdb_natgw_public_ip_host="${CTDB_NATGW_PUBLIC_IP%/*}/32" iptables -D INPUT -p tcp --syn -d $ctdb_natgw_public_ip_host -j REJECT 2>/dev/null iptables -I INPUT -p tcp --syn -d $ctdb_natgw_public_ip_host -j REJECT 2>/dev/null ip addr add $CTDB_NATGW_PUBLIC_IP dev $CTDB_NATGW_PUBLIC_IFACE ip route add 0.0.0.0/0 metric 10 via $CTDB_NATGW_DEFAULT_GATEWAY >/dev/null 2>/dev/null else # This is NOT the NAT GW ip route add 0.0.0.0/0 via $natgwip metric 10 # Make sure winbindd does not stay bound to this address # if we are no longer natgwmaster smbcontrol winbindd ip-dropped $CTDB_NATGW_PUBLIC_IP >/dev/null 2>/dev/null fi # flush our route cache echo 1 > /proc/sys/net/ipv4/route/flush ;; shutdown|removenatgw) delete_all ;; monitor) set_natgw_capability ensure_natgwmaster "$1" ;; *) ctdb_standard_event_handler "@" ;; esac exit 0