Home · Search · Print · Help
SSL layer
This page documents Web Polygraph traffic encryption capabilities related
to SSL and TLS (a.k.a., HTTPS) protocols. This functionality is supported
starting with Polygraph version 2.8.0.
Table of Contents
1. Terminology
2. Prerequisites
3. When to encrypt?
3.1 Server-side
3.2 Client-side
3.3 Proxy side
3.4 Configuration mismatch
4. SSL wraps
5. SSL Wrap
5.1 Session caching and resumption
6. Caveats
7. Appendix: Key generation
1. Terminology
By default, the term SSL is used to denote all supported
encryption protocols: SSLv2, SSLv3, and TLSv1. When applied to HTTP, this
group of encryption protocols is also known as HTTPS.
2. Prerequisites
Polygraph SSL support is based on the OpenSSL library. A recent version of
the library is required to compile Polygraph. We have tested with OpenSSL
versions 0.9.6g and 0.9.7b. The presence of OpenSSL is determined at
./configure time. Please check that ./configure actually found SSL library
and headers if you install Polygraph and want SSL support:
...
checking for CRYPTO_lock in -lcrypto... yes
checking for SSL_connect in -lssl... yes
checking for openssl/ssl.h... yes
checking for openssl/err.h... yes
checking for openssl/rand.h... yes
3. When to encrypt?
Using basic SSL features with Polygraph is quite simple,
provided you understand this section.
SSL is, essentially, a security layer on top of another protocol. In
our case, that other protocol is HTTP. Polygraph makes exactly the same
HTTP-level decisions regardless of the SSL configuration options. The good
old HTTP rules determine where Polygraph robots send their requests,
whether they think they are talking to a proxy, etc. SSL does not change
any of that.
The only big SSL-related decision Polygraph agents have to make is
whether to treat an existing (i.e., already established) HTTP/TCP
connection as an SSL-encrypted connection. To make that decision, a
Polygraph agent (robot or origin server) must consult ssl_wraps
array(s), a new configuration field added to Polygraph agents. The
encryption decision algorithm is different on client and server sides and
is documented below.
3.1 Server-side
On the server side, a server agent will treat an HTTP connection
as an SSL-encrypted connection if and only if that server agent
has a [non-empty] ssl_wraps array as a part of its PGL
configuration:
Server srvSsl = {
...
ssl_wraps = [ ... ];
};
In other words, servers do SSL when they are configured with
ssl_wraps. Servers with ssl_wraps do SSL and only
SSL.
3.2 Client-side
On the client side, a robot agent will treat an HTTP connection
as an SSL-encrypted connection if and only if both of the
following two conditions are met:
that robot has a [non-empty] ssl_wraps array
as a part of its PGL configuration, and
the visible origin server the robots wants to talk to is
configured to do SSL (i.e., has a [non-empty] ssl_wraps
array).
Robot rbtSsl = {
...
ssl_wraps = [ ... ];
origins = srvSsl.addresses;
};
In other words, Robots do SSL when they are configured with
ssl_wraps and expect the final destination of the request to do
SSL. As opposed to server agents, robots with ssl_wraps do either
SSL or unencrypted HTTP, depending on the visible request destination.
This asymmetry may seem unnatural, but it mimics real-life configurations
since most SSL-enabled clients can do both SSL and HTTP (while SSL servers
are usually dedicated to serving SSL requests).
See the next section for details about proxied cases.
3.3 Proxy side
It is important to remember that when deciding to enable SSL,
SSL-capable robots look at the final visible destination of the request
and not at the next hop on the request path. However, the next hop
configuration may affect other SSL-related aspects of a test. The next hop
can be:
- a true origin server,
- a surrogate proxy (a.k.a. web accelerator or reverse proxy)
pretending to be an origin server, or
- a forward proxy.
The first two cases are equivalent from HTTP point of view because
HTTP treats surrogates the same as origin server they represent (i.e.,
there is no protocol-level proxying going on).
The first case (a no-proxy mode) has already been discussed above.
When the next hop in your network setup is a surrogate doing SSL, you
need to tell Polygraph that that proxy is actually an SSL server, using
the Proxy PGL type. The Proxy type has been in PGL since
year 2000, but was not used much. Now it will be:
Proxy pxySsl = {
addresses = [ '172.16.0.5:443' ];
server.ssl_wraps = [ ... ];
};
use(pxySsl); // do not forget to use all agents
The above Proxy configuration template is probably sufficient for most
of your reverse proxy tests. The addresses array should contain
the addresses where your proxy/ies are listening to SSL requests. Proxy
addresses should also appear in the "names" array of an address map, as
usual:
AddrMap accelerationMap = {
names = pxySsl.addresses; // from
addresses = httpSrv.addresses; // to
};
use(accelerationMap);
These later mappings are needed for HTTP connections to work in the
presence of reverse proxies accelerating Polygraph origin server. They
are irrelevant to SSL. Recall that SSL decisions happen only after the two
points of an HTTP connection are decided upon. The only change here is
that SSL requires a Proxy agent so that we can put
ssl_wraps settings somewhere.
For forward proxying, the proxy address will be used with
--proxy command line option or in Robot.proxies array.
When a robot decides to do SSL (using the above documented rules) but
encounters a forward proxy on the way, the robot will use HTTP CONNECT
method to establish a tunnel through the proxy first, just like a
real web client would.
For example, the following trace shows robot CONNECT request, proxy
Connection Established response, robot GET request, and origin server OK
response. The latter two messages are tunneled through the proxy. Empty
lines separate HTTP messages.
CONNECT 172.16.0.202:4443 HTTP/1.1
HTTP/1.0 200 Connection established
GET http://172.16.0.202:4443/... HTTP/1.1
Accept: */*
Host: 172.16.0.202:4443
X-Target: 172.16.0.202:4443
HTTP/1.1 200 OK
Cache-Control: public
Date: Mon, 06 Oct 2003 16:52:18 GMT
Content-Length: 309520
X-Target: 172.16.0.202:4443
... CRLF followed by 309520 octets of data ...
Usually, a tunneling proxy would not be able to look at the content of
SSL-encrypted messages that it tunnels. However, if a proxy has origin
server private keys or if the robot does not thoroughly validate server
certificates, the proxy can terminate robot SSL encryption on itself
(i.e., act as an origin server) and establish its own SSL session with the
server. While this kind of behavior is a classic man-in-the-middle
attack, it is actually useful in many controlled environments where the
client trusts the proxy (e.g., a virus checking proxy on a corporate
network).
CONNECT requests and responses are not counted separately from other
HTTP messages and are viewed as a part of the following HTTP transaction.
Thus, the first HTTP transaction on an SSL tunnel will have longer
response times due to CONNECT overheads.
CONNECT phase of the tunnel establishment is performed in clear-text
mode, without any SSL encryption. Thus, the level of concurrent SSL
connections is often lower than the level of all concurrent HTTP/TCP
connections (since some connections are in a CONNECT state and do
not contribute towards SSL connections level).
3.4 Configuration mismatch
Note that SSL agents do not and cannot know whether the other end of
the HTTP/TCP connection is actually doing SSL. You can, for example,
[mis]configure an HTTP robot to talk to an SSL server. Similarly, if the
proxy is not doing its SSL encryption and/or decryption part, it may end
up speaking the "wrong" protocol to an agent. The result will be, of
course, a bunch of errors from SSL and/or HTTP routines.
4. SSL wraps
Agents' ssl_wraps array is a selector for SslWrap
objects:
SslWrap wrap1 = { ... };
SslWrap wrap2 = { ... };
SslWrap wrap3 = { ... };
Robot rbtSsl = {
addresses = [ '172.16.0.1' ** 10 ];
ssl_wraps = [ wrap1: 30%, wrap2: 20%, wrap3 ];
...
};
An SslWrap object describes SSL properties that should be used
for SSL connections serviced by the corresponding agent. We will talk
about SslWrap itself in the next section.
Note that ssl_wrap selection from ssl_wraps is
"random" and "sticky". Random selection means that you cannot predict
which robot will use what wrap unless you use a single wrap within a Robot
configuration.
Being "sticky" means that a single wrap is assigned to each robot at
the configuration time and the assignment does not change. This is natural
-- real agents usually do not change their SSL properties (e.g., going
from supporting SSLv2 to doing exclusively TLSv1). Sticky selection means
that if you have many wraps and few robots, the specified wrap
distribution (allocation percentages in ssl_wraps array) may not
materialize.
You can have many Robot configurations, of course:
Robot rbtSslOld = {
addresses = ...; // can be many
ssl_wraps = [ sslWrapOld1, sslWrapOld2 ];
...
};
Robot rbtSslNew = {
addresses = ...; // can be many
ssl_wraps = [ sslWrapTlsOnly ];
...
};
...
use(rbtSslOld, rbtSslNew);
Now let's see what we can put inside the ssl_wraps array.
5. SSL Wrap
An SslWrap object describes SSL properties that should be used
for SSL connections serviced by the corresponding agent. The setting
available in SslWrap may grow as Polygraph abilities expand. For
now, the following things can be specified:
SslWrap wrap = {
protocols = [ "SSLv2":40%, "SSLv3", "TLSv1" ];
root_certificate = "/tmp/root.pem";
ciphers = [ "ALL:HIGH": 100% ];
rsa_key_sizes = [ 512bit, 1024bit, 2048bit ];
session_resumption = 40%;
session_cache = 100;
};
If you are familiar with OpenSSL library design, you may notice that
the above fields affect mostly SSL context (OpenSSL's SSL_CTX type).
"protocols" -- selects a protocol an agent will support;
the selection is sticky per agent;
defaults to "any" which stands for "SSLv23" in OpenSSL
terminology.
"root_certificate" -- location of the root (CA) certificate
file; that file is needed for servers to generate
their certificates and for clients to verify server
certificates; if not defined, servers will generate
self-signed certificates and robots will not check
server certificates;
undefined by default
"ciphers" -- selects a ciphers the agent will use;
the selection is sticky;
see ciphers(1);
defaults to "ALL";
"rsa_key_sizes" -- selects key length to use when auto-generating
server private key;
the selection is sticky;
defaults to 1024 bits
"session_resumption" -- controls session caching and resumption
algorithms; should be used together with session_cache,
see below; defaults to 0%;
"session_cache" -- controls the size of the session cache
for the session_resumption feature, see below;
default varies based on the test side.
5.1 Session caching and resumption
Session caching algorithms differ on client and server sides.
Server-side session caching and resumption
A server agent enables OpenSSL session caching (with a configurable
cache size) if session_resumption is positive and disables it
otherwise.
The SSL session context ID is set if and only if session caching is
enabled.
If the cache size is not configured, the OpenSSL default is used.
OpenSSL documentation for SSL_CTX_sess_set_cache_size() says that the
default is SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (set to 1024*20 so that "up
to 20000 sessions can be held"), but check what your OpenSSL is using by
default. If the cache size is set to zero, OpenSSL uses an unlimited cache
size that may be perceived as a memory leak.
There is currently no way to control server-side caching at a finer
granularity because OpenSSL makes that very difficult if not
impossible.
Client-side session caching and resumption
On the client side, robots maintain a stack of SSL sessions. The
maximum size of the stack (in terms of number of sessions) is controlled
by the session_cache setting.
Session_resumption determines the probability that the robot
will attempt to resume the session for a new HTTP connection. Note that
such attempts may fail for various reasons beyond Polygraph control. If
the session was not resumed for that connection or the connection
experienced I/O errors, the session object (if there was one used) is
destroyed. Otherwise, the session object is put on the stack when the
connection is closed.
If session_resumption is not positive, the robot disables all
client-side session caching (which is also the OpenSSL default).
The session_cache option defaults to robot caches of unlimited
size. Unlimited cache sizes may lead to a ever-growing stack of SSL
sessions, which may be perceived as a memory leak. This default behavior
may change in future Polygraph releases.
6. Caveats
If you use SSL servers, they will need to generate their certificates.
The latter is done via calling OpenSSL command-line tools automatically
from the server process. This scheme works, but is somewhat
slow; a few second startup delay per server agent is typical.
An SSL configuration file, specified by the
SslWrap.ssl_config_file parameter, is needed for server agents to
generate their certificates runtime. This file can be rather complex but
this simple example seems to be sufficient for
our testing needs.
There are two ways Polygraph server can generate SSL certificates:
self-signed certificates and CA-signed certificates.
Working with self-signed certificates is simpler because all needed
certificates are generated runtime. Polygraph uses self-signed
certificates if SslWrap.root_certificate parameter is not
set.
Using CA-signed certificates requires generating a root CA certificate
beforehand and setting the SslWrap.root_certificate parameter.
Runtime, Polygraph would then generate server certificates signed with the
configured root CA certificate. The Key
generation appendix explains how to generate a root CA
certificate.
Polygraph uses "/tmp/" directory to store temporary files needed to
generate certificates.
Currently, SSL statistics are dumped on the console along with the
usual stats for all traffic. SSL-related lines have "https" suffix as
opposed to the "all" suffix of the lines that represent measurements for
all protocols. If you get no lines marked with "https", then your
test is not doing any SSL transactions.
000.54| i-test 4311 134.60 149 0.00 0 20 all
000.54| i-test 2111 66.40 145 0.00 0 8 https
000.63| i-test 5044 146.57 143 0.00 0 20 all
000.63| i-test 2450 67.79 158 0.00 0 10 https
000.71| i-test 5883 167.67 120 0.00 0 20 all
000.71| i-test 2871 84.13 118 0.00 0 10 https
...
001.14| p-test 10002 152.12 130 0.00 0 all
001.14| p-test 5016 76.29 130 0.00 0 https
We need to add a better interface to extract SSL-related
stats from Polygraph. If there is a particular measurement you would like
to see, please let us know.
7. Appendix: Key generation
This Appendix explains how to generate a root CA certificate useful
for SSL tests.
You may use command-line tools that come with OpenSSL to create a
private key and a self-signed certificate. You will need password-less
keys unless you want to type passphrase(s) when Polygraph starts. A simple
make-CA-cert.sh script does all the magic
for you. It uses a special ca-ssl.conf SSL
configuration file to generate a root CA certificate. The script puts both
private (used by servers) and public (used by robots) keys into a single
file, suitable for loading with the SslWrap.root_certificate
option documented above.
Home · Search · Print · Help
|