I'm using nginx to add TLS functionality on top of an existing TCP server (Redis) by proxying it like so (please read on before saying "Redis has builtin TLS support"):
stream {
server {
listen 6379 ssl;
ssl_certificate /etc/ssl/private/tls.crt;
ssl_certificate_key /etc/ssl/private/tls.key;
ssl_client_certificate /etc/ssl/private/ca.crt;
ssl_verify_client on;
proxy_pass redis:679;
}
}
However, this will accept all client certificates that have been signed by the specified CA. I'd like to only accept client certificates with a specific CN: cn=api
. When proxying HTTP I can use an if
statement like this
if ($ssl_client_s_dn != "CN=api") {
return 403;
}
However, it seems that if
statements like that are not allowed in stream servers. As a workaround I've used a map
statement to route requests that don't match the CN to a nonexistent upstream like this:
stream {
upstream redis_backend {
server redis:6379;
}
map $ssl_client_s_dn $backend_svr {
"CN=api" redis_backend;
default null;
}
server {
...
proxy_pass $backend_svr;
}
}
However, I can't help but feel that there must be a better way to reject the connection for mismatching client certificates.