Varnish Total Encryption provides cache encryption and a VCL based crypto API. Varnish Total Encryption uses an innovative dual key encryption algorithm with one key securely stored in the Linux kernel and the other key generated from the client request. No keys are ever stored in Varnish or in cache and every object has its own unique key.
Further information can be found here: Varnish Total Encryption.
Generate a cookie based random ID string (UUID).
import crypto;
import cookieplus;
sub vcl_deliver
{
# ID format: 5a580f83ff659c9554b91e06c90ae7f1
if (!cookieplus.get("id")) {
cookieplus.setcookie_add("id", crypto.hex_encode(crypto.urandom()));
cookieplus.setcookie_write();
}
# ID format: 06d1ee05-ad8d-0e22-563f-8f9bd5b59bec
if (!cookieplus.get("id2")) {
cookieplus.setcookie_add("id2", crypto.uuid_v4());
cookieplus.setcookie_write();
}
}
Encrypting malloc
, file
, and mse
(non-persistence) using a randomly generated master key.
include "total-encryption/random_key.vcl";
Encrypting mse
with persistence enabled using a local secret key.
First, generate a new secret key:
$ cat /dev/urandom | head -c 1024 > /etc/varnish/disk_secret
$ sudo chmod 600 /etc/varnish/disk_secret
$ sudo chown root: /etc/varnish/disk_secret
Add the key to the varnishd
systemd unit configuration.
This allows the disk_secret
to be securely read via the varnishd
jail configuration:
ExecStart=/usr/sbin/varnishd ... -E /etc/varnish/disk_secret
For more information on how to do this, please see our systemd reference.
Use the secret key to encrypt cache:
include "total-encryption/secret_key.vcl";
When using one of the above Total Encryption includes, you can optionally encrypt headers with the following VCL:
sub vcl_backend_response {
# Encrypt beresp.http.Content-Type
set beresp.http.Content-Type = crypto.hex_encode(crypto.aes_encrypt(beresp.http.Content-Type));
}
sub vcl_deliver {
# Decrypt resp.http.Content-Type
if (resp.http.Content-Type != "") {
set resp.http.Content-Type = crypto.aes_decrypt(crypto.hex_decode(resp.http.Content-Type));
}
}
Use crypto.aes_skip_response()
to skip encryption or decryption in
sub vcl_backend_response
or sub vcl_deliver
.
sub vcl_backend_response {
if (beresp.http.Content-Type ~ "video") {
crypto.aes_skip_response();
}
}
By default Varnish Total Encryption uses Cipher Block Chaining (CBC) AES encryption. On some systems, Propagating Cipher Block Chaining (PCBC) is available hardware accelerated. If so, use the following VCL to use PCBC AES encryption:
sub vcl_init {
te_opts.set("algorithm", "pcbc(aes)");
}
BLOB blob(STRING value)
Cast a STRING to a BLOB. If using a STRING based secret, this function must be used to cast the secret to a BLOB.
Arguments:
value
accepts type STRINGType: Function
Returns: Blob
STRING string(BLOB value)
Cast a BLOB to a STRING.
Arguments:
value
accepts type BLOBType: Function
Returns: String
STRING hex_encode(BLOB value)
Hex encode a binary (BLOB) value. Lowercase hex is used.
Arguments:
value
accepts type BLOBType: Function
Returns: String
BLOB hex_decode(STRING value)
Hex decode a hex string into a binary BLOB.
Arguments:
value
accepts type STRINGType: Function
Returns: Blob
STRING base64_encode(BLOB value)
Base64 encode a binary (BLOB) value.
Arguments:
value
accepts type BLOBType: Function
Returns: String
BLOB base64_decode(STRING value)
Base64 decode a string into a binary BLOB.
Arguments:
value
accepts type STRINGType: Function
Returns: Blob
BLOB urandom(INT bytes = 16)
Get bytes from /dev/urandom
.
Arguments:
bytes
accepts type INT with a default value of 16
optional
Type: Function
Returns: Blob
BLOB secret()
Get the contents of the secret file from the command line parameter -E
.
If using a Total Encryption secret key, this value will be scrubbed and the return value will be empty.
Arguments: None
Type: Function
Returns: Blob
VOID hash_part(ENUM {md5,sha1,sha224,sha256,sha384,sha512} algorithm, STRING part)
Arguments:
part
accepts type STRING
algorithm
is an ENUM that accepts values of md5
, sha1
, sha224
, sha256
, sha384
, and sha512
Type: Function
Returns: None
BLOB hash(ENUM {md5,sha1,sha224,sha256,sha384,sha512} algorithm, STRING value)
Arguments:
value
accepts type STRING
algorithm
is an ENUM that accepts values of md5
, sha1
, sha224
, sha256
, sha384
, and sha512
Type: Function
Returns: Blob
OBJECT hmac_init(ENUM {sha1,sha224,sha256,sha384,sha512} algorithm, STRING cache_name = "")
Create a new HMAC signing object. This object using the Linux Kernel Crypto API for signing. The HMAC key used is securely stored in the kernel and not kept in the Varnish address space.
Arguments:
cache_name
accepts type STRING with a default value of empty. optional
algorithm
is an ENUM that accepts values of sha1
, sha224
, sha256
, sha384
, and sha512
Type: Object
Returns: Object.
VOID .set_key(BLOB key)
Set the key of an HMAC signing object. Can only be used in sub vcl_init
.
Arguments:
key
accepts type BLOBType: Method
Returns: None
Restricted to: vcl_init
VOID .add_string(STRING value)
Add a string to the HMAC.
Arguments:
value
accepts type STRINGType: Method
Returns: None
VOID .add_blob(BLOB value)
Add a blob to the HMAC.
Arguments:
value
accepts type BLOBType: Method
Returns: None
BLOB .get()
The the HMAC value. After calling, the HMAC state is reset.
Arguments: None
Type: Method
Returns: Blob
BLOB hmac(ENUM {sha1,sha224,sha256,sha384,sha512} algorithm, BLOB key, STRING value)
Perform an HMAC operation.
Arguments:
key
accepts type BLOB
value
accepts type STRING
algorithm
is an ENUM that accepts values of sha1
, sha224
, sha256
, sha384
, and sha512
Type: Function
Returns: Blob
VOID aes_key(BLOB key, BLOB salt = 0, STRING algorithm = "")
Set an AES key. This is request scope only. The Linux Kernel Crypto API is used.
The key must be either 128, 192, or 256 bit. The salt (iv) must be 16 bytes, block size is 16 bytes and padding is NULL bytes
Note: If using Total Encryption, this can be safely used in sub vcl_recv
only.
This is automatically called in sub vcl_backend_response
and sub vcl_deliver
with a key
unique to the request. Please contact support for advanced usage.
Arguments:
key
accepts type BLOB
salt
accepts type BLOB with a default value of 0
optional
algorithm
accepts type STRING with a default value of empty. optional
Type: Function
Returns: None
BLOB aes_encrypt(STRING value)
AES encrypt a value. The block size is 16 bytes and the result is NULL padded.
Arguments:
value
accepts type STRINGType: Function
Returns: Blob
STRING aes_decrypt(BLOB value)
AES decrypt a value. The block size must be 16 bytes.
Arguments:
value
accepts type BLOBType: Function
Returns: String
INT aes_get_length()
Get the padding length.
Arguments: None
Type: Function
Returns: Int
VOID aes_set_length(INT length)
Set the padding length.
Arguments:
length
accepts type INTType: Function
Returns: None
VOID aes_encrypt_response()
Encrypt a response.
Arguments: None
Type: Function
Returns: None
VOID aes_decrypt_response()
Decrypt a response.
Arguments: None
Type: Function
Returns: None
VOID aes_skip_response()
Skip a response.
Arguments: None
Type: Function
Returns: None
STRING uuid_v4()
Get a version 4 UUID.
Arguments: None
Type: Function
Returns: String
The crypto
VMOD is available in Varnish Enterprise version 6.0.0r0
and later.