Project

General

Profile

High Availability » History » Version 4

Martin Willi, 07.04.2010 14:38

1 1 Martin Willi
h1. High Availability
2 1 Martin Willi
3 3 Martin Willi
{{>toc}}
4 3 Martin Willi
5 2 Andreas Steffen
Starting with the upcoming 4.4.0 release, the IKEv2 daemon will experimentally support pseudo active/active High Availability and Load Sharing capabilities using a cluster of [initially] two nodes.
6 1 Martin Willi
7 4 Martin Willi
The source code has been merged into the master branch and will be included in the 4.4.0 release.
8 3 Martin Willi
9 3 Martin Willi
> *The development of the High Availability functionality has been sponsored by "secunet":http://www.secunet.com.*
10 1 Martin Willi
11 1 Martin Willi
h2. Problem statement
12 1 Martin Willi
13 1 Martin Willi
The IKEv2/IPsec protocol is not well suited for operation in an active/active cluster. While it is possible to share the state of IKE_SAs over high-speed links in a cluster, sharing the kernel-maintained IPsec ESP SAs is very difficult. Due to the strict sequence numbering of ESP packets, the overhead for synchronizing ESP sequence numbers would be very high.
14 1 Martin Willi
15 4 Martin Willi
The IETF ipsecme working group "currently discusses":http://www.ietf.org/id/draft-ietf-ipsecme-ipsec-ha-00.txt the problems in more details and will probably standardize a solution which involves the client to work around the problems. This will, however, require an extension to the IKEv2 protocol. Clients connecting to a highly available cluster will benefit from this features only if they support this extension, existing clients (such as the one shipped with Windows 7) will not be able to take advantage of this efforts.
16 1 Martin Willi
17 1 Martin Willi
h2. Possible approaches
18 1 Martin Willi
19 2 Andreas Steffen
h3. Node-to-node synchronization
20 1 Martin Willi
21 2 Andreas Steffen
While the synchronization of IKE state including sequence numbers is realistic between two nodes, exchanging state information of an ESP security association is difficult.
22 1 Martin Willi
23 2 Andreas Steffen
Synchronizing the state for each processed IPsec packet will put a high load on the nodes. Synchronization after a certain amount of packets and/or after a certain timeout can reduce the load, but will make fail-over handling much more difficult, as we have to guess on the taking-over node how many packets the failing node has processed, but could not synchronize before it failed.
24 1 Martin Willi
25 1 Martin Willi
Another problem with such an approach is that there is no way of doing load sharing between nodes. An SA is strictly bound to a single node until the event of a failure.
26 1 Martin Willi
27 2 Andreas Steffen
h3. Client-to-cluster synchronization
28 1 Martin Willi
29 2 Andreas Steffen
Another approach to consider is requesting state information from the client. In the event of a failure, the taking-over node can request sequence numbers from the client. But this approach has the same deficiencies as previously discussed. Further, it requires extensions to the IKE protocol between client and gateway, making existing implementations incompatible with this approach.
30 1 Martin Willi
31 1 Martin Willi
h2. Functional specification
32 1 Martin Willi
33 1 Martin Willi
strongSwan uses a slightly different approach. Our solution should provide:
34 1 Martin Willi
* Failure detection: If a node fails due to power loss, hardware failures, kernel oops or daemon crashes, the node will be removed from the cluster.
35 1 Martin Willi
* State synchronization: If a node is removed due to failure or administrative purposes, the cluster should already have an up-to-date copy of the nodes state to take over.
36 1 Martin Willi
* Takeover: Node failure detection and state takeover should happen within 1-3 seconds.
37 1 Martin Willi
* Transparent migration: TCP or application sessions should not be interrupted during take over.
38 1 Martin Willi
* Load sharing: Load should be shared across all actives nodes in a cluster.
39 4 Martin Willi
* Reintgration: A repaired node can be (re-)added to an existing cluster, taking over a part of the load.
40 2 Andreas Steffen
* Legacy clients: No protocol extension, any IKEv2 client should be able to benefit from High Availability if connected to a cluster.
41 1 Martin Willi
42 1 Martin Willi
Migration of clients to another node does not affect the connection, a client does usually not detect a takeover. This allows a gateway administrator to e.g. remove a node from the load sharing cluster, apply security updates, reboot and reintegrate the node. 
43 1 Martin Willi
44 1 Martin Willi
h2. Selected solution
45 1 Martin Willi
46 1 Martin Willi
The selected solution is based on the idea of "ClusterIP":http://lwn.net/Articles/108078, a Linux kernel module allowing a set of nodes to provide a service under a single virtual IP.
47 1 Martin Willi
48 1 Martin Willi
h3. How ClusterIP works
49 1 Martin Willi
50 2 Andreas Steffen
All nodes in a ClusterIP-based setup act under a single virtual IP address. The nodes spoof ARP requests with a multicast MAC address. This will make the switch forwarding the packet to each node in the cluster.
51 1 Martin Willi
52 1 Martin Willi
The received packet is associated to a segment by calculating a hash value of it. In the simplest setup, the source address is hashed and the hash value modulo the number of segments results in the responsible segment number. Each segment is handled by exactly one node in the cluster.
53 1 Martin Willi
54 1 Martin Willi
The node responsible for the packet will pass it to upper layers, where all others just drop the packet in the netfilter code. Depending on the hash value, e.g. TCP connections are kept on the same node. If a node fails, a remaining node will take over the segment and process packets for it.
55 1 Martin Willi
56 1 Martin Willi
h3. IPsec with ClusterIP
57 1 Martin Willi
58 1 Martin Willi
While the ClusterIP module itself is not designed to handle IPsec traffic or even act as a forwarding router, the principle of ClusterIP is. If the IKE daemons in the cluster can synchronize the IKE state and the basic IPsec SA state without sequence numbers, a modified ClusterIP module can do the rest:
59 1 Martin Willi
60 1 Martin Willi
For traffic to decrypt, the SPI value of the ESP packet can be included in the hash calculation, resulting in a spread of the packet flow across all nodes. As each node processes a packet of an SA from time to time, sequence numbers are automatically incremented if a packet is processed. Sequence numbers are not mangled if a packet is not verified using the IPsec authentication algorithm, as an attacker would be able to manipulate the SA state otherwise. Paket flows are partitioned in a dozen of packets to avoid too much packet reordering.
61 1 Martin Willi
62 2 Andreas Steffen
For traffic to encrypt on the cluster, the SA is looked up and the hash value is fed with the SPI of the found SA. If the segment matches, the packet is further processed. If not, only the sequence number is incremented. To avoid assigning the same sequence number to different packets on multiple nodes, additional logic is required.
63 1 Martin Willi
64 1 Martin Willi
h2. Kernel Implementation
65 1 Martin Willi
66 1 Martin Willi
The ClusterIP Netfilter module uses an additional PREROUTING hook to mark received packets for forwarding. Two new Netfilter hooks are included in the IPsec processing, exactly before the decryption/encryption process (XFRM_IN/XFRM_OUT).
67 1 Martin Willi
68 1 Martin Willi
<pre>
69 1 Martin Willi
                 v        PLAIN        ^
