Short answer: Yes, there is difference between server_name "";
and server_name _;
Long answer: server_name "";
defines a match for a request without host
header since 0.8.48 and it has been supported since 0.7.12.
https://nginx.org/en/docs/http/request_processing.html
If requests without the “Host” header field should not be allowed, a
server that just drops the requests can be defined:
server {
listen 80;
server_name "";
return 444;
}
Here, the server name is set to an empty string that will match
requests without the “Host” header field, and a special nginx’s
non-standard code 444 is returned that closes the connection.
On the other side, server_name _;
defines an invalid server names which never intersect with any real name. It is just a non-match. So in the event of no matches, nginx will select the first server{} block and use that.
To conclude, you can use server_name _;
for catch-all server block but not server_name "";
.
Reference -
https://stackoverflow.com/questions/9454764/nginx-server-name-wildcard-or-catch-all
https://blog.gahooa.com/2013/08/21/nginx-how-to-specify-a-default-server/