Project

General

Profile

Load Tests » History » Version 18

Version 17 (Martin Willi, 12.11.2012 18:12) → Version 18/23 (Tobias Brunner, 23.07.2013 12:30)

h1. Load Tests

{{>toc}}

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.

h2. Setup

To build and enable the plugin, add
<pre>
--enable-load-tester
</pre>
to your _./configure_ options.

----

*Warning: Never enable the load-testing plugin on productive systems. It provides preconfigured credentials and allows an attacker to authenticate as any user.*

----

To make sure you are aware of this risk, an additional _enable_ switch in _strongswan.conf_ is required to load the plugin.

h2. Configuration

The plugin is configured using the following [[strongswan.conf]] options:

|_<.Key |_<.Default|_<.Description|
|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|
|charon.plugins.load-tester.addrs_keep |no |Whether to keep dynamic addresses installed even after the associated SA got terminated|
|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)|
|charon.plugins.load-tester.ca_dir | |Directory to load (intermediate) CA certificates from|
|charon.plugins.load-tester.child_rekey |600 |Seconds to start CHILD_SA rekeying after setup|
|charon.plugins.load-tester.delay |0 |Delay between initiatons for each thread|
|charon.plugins.load-tester.delete_after_established|no |Delete an IKE_SA as soon as it has been established|
|charon.plugins.load-tester.digest |sha1 |Digest algorithm used when issuing certificates|
|charon.plugins.load-tester.dpd_delay |0 |DPD delay to use in load test|
|charon.plugins.load-tester.dynamic_port |0 |Base port to be used for requests (each client uses a different port)|
|charon.plugins.load-tester.eap_password |default-pwd|EAP secret to use in load test|
|charon.plugins.load-tester.enable |no |Enable the load testing plugin. Read [[LoadTests]] first!|
|charon.plugins.load-tester.esp |aes128-sha1|CHILD_SA proposal to use for load tests|
|charon.plugins.load-tester.fake_kernel |no |Fake the kernel interface to allow load-testing against self|
|charon.plugins.load-tester.ike_rekey |0 |Seconds to start IKE_SA rekeying after setup|
|charon.plugins.load-tester.init_limit |0 |Global limit of concurrently established SAs during load test|
|charon.plugins.load-tester.initiator |0.0.0.0 |Address to initiate from|
|charon.plugins.load-tester.initiators |0 |Number of concurrent initiator threads to use in load test|
|charon.plugins.load-tester.initiator_auth |pubkey |Authentication method(s) the intiator uses|
|charon.plugins.load-tester.initiator_id | |Initiator ID to use in load test|
|charon.plugins.load-tester.initiator_match | |Initiator ID to match against as responder|
|charon.plugins.load-tester.initiator_tsi | |Traffic selector on initiator side, as proposed by initiator|
|charon.plugins.load-tester.initiator_tsr | |Traffic selector on responder side, as proposed by initiator|
|charon.plugins.load-tester.iterations |1 |Number of IKE_SAs to initiate by each initiator in load test|
|charon.plugins.load-tester.issuer_cert | |Path to the issuer certificate (if not configured a hard-coded value is used)|
|charon.plugins.load-tester.issuer_key | |Path to private key that is used to issue certificates (if not configured a hard-coded value is used)|
|charon.plugins.load-tester.pool | |Provide INTERNAL_IPV4_ADDRs from a named pool|
|charon.plugins.load-tester.preshared_key |default-psk|Preshared key to use in load test|
|charon.plugins.load-tester.proposal |aes128-sha1-modp768|IKE proposal to use in load test|
|charon.plugins.load-tester.responder |127.0.0.1 |Address to initiation connections to|
|charon.plugins.load-tester.responder ||Traffic selector on initiator side, as proposed by initiator|
|charon.plugins.load-tester.responder_auth |pubkey |Authentication method(s) the responder uses|
|charon.plugins.load-tester.responder_id | |Responder ID to use in load test|
|charon.plugins.load-tester.responder_tsi | |Traffic selector on initiator side, as narrowed by responder|
|charon.plugins.load-tester.responder_tsr | |Traffic selector on responder side, as narrowed by responder|
|charon.plugins.load-tester.request_virtual_ip |no |Request an INTERNAL_IPV4_ADDR from the server|
|charon.plugins.load-tester.shutdown_when_complete |no |Shutdown the daemon after all IKE_SAs have been established|
|charon.plugins.load-tester.socket |unix://${piddir}/charon.ldt|Socket provided by the [[LoadTests|load-tester]] plugin|
|charon.plugins.load-tester.version |0 |IKE version to use (0 means use IKEv2 as initiator and accept any version as responder)|