70 1 Martin Willi
    +------------------------------------------------+
71 1 Martin Willi
    |            |                     |             |
72 1 Martin Willi
    |     +--------------+      +--------------+     |
73 1 Martin Willi
    |  4. |  PREROUTING  |      |   DECRYPT    |  3. |
74 1 Martin Willi
    |     +--------------+      +--------------+     |
75 1 Martin Willi
    |            |                     ^             |
76 1 Martin Willi
    |            v                     |             |
77 1 Martin Willi
    |     +--------------+      +--------------+     |
78 1 Martin Willi
    |  5. |   XFRM_OUT   |      |   XFRM_IN    |  2. |
79 1 Martin Willi
    |     +--------------+      +--------------+     |
80 1 Martin Willi
    |            |                     ^             |
81 1 Martin Willi
    |            v           ^         | ESP/AH      |
82 1 Martin Willi
    |     +--------------+   |  +--------------+     |
83 1 Martin Willi
    |  6. |   ENCRYPT    |   +--|    INPUT     |  1. |
84 1 Martin Willi
    |     +--------------+      +--------------+     |
85 1 Martin Willi
    |            |                     |             |
86 1 Martin Willi
    +------------------------------------------------+
87 1 Martin Willi
                 v       CRYPTED       ^
88 1 Martin Willi
</pre>
89 1 Martin Willi
90 1 Martin Willi
#  AH, ESP and UDP-Encapsulated ESP packets are all accepted. Other traffic is subject to the ClusterIP selection algorithm based on the source IP address (e.g. IKE traffic).
91 1 Martin Willi
# Undecrypted IPsec traffic gets dropped using a ClusterIP algorithm, based on the IPsec SA.
92 1 Martin Willi
# Decryption process is done on the responsible node only.
93 1 Martin Willi
# Traffic is received on ClusterIP multicast MAC and must be tagged as unicast traffic to advance through IP forwarding.
94 1 Martin Willi
# After IPsec policy lookup, unencrypted traffic gets dropped using a ClusterIP algorithm, based on IPsec SA. Outgoing sequence numbers are assigned before the packed drop, this will keep outgoing sequence numbers in sync on all nodes.
95 1 Martin Willi
# Encryption process is done on the responsible node only.
96 1 Martin Willi
97 4 Martin Willi
Patches are available for the "XFRM input/output hooks":http://wiki.strongswan.org/attachments/111/0001-Netfilter-hooks-before-XFRM-input-and-output-process.patch and to the "ClusterIP module":http://wiki.strongswan.org/attachments/112/0002-Extended-the-CLUSTERIP-module-to-use-it-on-a-IPSec-g.patch that allows ClusterIP to work with IPsec.
98 4 Martin Willi
The patches currently break the Netfilter ABI, iptables needs "a patch":http://wiki.strongswan.org/attachments/113/0001-Added-XFRM-hooks-to-iptables-headers.patch to work on top of a patched kernel.
99 4 Martin Willi
100 1 Martin Willi
h2. IKE daemon implementation
101 1 Martin Willi
102 1 Martin Willi
A separate high availability plugin implemented for the IKEv2 daemon charon is responsible for state synchronization between the nodes in a cluster and simple monitoring functionality. It is currently designed for two nodes, but will be extended to synchronize larger clusters in the future.
103 4 Martin Willi
104 4 Martin Willi
To enable the high availability plugin, build strongSwan with --enable-ha.
105 1 Martin Willi
106 1 Martin Willi
h3. Daemon hooks
107 1 Martin Willi
108 1 Martin Willi
The plugin registers itself at several hooks in the daemon. These hooks are used for notifications about SA state changes and push information to the plugin. The following hooks are used:
109 1 Martin Willi
* ike_keys(): receives IKE key material (DH, nonces, proposals)
110 1 Martin Willi
* ike_updown()/ike_rekey(): monitor state changes of IKE SAs
111 1 Martin Willi
* message(): used to update IKE message IDs
112 1 Martin Willi
* child_keys(): receives CHILD key material
113 1 Martin Willi
* child_state_change(): monitor state changes of CHILD SAs
114 1 Martin Willi
115 1 Martin Willi
The plugin registers its hook functions at the daemon bus. These hooks are sufficient to synchronize all IKE- and CHILD SAs with all the state required to do a fail-over of IKE and ESP SAs.
116 1 Martin Willi
117 1 Martin Willi
h3. Synchronization messages
118 1 Martin Willi
119 1 Martin Willi
The hook functions collect the required synchronization data and prepare messages to be sent to other nodes in the cluster. Messages are sent in unencrypted UDP datagrams, sent and received on port 4510. As these messages contain sensitive key material, securing the messages by IPsec is recommended.
120 1 Martin Willi
121 1 Martin Willi
No packet acknowledge/retransmit scheme is currently implemented, the cluster needs a reliable network with very few packet losses. It might be necessary to use a more reliable transport protocol in the future, especially if nodes start to drop packets due to an overloaded CPU.
122 1 Martin Willi
123 1 Martin Willi
Messages contain a protocol version, a message type and different attributes. The following synchronization message types are currently defined:
124 1 Martin Willi
* IKE_ADD: A new IKE_SA has been established. This message contains all information to derive key material. If the message contains a REKEY attribute, the IKE_SA inherits all required parameters from the old SA.
125 1 Martin Willi
* IKE_UPDATE: Update IKE_SA with newer information (e.g. Identities when authentication is complete).
126 1 Martin Willi
* IKE_DELETE: Delete an established IKE_SA.
127 1 Martin Willi
* CHILD_ADD: CHILD_SA has been established, contains keying material.
128 1 Martin Willi
* CHILD_DELETE: CHILD_SA has been deleted.
129 1 Martin Willi
130 1 Martin Willi
h3. State synchronization
131 1 Martin Willi
132 1 Martin Willi
Received synchronization messages are parsed, mirrored IKE and CHILD_SAs are created from this information. Mirrored CHILD_SAs do not differ from normally exchanged ones; they are installed in the kernel and handle packets if ClusterIP feels responsible for it.
133 1 Martin Willi
134 1 Martin Willi
IKE_SAs are installed in a special PASSIVE state. They do not handle traffic, but accept state changes from sync messages only. PASSIVE IKE_SAs are managed in the IKE_SA manager as any other SA and are accessible through e.g. "ipsec statusall".
135 1 Martin Willi
136 1 Martin Willi
Key derivation is repeated on mirrored SAs the same way as it is done on the real SAs. This allows the reuse of existing installation routines and the HA plugin to be very unobtrusive. A node responsible for an IKE_SA does not keep the keying material in memory, it just pushes the exchanged secret to other nodes and forgets the secrets afterwards.
137 1 Martin Willi
138 1 Martin Willi
h3. Control messages
139 1 Martin Willi
140 1 Martin Willi
In addition to the synchronization messages, the HA plugin uses control messages to notify about segment changes and optionally messages for simple monitoring functions:
141 1 Martin Willi
* SEGMENT_DROP: List of segments the sending node is dropping responsibility.
142 1 Martin Willi
* SEGMENT_TAKE: List of segments the sending node is taking responsibility.
143 1 Martin Willi
* STATUS: Heartbeat message containing a list of segments the sending node is responsible.
144 1 Martin Willi
* RESYNC: Request for resynchronization of a list of segments.
145 1 Martin Willi
146 1 Martin Willi
The take/drop messages are sent to notify other nodes about changes done by the daemon automatically or the administrator manually. The receiving node will automatically do the opposite action to handle all segment exactly once.
147 1 Martin Willi
148 1 Martin Willi
If heartbeat monitoring is enabled, the status message is periodically sent. This allows to detect the activity of the remote node and take over segments the remote node is not serving. It also implements node failure detection for simple errors.
149 1 Martin Willi
150 1 Martin Willi
If a replacement of a failing node is installed, reintegration of the node can be speed up by sending the resynchronization message. The active node
151 1 Martin Willi
will start resyncing all SAs, allowing the administrator to rebalance the load distribution in the cluster afterwards.
152 1 Martin Willi
153 1 Martin Willi
h3. Failover
154 1 Martin Willi
155 1 Martin Willi
In the failover case, responsibility for complete ClusterIP segments are moved from one node to another. Responsibility for a segment can be enabled or disabled on each node. For this purpose, the plugin uses the same hashing algorithm to calculate responsibility based on the source IP address.
156 1 Martin Willi
157 1 Martin Willi
If a segment is activated, the plugin searches for IKE_SAs in this segment and sets the state of all PASSIVE IKE_SAs to ESTABLISHED. No further action is required: The daemon handles the IKE_SA as every other one and sends out synchronization messages for state changes.
158 1 Martin Willi
159 1 Martin Willi
On segment deactivation, the plugin searches for IKE_SAs in the ESTABLISHED state in this segments and sets the state to PASSIVE.
160 1 Martin Willi
161 1 Martin Willi
CHILD_SAs are completely unaffected from activation and deactivation: They are always active and handle traffic assigned by ClusterIP.
162 1 Martin Willi
163 1 Martin Willi
h3. Reintegration
164 1 Martin Willi
165 1 Martin Willi
To reintegrate a failed node into a cluster, the node needs state information from scratch. If all the required state has been synced, the reintegrated node can be used as failover node again. Segments can be activated on the reintegrated node only after all required state has been exchanged.
166 1 Martin Willi
167 1 Martin Willi
SA state automatically gets synchronized during rekeying. Each rekeying procedure provides fresh keying material which can be used to build the
168 1 Martin Willi
mirrored IKE and CHILD_SA state. Rekeying is currently the only way to push the required state to a reintegrated node, as the key material is not stored directly on an active node.
169 1 Martin Willi
170 1 Martin Willi
To speed up the reintegration process, the plugin can trigger the rekeying of existing IKE- and CHILD_SAs in a segment, allowing a reintegration process to complete within seconds.
171 1 Martin Willi
172 1 Martin Willi
173 1 Martin Willi
h2. Configuration
174 1 Martin Willi
175 1 Martin Willi
Configuration is done in two places. The necessary virtual IPs and the ClusterIP rules are installed manually. This is explicitly not done by the daemon, as the rules must stay active after daemon shutdown or error conditions.
176 1 Martin Willi
177 1 Martin Willi
The HA plugin requires a configuration matching to the installed ClusterIP rules. All nodes in the cluster need an identical connection configuration and credentials; IP addresses assigned to clients using configuration payloads must be set carefully using a central or two distinct address pools.
178 1 Martin Willi
179 1 Martin Willi
180 1 Martin Willi
h3. ClusterIP
181 1 Martin Willi
182 1 Martin Willi
The configuration of the extended ClusterIP module is similar to a default ClusterIP setup. For a traffic forwarding IPsec gateway, a cluster usually
183 1 Martin Willi
needs an internal virtual IP/MAC and an external virtual IP/MAC on each node.
184 1 Martin Willi
185 1 Martin Willi
<pre>
186 1 Martin Willi
ip address add 192.168.0.200/24 dev eth0
187 1 Martin Willi
iptables -A INPUT -i eth0 -d 192.168.0.200 -j CLUSTERIP --new \
188 1 Martin Willi
   --hashmode sourceip --clustermac 01:00:5e:00:00:20 \
