2 # Script to set up one of the nodes as a NAT gateway for all other nodes.
3 # This is used to ensure that all nodes in the cluster can still originate
4 # traffic to the external network even if there are no public addresses
8 [ -n "$CTDB_BASE" ] || \
9 CTDB_BASE=$(d=$(dirname "$0") ; cd -P "$d" ; dirname "$PWD")
11 . "${CTDB_BASE}/functions"
17 [ -n "$CTDB_NATGW_NODES" ] || exit 0
18 export CTDB_NATGW_NODES
20 ctdb_setup_state_dir "failover" "$service_name"
22 # script_state_dir set by ctdb_setup_state_dir()
23 # shellcheck disable=SC2154
24 natgw_cfg_new="${script_state_dir}/cfg_new"
25 natgw_cfg_old="${script_state_dir}/cfg_old"
26 natgw_master_old="${script_state_dir}/master_old"
28 ctdb_natgw_slave_only ()
30 _ip_address=$(ctdb_get_ip_address)
32 awk -v my_ip="$_ip_address" \
33 '$1 == my_ip { if ($2 ~ "slave-only") { exit 0 } else { exit 1 } }' \
39 [ -r "$CTDB_NATGW_NODES" ] || \
40 die "error: CTDB_NATGW_NODES=${CTDB_NATGW_NODES} unreadable"
41 if ! ctdb_natgw_slave_only ; then
42 [ -n "$CTDB_NATGW_PUBLIC_IP" ] || \
43 die "Invalid configuration: CTDB_NATGW_PUBLIC_IP not set"
44 [ -n "$CTDB_NATGW_PUBLIC_IFACE" ] || \
45 die "Invalid configuration: CTDB_NATGW_PUBLIC_IFACE not set"
47 [ -n "$CTDB_NATGW_PRIVATE_NETWORK" ] || \
48 die "Invalid configuration: CTDB_NATGW_PRIVATE_NETWORK not set"
50 # The default is to create a single default route
51 [ -n "$CTDB_NATGW_STATIC_ROUTES" ] || CTDB_NATGW_STATIC_ROUTES="0.0.0.0/0"
59 CTDB_NATGW_NODES="$CTDB_NATGW_NODES"
60 CTDB_NATGW_PUBLIC_IP="$CTDB_NATGW_PUBLIC_IP"
61 CTDB_NATGW_PUBLIC_IFACE="$CTDB_NATGW_PUBLIC_IFACE"
62 CTDB_NATGW_DEFAULT_GATEWAY="$CTDB_NATGW_DEFAULT_GATEWAY"
63 CTDB_NATGW_PRIVATE_NETWORK="$CTDB_NATGW_PRIVATE_NETWORK"
64 CTDB_NATGW_STATIC_ROUTES="$CTDB_NATGW_STATIC_ROUTES"
68 natgw_config_has_changed ()
70 natgw_write_config "$natgw_cfg_new"
72 # Non-existent old returns true, no log message
73 if [ ! -f "$natgw_cfg_old" ] ; then
78 if cmp "$natgw_cfg_old" "$natgw_cfg_new" >/dev/null 2>&1 ; then
82 echo "NAT gateway configuration has changed"
88 _ip="${CTDB_NATGW_PUBLIC_IP%/*}"
89 _maskbits="${CTDB_NATGW_PUBLIC_IP#*/}"
91 delete_ip_from_iface \
92 "$CTDB_NATGW_PUBLIC_IFACE" "$_ip" "$_maskbits" >/dev/null 2>&1
93 for _net_gw in $CTDB_NATGW_STATIC_ROUTES ; do
95 ip route del "$_net" metric 10 >/dev/null 2>/dev/null
98 # Delete the masquerading setup from a previous iteration where we
100 iptables -D POSTROUTING -t nat \
101 -s "$CTDB_NATGW_PRIVATE_NETWORK" ! -d "$CTDB_NATGW_PRIVATE_NETWORK" \
102 -j MASQUERADE >/dev/null 2>/dev/null
104 iptables -D INPUT -p tcp --syn -d "${_ip}/32" -j REJECT 2>/dev/null
109 if [ -r "$natgw_cfg_old" ] ; then
110 (. "$natgw_cfg_old" ; _natgw_clear)
118 set_proc sys/net/ipv4/ip_forward 1
119 iptables -A POSTROUTING -t nat \
120 -s "$CTDB_NATGW_PRIVATE_NETWORK" ! -d "$CTDB_NATGW_PRIVATE_NETWORK" \
123 # block all incoming connections to the NATGW IP address
124 ctdb_natgw_public_ip_host="${CTDB_NATGW_PUBLIC_IP%/*}/32"
125 iptables -D INPUT -p tcp --syn \
126 -d "$ctdb_natgw_public_ip_host" -j REJECT 2>/dev/null
127 iptables -I INPUT -p tcp --syn \
128 -d "$ctdb_natgw_public_ip_host" -j REJECT 2>/dev/null
130 ip addr add "$CTDB_NATGW_PUBLIC_IP" dev "$CTDB_NATGW_PUBLIC_IFACE"
131 for _net_gw in $CTDB_NATGW_STATIC_ROUTES ; do
133 if [ "$_net" != "$_net_gw" ] ; then
136 _gw="$CTDB_NATGW_DEFAULT_GATEWAY"
139 [ -n "$_gw" ] || continue
140 ip route add "$_net" metric 10 via "$_gw"
148 for _net_gw in $CTDB_NATGW_STATIC_ROUTES ; do
150 ip route add "$_net" via "$_natgwip" metric 10
154 natgw_ensure_master ()
156 # Intentional word splitting here
157 # shellcheck disable=SC2046
158 set -- $("${CTDB_HELPER_BINDIR}/ctdb_natgw" master)
159 natgwmaster="${1:--1}" # Default is -1, for failure above
162 if [ "$natgwmaster" = "-1" ]; then
164 die "There is no NATGW master node"
168 natgw_master_has_changed ()
170 if [ -r "$natgw_master_old" ] ; then
171 read _old_natgwmaster <"$natgw_master_old"
175 [ "$_old_natgwmaster" != "$natgwmaster" ]
180 echo "$natgwmaster" >"$natgw_master_old"
181 # Created by natgw_config_has_changed()
182 mv "$natgw_cfg_new" "$natgw_cfg_old"
194 # Error if CTDB_NATGW_PUBLIC_IP is listed in public addresses
195 ip_pat=$(echo "$CTDB_NATGW_PUBLIC_IP" | sed -e 's@\.@\\.@g')
196 ctdb_public_addresses="${CTDB_BASE}/public_addresses"
197 if grep -q "^${ip_pat}[[:space:]]" "$ctdb_public_addresses" ; then
198 die "ERROR: CTDB_NATGW_PUBLIC_IP same as a public address"
201 # do not send out arp requests from loopback addresses
202 set_proc sys/net/ipv4/conf/all/arp_announce 2
205 updatenatgw|ipreallocated)
210 natgw_config_has_changed || natgw_master_has_changed || exit 0
215 if [ "$pnn" = "$natgwmaster" ]; then
218 natgw_set_slave "$natgwip"
221 # flush our route cache
222 set_proc sys/net/ipv4/route/flush 1
224 # Only update saved state when NATGW successfully updated
228 shutdown|removenatgw)
236 if [ -n "$CTDB_NATGW_PUBLIC_IFACE" ] ; then
237 interface_monitor "$CTDB_NATGW_PUBLIC_IFACE" || exit 1