File: //usr/share/doc/conntrack-tools/doc/misc/clusterip.sh
#!/bin/sh
#
# (C) 2009-2011 by Pablo Neira Ayuso <pneira@us.es>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
#
# Here, you can find the variables that you have to change.
#
# enable this for debugging
LOG_DEBUG=0
# number of cluster node (must be unique, from 1 to N cluster nodes)
NODE=1
# this is the real MAC address of eth1
REAL_HWADDR1=00:18:71:68:f2:34
# this is the real MAC address of eth2
REAL_HWADDR2=00:11:0a:60:e7:32
#
# These variables MUST have the same values in both cluster nodes
#
# number of nodes that belong this cluster
TOTAL_NODES=2
# this is the cluster multicast MAC address of eth1
MC_HWADDR1=01:00:5e:00:01:01
# this is the cluster multicast MAC address of eth2
MC_HWADDR2=01:00:5e:00:01:02
# cluster IP address of eth1
ADDR1=192.168.0.5/24
# cluster IP address of eth2
ADDR2=192.168.1.5/24
# random seed for hashing
SEED=0xdeadbeef
start_cluster_address()
{
# set cluster IP addresses
ip a a $ADDR1 dev eth1
ip a a $ADDR2 dev eth2
# set cluster multicast MAC addresses
ip maddr add $MC_HWADDR1 dev eth1
ip maddr add $MC_HWADDR2 dev eth2
# mangle ARP replies to include the cluster multicast MAC addresses
arptables -I OUTPUT -o eth1 --h-length 6 \
-j mangle --mangle-mac-s $MC_HWADDR1
# mangle ARP request to use the original MAC address (otherwise the
# stack drops this packet).
arptables -I INPUT -i eth1 --h-length 6 --destination-mac \
$MC_HWADDR1 -j mangle --mangle-mac-d $REAL_HWADDR1
arptables -I OUTPUT -o eth2 --h-length 6 \
-j mangle --mangle-mac-s $MC_HWADDR2
arptables -I INPUT -i eth2 --h-length 6 --destination-mac \
$MC_HWADDR2 -j mangle --mangle-mac-d $REAL_HWADDR2
}
stop_cluster_address()
{
# delete cluster IP addresses
ip a d $ADDR1 dev eth1
ip a d $ADDR2 dev eth2
# delete cluster multicast MAC addresses
ip maddr del $MC_HWADDR1 dev eth1
ip maddr del $MC_HWADDR2 dev eth2
# delete ARP replies mangling
arptables -D OUTPUT -o eth1 --h-length 6 \
-j mangle --mangle-mac-s $MC_HWADDR1
# delete ARP requests mangling
arptables -D INPUT -i eth1 --h-length 6 --destination-mac \
$MC_HWADDR1 -j mangle --mangle-mac-d $REAL_HWADDR1
arptables -D OUTPUT -o eth2 --h-length 6 \
-j mangle --mangle-mac-s $MC_HWADDR2
arptables -D INPUT -i eth2 --h-length 6 --destination-mac \
$MC_HWADDR2 -j mangle --mangle-mac-d $REAL_HWADDR2
}
start_nat()
{
iptables -A POSTROUTING -t nat -s 192.168.0.11 \
-j SNAT --to-source 192.168.1.5
iptables -A POSTROUTING -t nat -s 192.168.0.2 \
-j SNAT --to-source 192.168.1.5
}
stop_nat()
{
iptables -D POSTROUTING -t nat -s 192.168.0.11 \
-j SNAT --to-source 192.168.1.5
iptables -D POSTROUTING -t nat -s 192.168.0.2 \
-j SNAT --to-source 192.168.1.5
}
iptables_start_cluster_rules()
{
# mark packets that belong to this node (go direction)
iptables -A CLUSTER-RULES -t mangle -i eth1 -m cluster \
--cluster-total-nodes $TOTAL_NODES --cluster-local-node $1 \
--cluster-hash-seed $SEED -j MARK --set-mark 0xffff
# mark packet that belong to this node (reply direction)
# note: we *do* need this to change the packet type to PACKET_HOST,
# otherwise the stack silently drops the packet.
iptables -A CLUSTER-RULES -t mangle -i eth2 -m cluster \
--cluster-total-nodes $TOTAL_NODES --cluster-local-node $1 \
--cluster-hash-seed $SEED -j MARK --set-mark 0xffff
}
iptables_stop_cluster_rules()
{
iptables -D CLUSTER-RULES -t mangle -i eth1 -m cluster \
--cluster-total-nodes $TOTAL_NODES --cluster-local-node $1 \
--cluster-hash-seed $SEED -j MARK --set-mark 0xffff
iptables -D CLUSTER-RULES -t mangle -i eth2 -m cluster \
--cluster-total-nodes $TOTAL_NODES --cluster-local-node $1 \
--cluster-hash-seed $SEED -j MARK --set-mark 0xffff
}
start_cluster_ruleset() {
iptables -N CLUSTER-RULES -t mangle
iptables_start_cluster_rules $NODE
iptables -A PREROUTING -t mangle -j CLUSTER-RULES
if [ $LOG_DEBUG -eq 1 ]
then
iptables -A PREROUTING -t mangle -i eth1 -m mark \
--mark 0xffff -j LOG --log-prefix "cluster-accept: "
iptables -A PREROUTING -t mangle -i eth1 -m mark \
! --mark 0xffff -j LOG --log-prefix "cluster-drop: "
iptables -A PREROUTING -t mangle -i eth2 -m mark \
--mark 0xffff \
-j LOG --log-prefix "cluster-reply-accept: "
iptables -A PREROUTING -t mangle -i eth2 -m mark \
! --mark 0xffff \
-j LOG --log-prefix "cluster-reply-drop: "
fi
# drop packets that don't belong to us (go direction)
iptables -A PREROUTING -t mangle -i eth1 -m mark \
! --mark 0xffff -j DROP
# drop packets that don't belong to us (reply direction)
iptables -A PREROUTING -t mangle -i eth2 -m mark \
! --mark 0xffff -j DROP
}
stop_cluster_ruleset() {
iptables -D PREROUTING -t mangle -j CLUSTER-RULES
if [ $LOG_DEBUG -eq 1 ]
then
iptables -D PREROUTING -t mangle -i eth1 -m mark \
--mark 0xffff -j LOG --log-prefix "cluster-accept: "
iptables -D PREROUTING -t mangle -i eth1 -m mark \
! --mark 0xffff -j LOG --log-prefix "cluster-drop: "
iptables -D PREROUTING -t mangle -i eth2 -m mark \
--mark 0xffff \
-j LOG --log-prefix "cluster-reply-accept: "
iptables -D PREROUTING -t mangle -i eth2 -m mark \
! --mark 0xffff \
-j LOG --log-prefix "cluster-reply-drop: "
fi
iptables -D PREROUTING -t mangle -i eth1 -m mark \
! --mark 0xffff -j DROP
iptables -D PREROUTING -t mangle -i eth2 -m mark \
! --mark 0xffff -j DROP
iptables_stop_cluster_rules $NODE
iptables -F CLUSTER-RULES -t mangle
iptables -X CLUSTER-RULES -t mangle
}
case "$1" in
start)
echo "starting cluster configuration for node $NODE."
# just in case that you forget it
echo 1 > /proc/sys/net/ipv4/ip_forward
# disable TCP pickup
echo 0 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal
echo 0 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_loose
start_cluster_address
start_nat
# drop invalid flows from eth2 (not allowed). This is mandatory
# because traffic which does not belong to this node is always
# labeled as INVALID by TCP and ICMP state tracking. For protocols like
# UDP, you will have to drop NEW traffic from eth2, otherwise reply
# traffic may be accepted by both nodes, thus duplicating the traffic.
iptables -A PREROUTING -t mangle -i eth2 \
-m state --state INVALID -j DROP
start_cluster_ruleset
;;
stop)
echo "stopping cluster configuration for node $NODE."
stop_cluster_address
stop_nat
iptables -D PREROUTING -t mangle -i eth2 \
-m state --state INVALID -j DROP
stop_cluster_ruleset
;;
primary)
logger "cluster-match-script: entering MASTER state for node $2"
if [ -x $CONNTRACKD_SCRIPT ]
then
sh $CONNTRACKD_SCRIPT primary $NODE $2
fi
iptables_start_cluster_rules $2
;;
backup)
logger "cluster-match-script: entering BACKUP state for node $2"
if [ -x $CONNTRACKD_SCRIPT ]
then
sh $CONNTRACKD_SCRIPT backup $NODE $2
fi
iptables_stop_cluster_rules $2
;;
fault)
logger "cluster-match-script: entering FAULT state for node $2"
if [ -x $CONNTRACKD_SCRIPT ]
then
sh $CONNTRACKD_SCRIPT fault $NODE $2
fi
iptables_stop_cluster_rules $2
;;
*)
echo "$0 start|stop|add|del [nodeid]"
;;
esac