189 1 Martin Willi
   --total-nodes 2 --local-node 1
190 1 Martin Willi
</pre>
191 1 Martin Willi
192 1 Martin Willi
This example installs the virtual IP 192.168.0.200 on interface eth0 and adds a corresponding ClusterIP rule. ClusterIP rules are always added to the INPUT chain. To get the same result for segment responsibility calculation in the kernel and the HA plugin, the sourceip hashmode and a hash init value of 0 must be used (default).
193 1 Martin Willi
194 1 Martin Willi
The _total-nodes_ option must match the configuration of the HA plugin, and all nodes require the same virtual IP/MAC and ClusterIP configuration.
195 1 Martin Willi
196 1 Martin Willi
ClusterIP requires the _local-node_ option to be present. However, the HA plugin reassigns segment responsibility during daemon startup.
197 1 Martin Willi
198 1 Martin Willi
h3. HA plugin
199 1 Martin Willi
200 1 Martin Willi
The HA plugin configuration is handled in the _strongswan.conf_ file.
201 1 Martin Willi
202 1 Martin Willi
<pre>
203 1 Martin Willi
charon {
204 1 Martin Willi
    # ...
205 1 Martin Willi
    ha {
206 1 Martin Willi
        local = 10.0.0.2
207 1 Martin Willi
        remote = 10.0.0.1
208 1 Martin Willi
        segment_count = 2
209 1 Martin Willi
        # secret = s!ronG-P5K-s3cret
210 1 Martin Willi
        fifo_interface = yes
211 1 Martin Willi
        monitor = yes
212 1 Martin Willi
        resync = yes
213 1 Martin Willi
    }
214 1 Martin Willi
}
215 1 Martin Willi
</pre>
216 1 Martin Willi
217 1 Martin Willi
The _local_ and _remote_ addresses are used to send and receive sync messages, _segment_count_ defines the number of segments to use.
218 1 Martin Willi
219 1 Martin Willi
If a _secret_ option is specified, the nodes automatically establish a pre-shared key authenticated IPsec tunnel for HA sync and control messages
220 1 Martin Willi
(experimental).
221 1 Martin Willi
222 1 Martin Willi
The segment responsibility administration interface is enabled with the _fifo_interface_ option. The _monitor_ parameter enables the heartbeat based remote node monitoring, the _resync_ option enables automatic state resynchronization if a node joins the cluster.
223 1 Martin Willi
224 1 Martin Willi
h3. Administrating segment responsibility
225 1 Martin Willi
226 1 Martin Willi
Changing the segment responsibility is done for the daemon, where it will propagate the changes in segment responsibility to the kernel.
227 1 Martin Willi
228 1 Martin Willi
The HA plugin uses a very similar interface for segment control as ClusterIP. Instead of a proc entry, it uses a FIFO located at _/var/run/charon.ha_ .
229 1 Martin Willi
Echoing +1/-1 will activate/deactivate responsibility for segment 1, while an additional command *3 will enforce a resynchronization by triggering a rekey of all SAs in segment 3.