h2.
Testing against self

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.

A simple loop-back configuration in [[StrongswanConf|/etc/strongswan.conf]] might look like this:
<pre>
charon {
# create a new IKE_SA for each CHILD_SA to simulate different clients
reuse_ikesa = no
# turn off denial of service protection
dos_protection = no

plugins {
load-tester {
# enable the plugin
enable = yes
# use 4 threads to initiate connections simultaneously
initiators = 4
# each thread initiates 1000 connections
iterations = 1000
# delay each initiation in each thread by 20ms
delay = 20
# fake the kernel interface to avoid SA conflicts
fake_kernel = yes
}
}
}
</pre>

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.

h2. Testing against remote host

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:
<pre>
charon {
reuse_ikesa = no
threads = 32

plugins {
load-tester {
# enable the plugin
enable = yes
# 10000 connections, ten in parallel
initiators = 10
iterations = 1000
# use a delay of 100ms, overall time is: iterations * delay = 100s
delay = 100
# address of the gateway (releases before 5.0.2 used the "remote" keyword!)
responder = 1.2.3.4
# IKE-proposal to use
proposal = aes128-sha1-modp1024
# use faster PSK authentication instead of 1024bit RSA
initiator_auth = psk
responder_auth = psk
# request a virtual IP using configuration payloads
request_virtual_ip = yes
# disable IKE_SA rekeying (default)
ike_rekey = 0
# enable CHILD_SA every 60s
child_rekey = 60
# do not delete the IKE_SA after it has been established (default)
delete_after_established = no
# do not shut down the daemon if all IKE_SAs established
shutdown_when_complete = no
}
}
}
</pre>

h2. Configuration details

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).

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_.

For EAP authentication, the client uses a NAI in the form _100000000010001@strongswan.org_.

To configure multiple authentication, concatenate multiple methods using, e.g.
<pre>
initiator_auth = pubkey|psk|eap-md5|eap-aka
</pre>

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.

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.

There is a list of available configuration options for the load-tester plugin at the [[strongswanConf|strongswan.conf]] page.

h3. Custom credentials

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.

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_.

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.

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.

An example of a load-test to itself with custom credentials could look like this:
<pre>
charon {
# ...
plugins {
load-tester {
enable = yes
initiators = 1
iterations = 100
fake_kernel = yes

# initiator authenticates twice with on-demand
# generated certificates. Responder authenticates
# once only.
initiator_auth = pubkey|pubkey
initiator_id = conn-%d-round-%d@strongswan.org
initiator_match = *@strongswan.org
responder_id = srv.strongswan.org
digest = sha256
issuer_cert = /path/to/ca.crt
issuer_key = /path/to/ca.key
ca_dir = /path/to/trustchain/certs
}
}
}
</pre>

h3. Traffic selectors

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.

h3. On-demand installed external addresses

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:

<pre>
charon {
# ...
plugins {
load-tester {
# ...
addrs {
# install ~32K addresses on eth0
eth0 = 10.2.0.0/17
# and then ~32K addresses on eth1
eth1 = 10.2.128.0/17
}
# install all addresses with a /16 prefix
addrs_prefix = 16
}
}
}
</pre>

> *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.

h2. Triggered batch initiations

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.

The _load-tester_ tool prints the status of the initiation with some simple characters to the console:

<pre>
. : Initiation of a single tunnel started
! : Initiation of a tunnel failed
+ : A tunnel has been established successfully
- : A tunnel failed to establish during the exchange
* : A message has been retransmitted
</pre>

A session might look like this:

<pre>
> ipsec load-tester initiate 100 2
.....++.+++..+..+.+.++..++.+.+.+.+.+.++..+..++...++.+.+.+.+.+
...+++.+.+..++.++..+.++....+.+++++...+..+.++.+.++....++..+++.
+..++.+.+.++.++....+++..++..+..+++.+..+..++.+.+..+++...++.++.
+..+.+.+.+.+.+++*+
</pre>

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.