1
I am using the nginx stream module to leverage nginx as a tcp reverse proxy in front of s3. Recently, I needed to add logic to accommodate an additional upstream. To do this, I chose to make use of conditional logic via the map variable $ssl_preread_server_name. ssl_preread allows nginx to extract the server name from the ClientHello message without terminating SSL. You can see the logic below:
map $ssl_preread_server_name $https_cname {
s3.amazonaws.com https_s3_backend;
aws-service-2.amazonaws.com aws-service-2-backend;
}
upstream https_s3_backend {
server s3.amazonaws.com:443;
}
upstream aws_service_2_backend {
server aws-service-2.amazonaws.com:443;
}
server {
listen 443;
proxy_pass $https_cname;
ssl_preread on;
}
When a request comes in that has the server name s3.amazonaws.com the request is sent to s3. When a request comes in that has the server name aws-service-2.amazonaws.com, the request is sent to aws-service-2.
This works most of the time. But, sometimes there are errors in the error log that indicate that somehow requests are hitting the nginx servers on port 443 without any server name.
[error] ... no host in upstream "", client: x.x.x.x, server: 0.0.0.0:443
When I add in a default statement in the map logic, these errors go away. What are possible explanations for some s3 requests coming in with no server name extracted? The only way requests could hit these nginx boxes currently is if someone does an s3 operation.