Defender uses nginx to enable mutual Transport Layer Security (mTLS). With mTLS, in addition to the server presenting a certificate to the client, the client sends a certificate to the server.
The Defender configuration file
The nginx-config.json file enables Defender to use mTLS.
{
"includes": [
"/opt/cequence/nginx/conf/main.conf"
],
"directives": {
"worker_processes": "auto",
"pid": "/opt/nginx/nginx.pid",
"error_log": "/opt/nginx/log/error.log warn"
},
"events": {
"worker_connections": 16384
},
"http": {
"includes": [
"/opt/nginx/mime.types",
"/opt/cequence/nginx/conf/http.conf"
],
"directives": {
"uninitialized_variable_warn": "off",
"client_max_body_size": "250m",
"client_header_buffer_size": "12k",
"large_client_header_buffers": "8 16k",
"proxy_pass_header": "Server",
"proxy_buffer_size": "64K",
"proxy_buffers": "4 64k",
"default_type": "application/octet-stream",
"server_tokens": "off",
"resolver": "4.2.2.2",
"sendfile": "on",
"tcp_nopush": "on",
"tcp_nodelay": "on",
"keepalive_timeout": 65,
"map_hash_bucket_size": 128,
"underscores_in_headers": "on",
"access_log": "/opt/nginx/log/access.log main"
},
"log_formats": {
"main": [
"'[$time_local] $remote_addr $remote_port $uri $request_uri $status $body_bytes_sent \"$http_user_agent\" $request_time \"$upstream_connect_time\" \"$upstream_header_time\" \"$upstream_response_time\" \"$upstream_status\" \"$connection\" \"$connection_requests\" \"$upstream_addr\" \"$http_host\" $cq_client_ip $cq_fingerprint \"$ssl_cipher\" \"$ssl_server_name\" \"$ssl_client_verify\" \"$ssl_client_i_dn_legacy\" \"$ssl_client_s_dn_legacy\"'"
]
},
"servers": [
{
"includes": [
"/opt/cequence/nginx/conf/server.conf"
],
"listen": {
"port": 8443
},
"directives": {
"server_name": [
"servername.hostname.com"
],
"ssl_certificate": "/opt/cequence/nginx/mtls/certs/platform/serverCert.pem",
"ssl_certificate_key": "/opt/cequence/nginx/mtls/certs/platform/serverKey.pem",
"ssl_stapling": "on",
"ssl_stapling_verify": "on",
"ssl_trusted_certificate": "/opt/cequence/nginx/mtls/certs/platform/trustedCAs.pem",
"ssl_verify_client": "on",
"ssl_verify_depth": "5",
"ssl_client_certificate": "/opt/cequence/nginx/mtls/certs/platform/trustedCAs.pem",
"ssl_session_timeout": "5m",
"error_page": "400 /400.html"
},
"if_blocks": [
{
"condition": "$host",
"set_directives": {
"$origin": "$https_origin",
"$cq_upstream_resolve": "on",
"$cq_upstream_ttl_policy": "dns",
"$cq_resolver": "127.0.0.11,127.0.0.11"
}
}
],
"routes": {
"/.stealth-check": {
"modifier": "",
"directives": {
"return": "200 \"OK\n\""
}
},
"/": {
"modifier": "",
"proxy_pass": {
"scheme": "https",
"upstream": "$https_origin"
},
"if_blocks": [
{
"condition": "$ssl_client_verify != SUCCESS",
"directives": {
"return": "400"
}
}
],
"proxy_headers": {
"Host": "$host",
"Connection": "\"\"",
"CQ-Select": "CQ-Select-value",
"X-Forwarded-For": "$proxy_add_x_forwarded_for",
"True-Client-CQ": "$remote_addr",
"CQ-Mtls-Verified": "$ssl_client_verify",
"CQ-Client-Cert": "$ssl_client_escaped_cert",
"CQ-Client-Cert-CN": "$ssl_client_s_dn_cn",
"CQ-Request-Tls-Alpn": "$ssl_alpn_protocol",
"CQ-Request-Tls-Ciphers": "\"$ssl_cipher, $ssl_ciphers\"",
"CQ-Request-Tls-Curves": "\"$ssl_curve, $ssl_curves\"",
"CQ-Request-Tls-Protocol": "\"$ssl_protocol $ssl_early_data\""
},
"directives": {
"proxy_ssl_server_name": "on",
"proxy_ssl_certificate": "/opt/cequence/nginx/mtls/certs/platform/upstreamClientCert.pem",
"proxy_ssl_certificate_key": "/opt/cequence/nginx/mtls/certs/platform/upstreamClientKey.pem",
"proxy_http_version": "1.1",
"proxy_ssl_name": "$host"
}
},
"/400.html": {
"modifier": "=",
"directives": {
"root": "/opt/nginx/html",
"internal": ""
}
}
}
}
],
"maps": [
{
"source": "$ssl_client_s_dn",
"variable": "$ssl_client_s_dn_cn",
"directives": {
"default": "\"\"",
"~CN=(?<CN>([^,]|\\\\,)+)": "\"$CN\""
}
}
],
"upstreams": []
},
"upstream_conf": "/opt/cequence/conf/application-upstream.conf",
"default_conf": "/opt/nginx/conf.d/default.conf",
"nginx_conf": "/opt/nginx/nginx.conf"
}
The certificate lines in the server block of the configuration file enable communication from the downstream host to Defender.
"ssl_certificate": "/opt/cequence/nginx/mtls/certs/platform/serverCert.pem",
"ssl_certificate_key": "/opt/cequence/nginx/mtls/certs/platform/serverKey.pem",
"ssl_stapling": "on",
"ssl_stapling_verify": "on",
"ssl_trusted_certificate": "/opt/cequence/nginx/mtls/certs/platform/trustedCAs.pem",
"ssl_verify_client": "on",
"ssl_verify_depth": "5",
"ssl_client_certificate": "/opt/cequence/nginx/mtls/certs/platform/trustedCAs.pem",
- ssl_certificate - The certificate that the server presents to the downstream host, such as a browser or customer application.
- ssl_certificate_key - The private key for the server certificate.
- ssl_trusted_certificate - The list of certificates that the defender trusts when the client presents a certificate. Any certificate the client uses with the defender must be a certificate from the list.
- ssl_client_certificate - A list of certificate authorities (CAs) the defender sends to the client. The client must choose a certificate signed by a CA on the list. These CAs are not used to establish trust, but only when the defender must instruct the downstream server about acceptable certificates. This behavior is generally optional but specific use cases may require it.
The certificate lines in the following block of the configuration file enable comunication from the Defender to the upstream host.
"proxy_ssl_certificate": "/opt/cequence/nginx/mtls/certs/platform/upstreamClientCert.pem",
"proxy_ssl_certificate_key": "/opt/cequence/nginx/mtls/certs/platform/upstreamClientKey.pem",
"proxy_http_version": "1.1",
- proxy_ssl_certificate - The certificate presented to the upstream host.
- proxy_ssl_certificate_key - The key for the certificate.