-
Notifications
You must be signed in to change notification settings - Fork 103
Tempesta TLS
Tempesta TLS supports TLS 1.2 only and TLS 1.3 is going to be implemented soon. Any SSL versions as well as old TLS versions such as 1.0 and 1.1 aren't supported. Insecure features commented in RFC 2525 are also gone: compression, renegotiations (Triple Handshakes and Cookie Cutters: Breaking andFixing Authentication over TLS describes attacks using TLS renegotiations), non-ephemeral key exchanges, weak ciphers like RC4 and DES and hashes like MD5, truncated HMAC, and so on.
- ECDHE-ECDSA-WITH-AES-128-GCM-SHA256
- ECDHE-ECDSA-WITH-AES-256-GCM-SHA384
- ECDHE-ECDSA-WITH-AES-256-CCM
- ECDHE-ECDSA-WITH-AES-128-CCM
- ECDHE-RSA-WITH-AES-128-GCM-SHA256
- ECDHE-RSA-WITH-AES-256-GCM-SHA384
- DHE-RSA-WITH-AES-256-GCM-SHA384
- DHE-RSA-WITH-AES-128-GCM-SHA256
- DHE-RSA-WITH-AES-256-CCM
- DHE-RSA-WITH-AES-128-CCM
During a TLS handshake Tempesta TLS picks the first ciphersuite from the list which is also present in the ClientHello list.
ECDHE and ECDSA algorithms are the most optimized, so we recommend to use
ECDHE-ECDSA
ciphersuites. At the moment, the RSA algorithm isn't performance
optimized, so we recommend to avoid it (RSA is the subject for performance
optimization is task https://github.com/tempesta-tech/tempesta/issues/1335).
At the moment we support only 1 NIST curve (short Weierstrass): secp256r1 (prime256v1).
Support of Curve25519
(Montgomery) is the subject for the task
https://github.com/tempesta-tech/tempesta/issues/1335 .
By default Tempesta TLS uses point randomization to prevent side channel attacks (read our Netdev 0x14 paper for details). This configuration provide the best performance and good security if you trust your CPU vendor since we use RDRAND instruction for random numbers generation.
If you do not trust your CPU vendor, then please use CRYPTO_CONST_TIME
configuration
option to make Tempesta TLS to use algorithms with constant time instead of
relying on point randomization. To do so, you need to recompile Tempesta with:
$ CRYPTO_CONST_TIME=1 make
Also reference how to build Tempesta FW from source code.
TempestaFW allows the use of TLS-encrypted HTTP connections (HTTPS). HTTPS traffic is terminated on TempestaFW. Backend servers always receive unencrypted traffic.
First configure TLS listening ports by adding proto=https
option for the listen
directive.
Example:
listen 443 proto=https;
Then add public certificate and the private key to configuration. PKCS#12 format isn't supported, please use OpenSSL command line tool to convert file formats if you want to store certificates in PKCS#12.
Certificates can be defined on per-vhost basis or at global level. Up to 8 certificates can be defined for each vhost.
To configure certificates for specific vhost, insert directives
tls_certificate
-- path to file with public certificate;
tls_certificate_key
-- path to file with private key;
inside vhost
section. The directives can be listed multiple times to configure
multiple possible certificates. Note, that certificates based on elliptic curves
provide better performance and less CPU consumption that RSA ones. It is
recommended to place certificates based on elliptic curves before RSA ones in
certificate list, because certificates are tried one-by-one.
vhost tempesta-tech.com {
tls_certificate /path/to/tfw-root.crt;
tls_certificate_key /path/to/tfw-root.key;
tls_certificate /path/to/other/tfw-root.crt;
tls_certificate_key /path/to/other/tfw-root.key;
}
Directive tls_certificate
must be always followed by tls_certificate_key
directive. If the condition is broken the syntax error will be thrown. Once both
are described, certificate is parsed and loaded into Tempesta. If an error
happens, configuration process will be aborted and line number of the
certificate caused error will be printed in the error message.
Same syntax is used to describe certificates at the top level of the
configuration file, the certificates will be applied to implicit default
vhost
then:
tls_certificate /path/to/tfw-root.crt;
tls_certificate_key /path/to/tfw-root.key;
tls_certificate /path/to/other/tfw-root.crt;
tls_certificate_key /path/to/other/tfw-root.key;
To chose the most suitable certificate for a new TLS connection Tempesta
extracts
Server Name Indication
and information about supported algorithms from ClientHello
message.
Server name extracted from the SNI extension in the ClientHello
is compared
across vhosts names defined in configuration file. If match is found that
vhost is used, otherwise connection is rejected. If client doesn't send SNI,
then default vhost is used.
Server name in the SNI extension in the ClientHello
message must conform
one of the vhost names defined in the configuration file, otherwise connection
will be rejected. If no TLS certificates is configured for target vhost,
default
vhost is chosen as a fallback option.
If client doesn't send SNI extension, then target server name
is not specified and the connection is established to default
vhost.
E.g. if client requests server name example.com
, vhost name example.com
will be chosen for that connection. If vhost example.com
doesn't exist in
the configuration incoming TLS connection will be rejected.
After vhost is determined, Tempesta tries certificates defined for that vhost one-by-one and chooses the first matching client abilities. Thus more preferable certificates should be defined first.
Note, although vhost is chosen for the TLS connection at establishing stage, it doesn't affect request distribution and doesn't replace
http_chain
directive.
The tls_match_any_server_name
directive can be defined for the default
vhost to match unknown server names to default
vhost:
tls_match_any_server_name;
Example 1. Multiple vhosts are defined in the configuration, each has its
own certificate. If a client requests server names example.com
, library.com
or store.com
, TLS connection is established. If client doesn't send SNI
extension, TLS connection is rejected.
listen 443 proto=https;
listen 80;
srv_group sg1 {
server 127.0.0.1:8080;
}
srv_group sg2 {
server 127.0.0.1:8081;
}
srv_group sg3 {
server 127.0.0.1:8082;
}
vhost example.com {
proxy_pass sg1;
tls_certificate /root/certbot/example/cert.pem;
tls_certificate_key /root/certbot/example/privkey.pem;
}
vhost library.com {
proxy_pass sg2;
tls_certificate /root/certbot/library/cert.pem;
tls_certificate_key /root/certbot/library/privkey.pem;
}
vhost store.com {
proxy_pass sg3;
tls_certificate /root/certbot/store/cert.pem;
tls_certificate_key /root/certbot/store/privkey.pem;
}
http_chain {
host == "example.com" -> example.com;
host == "library.com" -> library.com;
host == "store.com" -> store.com;
-> block;
}
Example 2. Two vhosts, but only one supports TLS connections.
If a client requests server names library.com
, TLS connection is established.
If client doesn't send SNI extension, TLS connection is rejected.
listen 443 proto=https;
listen 80;
srv_group sg1 {
server 127.0.0.1:8080;
}
srv_group sg2 {
server 127.0.0.1:8081;
}
vhost example.com {
proxy_pass sg1;
# No TLS certificates: this vhost is available only by HTTP connections.
}
vhost library.com {
proxy_pass sg2;
# TLS certificates configured, both HTTP and HTTPS connections to this vhost
# are possible.
tls_certificate /root/certbot/library/cert.pem;
tls_certificate_key /root/certbot/library/privkey.pem;
}
http_chain {
host == "example.com" -> example.com;
host == "library.com" -> library.com;
-> block;
}
Example 3. Global certificate is used for two vhosts, while the third uses
it's own certificate. If a client requests server names example.com
,
crm.example.com
or doesn't specify any (missing SNI extension), TLS connection
is established using /root/certbot/cert.pem
certificate.
If a client requests server name store.com
, TLS connection is established
using /root/certbot/store/cert.pem
certificate.
listen 443 proto=https;
listen 80;
srv_group sg1 {
server 127.0.0.1:8080;
}
srv_group sg2 {
server 127.0.0.1:8081;
}
srv_group sg3 {
server 127.0.0.1:8083;
}
vhost crm.example.com {
proxy_pass sg1;
}
vhost example.com {
proxy_pass sg2;
}
# vhost with it's own certificate.
vhost store.com {
proxy_pass sg3;
tls_certificate /root/certbot/store/cert.pem;
tls_certificate_key /root/certbot/store/privkey.pem;
}
# Singe TLS certificate for all the domains except 'store.com'
tls_certificate /root/certbot/cert.pem;
tls_certificate_key /root/certbot/privkey.pem;
http_chain {
host == "crm.example.com" -> crm.example.com;
host == "example.com" -> example.com;
host == "store.com" -> store.com;
-> block;
}
Example 4. Thousands of vhosts, few have their own certificates, but majority relies on global certificate. Clients with no SNI extension are allowed to open TLS connection using global certificate.
# Normal clients: Vhost names - domain names. No TLS certificates are configured
# global certificates will be used.
vhost baloons-for-sale.com {
...
}
vhost bnl.com {
...
}
vhost pizza-planet.com {
...
}
...
# Temporal clients pool for evaluation purposes. Vhost names - some abstract
# strings, not domain names, since domain names are auto generated.
vhost temp-client1 {
...
}
vhost temp-client2 {
...
}
vhost temp-client3 {
...
}
...
# Special clients with own TLS certificates.
vhost alstoybarn.com {
...
tls_certificate /root/certbot/store/cert_rsa.pem;
tls_certificate_key /root/certbot/store/privkey_rsa.pem;
tls_certificate /root/certbot/store/cert_ec.pem;
tls_certificate_key /root/certbot/store/privkey_ec.pem;
}
# We use one master certificate for all vhosts except very specific ones.
# If there is no 'tls_certificate' sertificate in vhost section, master
# certificate is used.
# Some clients - automation scripts (curl) and IoT devices that doesn't set SNI
# in TLS connections, master certificate is used for them.
# Some vhosts - temporal clients, we provide auto generated 3-rd level domain
# names for them. When a new client is added, we just update http_chain rules,
# but never update pool of vhosts in configuration. Thus we use
# `tls_match_any_server_name` directive to use mater key for all the unknown
# server names.
tls_match_any_server_name;
tls_certificate /root/certbot/cert.pem;
tls_certificate_key /root/certbot/privkey.pem;
# Dynamic rules, updated every two days:
http_chain evaluation_clients {
host == "mrpotato.cdn.com" -> temp-client1;
host == "linguine.cdn.com" -> temp-client2;
host == "zurg.cdn.com" -> temp-client3;
-> block;
}
# Constant rules, almost never updated.
http_chain {
# Normal clients:
host == "baloons-for-sale.com" -> baloons-for-sale.com;
host == "bnl.com" -> bnl.com;
host == "pizza-planet.com" -> pizza-planet.com;
# Special clients
host == "alstoybarn.com" -> alstoybarn.com;
# Clients on evaluation period
-> evaluation_clients;
}
If the server certificate is issued by Authority not known by the clients, chain of intermediate certificates up to root CA should be sent to clients in addition to server certificate.
To do so, just append intermediate certificates to file with server certificate.
cat server.crt intermediate1_cart.crt intermediate1_cart.crt > server_chained.crt
TempestaFW can resume previously established TLS sessions without storing session state as described in RFC 5077. This allows to save heavy computations on TLS handshake stage and reduce single packet round-trip between server and client. TLS Session ticket extension support is required from a client. Majority of the browsers and TLS libraries support it.
After a new TLS session is established, an encrypted ticket is sent to the client. The client can't decrypt or examine ticket content. The ticket can be sent by client in a new TLS handshake, if it can be successfully decrypted and not expired, server can reuse session state saved in the ticket. In this scenario, called abbreviated handshake, both client and server will reuse master key generated on the previous handshake and resume previous session.
Abbreviated handshakes are less expensive for server and enabled by default on majority of the clients, so the feature is enabled by default in TempestaFW too. But the configuration can be changed for each virtual host.
To reduce number of tickets, encrypted by the same key, TempestaFW uses individual keys for each virtual host and constantly rotates the ticket keys. Key rotation can be synchronised between multiple TempestaFW server, allowing to resume session created on another TempestaFW node. No shared cache is required, all the necessary information is stored inside TLS session ticket.
TLS tickets can be configured in vhost context with the following syntax:
tls_tickets secret="SECRET" lifetime=SECS;
where secret
- secret string, used to synchronize key rotation between multiple
servers. If not defined, a random value will be used on each node. lifetime
-
describes both key rotation time and maximum ticket lifetime, default -
3600
(1 hour). When a ticket is received by TempestaFW, it's creation time
is evaluated and, if it's already expired, fallback to full handshake is performed.
TLS tickets can be switched off using directive:
tls_tickets off;
Example:
vhost example.com {
tls_tickets secret="f00)9eR59*_/22" lifetime=7200;
}
The Virtual Host Confusion article from The Black Hat conference shows that use of shared TLS session caches and session tickets across different virtual hosts and connection reuse may weaken server authentication. Such network-based redirection attacks can lead to cookies and sign-on tokens theft, sessions hijacking, or certificate validation bypass.
In TempestaFW each session ticket is encrypted with a key, unique for each virtual host, contains authentication tag and requested SNI information. Thus ticket issued for one virtual host can't be used to resume session with another virtual host.
More information, tips and common mistakes explanation can be found on Virtual host confusion wiki page.
Certbot provides API to automatically get free certificates from Let's Encrypt service.
There is no official documentation to configure certbot
with Tempesta FW, so
we use Nginx script to initialize configs:
# apt install nginx
# certbot --nginx
# apt purge nginx
We recommend to use webroot plugin with Tempesta FW, for example:
# certbot certonly --key-type ecdsa --elliptic-curve secp256r1 --webroot -w /your/site/root/ --preferred-challenges http -d your.domain.com
Note that ECDSA certificate for secp256r1 curve is explicitly specified. By default certbot generates RSA certificates, which make TLS handshake much slower.
Configure your Tempesta FW to work with the certificate and private key updated by certbot:
tls_certificate /etc/letsencrypt/live/your.domain.com/cert.pem;
tls_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem;
To make certbot reload Tempesta FW configuration on certificate update, add
following renewal hook to /etc/letsencrypt/renewal/your.domain.com.conf
(supposed that you've installed Tempesta FW from
packages):
renew_hook = systemctl reload tempesta-fw.service
Finally, check your certbot configuration with
sudo certbot renew --dry-run
If it shows no errors, then you did everything right. Also check the systemd timers to make sure that the certbot automatic renewal was configured properly:
# systemctl list-timers |grep certbot
Mon 2021-07-19 04:17:00 UTC 4h 43min left Sun 2021-07-18 18:34:01 UTC 4h 59min ago snap.certbot.renew.timer snap.certbot.renew.service
- Home
- Requirements
- Installation
-
Configuration
- Migration from Nginx
- On-the-fly reconfiguration
- Handling clients
- Backend servers
- Load Balancing
- Caching Responses
- Non-Idempotent Requests
- Modify HTTP Messages
- Virtual hosts and locations
- HTTP Session Management
- HTTP Tables
- HTTP(S) Security
- Header Via
- Health monitor
- TLS
- Virtual host confusion
- Traffic Filtering by Fingerprints
- Run & Stop
- Application Performance Monitoring
- Use cases
- Performance
- Contributing