Project

General

Profile

Load Tests » History » Version 21

Tobias Brunner, 01.03.2014 17:11

1 7 Martin Willi
h1. Load Tests
2 7 Martin Willi
3 16 Martin Willi
{{>toc}}
4 7 Martin Willi
5 6 Martin Willi
To do stability testing and performance optimizations, charon provides a load-tester plugin. This plugin allows to set up thousands of tunnels concurrently against the daemon itself or a remote host.
6 1 Martin Willi
7 1 Martin Willi
8 7 Martin Willi
h2. Setup
9 7 Martin Willi
10 1 Martin Willi
To build and enable the plugin, add
11 7 Martin Willi
<pre>
12 9 Martin Willi
--enable-load-tester
13 1 Martin Willi
</pre>
14 8 Tobias Brunner
to your _./configure_ options.
15 8 Tobias Brunner
16 8 Tobias Brunner
17 7 Martin Willi
----
18 8 Tobias Brunner
19 1 Martin Willi
*Warning: Never enable the load-testing plugin on productive systems. It provides preconfigured credentials and allows an attacker to authenticate as any user.*
20 8 Tobias Brunner
21 7 Martin Willi
----
22 8 Tobias Brunner
23 7 Martin Willi
To make sure you are aware of this risk, an additional _enable_ switch in _strongswan.conf_ is required to load the plugin.
24 6 Martin Willi
25 18 Tobias Brunner
h2. Configuration
26 18 Tobias Brunner
27 18 Tobias Brunner
The plugin is configured using the following [[strongswan.conf]] options:
28 18 Tobias Brunner
29 1 Martin Willi
|_<.Key                                             |_<.Default|_<.Description|
30 21 Tobias Brunner
|charon.plugins.load-tester.addrs                   |          |Subsection that contains key/value pairs with address pools (in CIDR notation) to use for a specific network interface e.g. eth0 = 10.10.0.0/16.|
31 21 Tobias Brunner
|charon.plugins.load-tester.addrs_keep              |no        |Whether to keep dynamic addresses installed even after the associated SA got terminated.|
32 21 Tobias Brunner
|charon.plugins.load-tester.addrs_prefix            |16        |Network prefix length to use when installing dynamic addresses. If set to -1 the full address is used (i.e. 32 or 128).|
33 21 Tobias Brunner
|charon.plugins.load-tester.ca_dir                  |          |Directory to load (intermediate) CA certificates from.|
34 21 Tobias Brunner
|charon.plugins.load-tester.child_rekey             |600       |Seconds to start CHILD_SA rekeying after setup.|
35 21 Tobias Brunner
|charon.plugins.load-tester.delay                   |0         |Delay between initiatons for each thread.|
36 21 Tobias Brunner
|charon.plugins.load-tester.delete_after_established|no        |Delete an IKE_SA as soon as it has been established.|
37 21 Tobias Brunner
|charon.plugins.load-tester.digest                  |sha1      |Digest algorithm used when issuing certificates.|
38 21 Tobias Brunner
|charon.plugins.load-tester.dpd_delay               |0         |DPD delay to use in load test.|
39 21 Tobias Brunner
|charon.plugins.load-tester.dynamic_port            |0         |Base port to be used for requests (each client uses a different port).|
40 21 Tobias Brunner
|charon.plugins.load-tester.eap_password            |default-pwd|EAP secret to use in load test.|
41 21 Tobias Brunner
|charon.plugins.load-tester.enable                  |no        |Enable the load testing plugin. Read [[LoadTests]] first!.|
42 21 Tobias Brunner
|charon.plugins.load-tester.esp                     |aes128-sha1|CHILD_SA proposal to use for load tests.|
43 21 Tobias Brunner
|charon.plugins.load-tester.fake_kernel             |no        |Fake the kernel interface to allow load-testing against self.|
44 21 Tobias Brunner
|charon.plugins.load-tester.ike_rekey               |0         |Seconds to start IKE_SA rekeying after setup.|
45 21 Tobias Brunner
|charon.plugins.load-tester.init_limit              |0         |Global limit of concurrently established SAs during load test.|
46 21 Tobias Brunner
|charon.plugins.load-tester.initiator               |0.0.0.0   |Address to initiate from.|
47 21 Tobias Brunner
|charon.plugins.load-tester.initiator_auth          |pubkey    |Authentication method(s) the intiator uses.|
48 21 Tobias Brunner
|charon.plugins.load-tester.initiator_id            |          |Initiator ID used in load test.|
49 21 Tobias Brunner
|charon.plugins.load-tester.initiator_match         |          |Initiator ID to match against as responder.|
50 21 Tobias Brunner
|charon.plugins.load-tester.initiator_tsi           |          |Traffic selector on initiator side, as proposed by initiator.|
51 21 Tobias Brunner
|charon.plugins.load-tester.initiator_tsr           |          |Traffic selector on responder side, as proposed by initiator.|
52 21 Tobias Brunner
|charon.plugins.load-tester.initiators              |0         |Number of concurrent initiator threads to use in load test.|
53 21 Tobias Brunner
|charon.plugins.load-tester.issuer_cert             |          |Path to the issuer certificate (if not configured a hard-coded default value is used).|
54 21 Tobias Brunner
|charon.plugins.load-tester.issuer_key              |          |Path to private key that is used to issue certificates (if not configured a hard-coded default value is used).|
55 21 Tobias Brunner
|charon.plugins.load-tester.iterations              |1         |Number of IKE_SAs to initiate by each initiator in load test.|
56 21 Tobias Brunner
|charon.plugins.load-tester.mode                    |tunnel    |IPsec mode to use, one of _tunnel_, _transport_, or _beet_.|
57 21 Tobias Brunner
|charon.plugins.load-tester.pool                    |          |Provide INTERNAL_IPV4_ADDRs from a named pool.|
58 21 Tobias Brunner
|charon.plugins.load-tester.preshared_key           |<default-psk>|Preshared key to use in load test.|
59 21 Tobias Brunner
|charon.plugins.load-tester.proposal                |aes128-sha1-modp768|IKE proposal to use in load test.|
60 21 Tobias Brunner
|charon.plugins.load-tester.request_virtual_ip      |no        |Request an INTERNAL_IPV4_ADDR from the server.|
61 21 Tobias Brunner
|charon.plugins.load-tester.responder               |127.0.0.1 |Address to initiation connections to.|
62 21 Tobias Brunner
|charon.plugins.load-tester.responder_auth          |pubkey    |Authentication method(s) the responder uses.|
63 21 Tobias Brunner
|charon.plugins.load-tester.responder_id            |          |Responder ID used in load test.|
64 21 Tobias Brunner
|charon.plugins.load-tester.responder_tsi           |initiator_tsi|Traffic selector on initiator side, as narrowed by responder.|
65 21 Tobias Brunner
|charon.plugins.load-tester.responder_tsr           |initiator_tsr|Traffic selector on responder side, as narrowed by responder.|
66 21 Tobias Brunner
|charon.plugins.load-tester.shutdown_when_complete  |no        |Shutdown the daemon after all IKE_SAs have been established.|
67 21 Tobias Brunner
|charon.plugins.load-tester.socket                  |unix://${piddir}/charon.ldt|Socket provided by the [[LoadTests|load-tester]] plugin.|
68 21 Tobias Brunner
|charon.plugins.load-tester.version                 |0         |IKE version to use (0 means use IKEv2 as initiator and accept any version as responder).|
69 18 Tobias Brunner
70 7 Martin Willi
h2. Testing against self
71 7 Martin Willi
72 1 Martin Willi
73 1 Martin Willi
In the simplest case, the the daemon initiates IKE_SAs against self using the loopback interface. This will actually establish the doubled number of IKE_SAs, as the daemon is initiator and responder for each IKE_SA at the same time. Installation of IPsec SAs would fail, as each SA gets installed twice. To simulate the correct behavior, a faked kernel interface can be enabled which does not install the IPsec SAs at the kernel level.
74 1 Martin Willi
75 8 Tobias Brunner
A simple loop-back configuration in [[StrongswanConf|/etc/strongswan.conf]] might look like this:
76 7 Martin Willi
<pre>
77 1 Martin Willi
charon {
78 1 Martin Willi
    # create a new IKE_SA for each CHILD_SA to simulate different clients
79 1 Martin Willi
    reuse_ikesa = no
80 1 Martin Willi
    # turn off denial of service protection
81 1 Martin Willi
    dos_protection = no
82 1 Martin Willi
83 6 Martin Willi
    plugins {
84 9 Martin Willi
        load-tester {
85 1 Martin Willi
            # enable the plugin
86 1 Martin Willi
            enable = yes
87 1 Martin Willi
            # use 4 threads to initiate connections simultaneously
88 1 Martin Willi
            initiators = 4
89 1 Martin Willi
            # each thread initiates 1000 connections
90 1 Martin Willi
            iterations = 1000
91 1 Martin Willi
            # delay each initiation in each thread by 20ms
92 1 Martin Willi
            delay = 20
93 1 Martin Willi
            # fake the kernel interface to avoid SA conflicts
94 1 Martin Willi
            fake_kernel = yes
95 1 Martin Willi
        }
96 1 Martin Willi
    }
97 7 Martin Willi
}
98 1 Martin Willi
</pre>
99 1 Martin Willi
100 8 Tobias Brunner
This will initiate 4000 IKE_SAs within 20 seconds. You may increase the delay value if your box can not handle that much load, or decrease it to put more load on it. If the daemon starts retransmitting messages, your box probably can not handle all connection attempts.
101 1 Martin Willi
102 8 Tobias Brunner
h2. Testing against remote host
103 7 Martin Willi
104 7 Martin Willi
The plugin also allows to test against a remote host. This might help to test against a real world configuration. A connection setup to do stress testing of a gateway might look like this:
105 1 Martin Willi
<pre>
106 7 Martin Willi
charon {
107 1 Martin Willi
    reuse_ikesa = no
108 1 Martin Willi
    threads = 32
109 6 Martin Willi
110 6 Martin Willi
    plugins {
111 9 Martin Willi
        load-tester {
112 1 Martin Willi
            # enable the plugin
113 1 Martin Willi
            enable = yes
114 1 Martin Willi
            # 10000 connections, ten in parallel
115 1 Martin Willi
            initiators = 10
116 1 Martin Willi
            iterations = 1000
117 9 Martin Willi
            # use a delay of 100ms, overall time is: iterations * delay = 100s
118 1 Martin Willi
            delay = 100
119 12 Martin Willi
            # address of the gateway (releases before 5.0.2 used the "remote" keyword!)
120 12 Martin Willi
            responder = 1.2.3.4
121 1 Martin Willi
            # IKE-proposal to use
122 1 Martin Willi
            proposal = aes128-sha1-modp1024
123 1 Martin Willi
            # use faster PSK authentication instead of 1024bit RSA
124 9 Martin Willi
            initiator_auth = psk
125 9 Martin Willi
            responder_auth = psk
126 1 Martin Willi
            # request a virtual IP using configuration payloads
127 1 Martin Willi
            request_virtual_ip = yes
128 9 Martin Willi
            # disable IKE_SA rekeying (default)
129 9 Martin Willi
            ike_rekey = 0
130 9 Martin Willi
            # enable CHILD_SA every 60s
131 9 Martin Willi
            child_rekey = 60
132 9 Martin Willi
            # do not delete the IKE_SA after it has been established (default)
133 9 Martin Willi
            delete_after_established = no
134 9 Martin Willi
            # do not shut down the daemon if all IKE_SAs established
135 9 Martin Willi
            shutdown_when_complete = no
136 1 Martin Willi
        }
137 1 Martin Willi
    }
138 1 Martin Willi
}
139 1 Martin Willi
</pre>
140 1 Martin Willi
141 1 Martin Willi
h2. Configuration details
142 1 Martin Willi
143 9 Martin Willi
For public key authentication, the responder uses the _"CN=srv, OU=load-test, O=strongSwan"_ identity. The initiator, each connection attempt uses a different identity in the form _"CN=c1-r1, OU=load-test, O=strongSwan"_, where the first number inidicated the client number, the second the authentication round (if multiple authentication is used).
144 1 Martin Willi
145 9 Martin Willi
For PSK authentication, FQDN identities are used. The server uses _srv.strongswan.org_, the client uses an identity in the form _c1-r1.strongswan.org_.
146 1 Martin Willi
147 9 Martin Willi
For EAP authentication, the client uses a NAI in the form _100000000010001@strongswan.org_.
148 9 Martin Willi
149 9 Martin Willi
To configure multiple authentication, concatenate multiple methods using, e.g.
150 9 Martin Willi
<pre>
151 9 Martin Willi
  initiator_auth = pubkey|psk|eap-md5|eap-aka
152 9 Martin Willi
</pre>
153 9 Martin Willi
154 10 Tobias Brunner
The responder uses a hardcoded certificate based on a 1024-bit RSA key (see source:src/libcharon/plugins/load_tester/load_tester_creds.c). This certificate additionally serves as CA certificate. A peer uses the same private key, but generates client certificates on demand signed by the CA certificate. Install the Responder/CA certificate on the remote host to authenticate all clients.
155 5 Martin Willi
156 7 Martin Willi
To speed up testing, the load tester plugin implements a special Diffie-Hellman implementation called _modpnull_. By setting _proposal = aes128-sha1-modpnull_, this wicked fast DH implementation is used. It does not provide any security at all, but allows to run tests without DH calculation overhead.
157 1 Martin Willi
158 8 Tobias Brunner
There is a list of available configuration options for the load-tester plugin at the [[strongswanConf|strongswan.conf]] page.
159 11 Martin Willi
160 11 Martin Willi
h3. Custom credentials
161 11 Martin Willi
162 11 Martin Willi
Starting with strongSwan [[502|5.0.2]], load-tester can use a custom set of certificates for authentication. Certificates are still issued on demand, and the _issuer_key_ and _isser_cert_ options define the path to load the CA certificate and private key to load for issuing certificates. To load additional certificates to verify the trust chain (above _issuer_cert_), the _ca_dir_ option takes a directory to load trusted certificates from.
163 11 Martin Willi
164 11 Martin Willi
By default, the on-demand generated peer certificates are issued with RSA signatures using SHA1. To use a different hashing algorithm, the _digest_ option can be used, which accepts hash algorithms, such as _md5_, _sha1_, _sha256_ or _sha512_.
165 11 Martin Willi
166 11 Martin Willi
To use other peer identities than those hard-coded, the _initiator_id_ and _responder_id_ options can be used. These options can contain up to two _%d_ printf specifiers to replace. The first one is replaced by a unique number for each tunnel established, starting from 1. The second is replaced by the authentication round for this connection, starting at one. Take care to use _%d_ identifiers only, and just two of them, as the format string is not validated. To include % characters in an identity, prefix it with an additional %, as you would do it in a printf format string. As a responder, a specific _initiator_id_ wouldn't match to a custom _initiator_id_ configured on the client. Hence the _initiator_match_ option is introduced, which can be defined to an identity with wildcards that should match to all identities the initiator generates from the _initiator_id_ template. 
167 11 Martin Willi
168 11 Martin Willi
The identities generated from the configured templates are included in the on-demand issued certificates. Distinguished Name identities are encoded as subject. FQDN, email, IPv4/v6 identities are encoded as subjectAltName. If a subjectAltName gets encoded, the subject Distinguished Name of the certificate is a single Common Name Relative Distinguished Name equal to the subjectAltName.
169 11 Martin Willi
170 11 Martin Willi
An example of a load-test to itself with custom credentials could look like this:
171 11 Martin Willi
<pre>
172 11 Martin Willi
charon {
173 11 Martin Willi
    # ...
174 11 Martin Willi
    plugins {
175 11 Martin Willi
        load-tester {
176 11 Martin Willi
            enable = yes
177 11 Martin Willi
            initiators = 1
178 11 Martin Willi
            iterations = 100
179 11 Martin Willi
            fake_kernel = yes
180 11 Martin Willi
181 11 Martin Willi
            # initiator authenticates twice with on-demand
182 11 Martin Willi
            # generated certificates. Responder authenticates
183 11 Martin Willi
            # once only. 
184 11 Martin Willi
            initiator_auth = pubkey|pubkey
185 11 Martin Willi
            initiator_id = conn-%d-round-%d@strongswan.org
186 11 Martin Willi
            initiator_match = *@strongswan.org
187 11 Martin Willi
            responder_id = srv.strongswan.org
188 11 Martin Willi
            digest = sha256
189 11 Martin Willi
            issuer_cert = /path/to/ca.crt
190 11 Martin Willi
            issuer_key = /path/to/ca.key
191 11 Martin Willi
            ca_dir = /path/to/trustchain/certs
192 11 Martin Willi
        }
193 11 Martin Willi
    }
194 11 Martin Willi
}
195 11 Martin Willi
</pre>
196 13 Martin Willi
197 13 Martin Willi
h3. Traffic selectors
198 13 Martin Willi
199 13 Martin Willi
Starting with strongSwan [[502|5.0.2]], custom traffic selectors can be defined. The _initiator_tsi_, _initiator_tsr_, _responder_tsi_ and _responder_tsr_ define a traffic selector to propose as initiator or narrow down as responder. Only a single CIDR style subnet definition is allowed, protocol/port selectors are currently not supported.
200 14 Martin Willi
201 14 Martin Willi
h3. On-demand installed external addresses
202 14 Martin Willi
203 14 Martin Willi
To generate load against a responder that simulates more closely the real world, load-tester can use a unique external tunnel address for each established IKE_SA. The IPs are installed on-demand just before tunnel establishment on one or more interfaces. The _addrs_ sections takes key/value pairs of address pools to use, the _addrs_prefix_ defines the network prefix how the address is installed on the interface. An example could look like this:
204 14 Martin Willi
205 14 Martin Willi
<pre>
206 14 Martin Willi
charon {
207 14 Martin Willi
    # ...
208 14 Martin Willi
    plugins {
209 14 Martin Willi
        load-tester {
210 14 Martin Willi
            # ...
211 14 Martin Willi
            addrs {
212 14 Martin Willi
                # install ~32K addresses on eth0
213 14 Martin Willi
                eth0 = 10.2.0.0/17
214 14 Martin Willi
                # and then ~32K addresses on eth1
215 14 Martin Willi
                eth1 = 10.2.128.0/17
216 14 Martin Willi
            }
217 14 Martin Willi
            # install all addresses with a /16 prefix
218 14 Martin Willi
            addrs_prefix = 16
219 14 Martin Willi
        }
220 14 Martin Willi
    }
221 14 Martin Willi
}
222 14 Martin Willi
</pre>
223 14 Martin Willi
224 14 Martin Willi
> *Note:* Make sure to shut down unused network services when installing hundreds of addresses. Some services don't scale very well to this many addresses, the Avahi daemon for example can significantly slow down the system when running such tests.
225 15 Martin Willi
226 15 Martin Willi
227 15 Martin Willi
h2. Triggered batch initiations
228 15 Martin Willi
229 17 Martin Willi
With strongSwan [[502|5.0.2]], tunnels can not only be initiated on daemon startup with the _initiators/iterations_ keywords, but also while the daemon is running. The _ipsec load-tester_ tool takes as first argument the number of tunnels, and as second argument the delay between each initiation. Multiple clients can trigger initiation at the same time.
230 15 Martin Willi
231 15 Martin Willi
The _load-tester_ tool prints the status of the initiation with some simple characters to the console:
232 15 Martin Willi
233 15 Martin Willi
<pre>
234 15 Martin Willi
. : Initiation of a single tunnel started
235 15 Martin Willi
! : Initiation of a tunnel failed
236 15 Martin Willi
+ : A tunnel has been established successfully
237 15 Martin Willi
- : A tunnel failed to establish during the exchange
238 15 Martin Willi
* : A message has been retransmitted
239 15 Martin Willi
</pre>
240 15 Martin Willi
241 15 Martin Willi
A session might look like this:
242 15 Martin Willi
243 15 Martin Willi
<pre>
244 15 Martin Willi
> ipsec load-tester initiate 100 2
245 15 Martin Willi
.....++.+++..+..+.+.++..++.+.+.+.+.+.++..+..++...++.+.+.+.+.+
246 15 Martin Willi
...+++.+.+..++.++..+.++....+.+++++...+..+.++.+.++....++..+++.
247 15 Martin Willi
+..++.+.+.++.++....+++..++..+..+++.+..+..++.+.+..+++...++.++.
248 15 Martin Willi
+..+.+.+.+.+.+++*+
249 15 Martin Willi
</pre>
250 15 Martin Willi
251 15 Martin Willi
100 tunnels have been initiated and established successfully, one packet has been lost and was retransmitted. If many packets get retransmitted, this can be an indication that one of the systems is overloaded.