为什么 nginx 对任何域名都有响应?

我已经启动了 nginx 并运行了一个 Ruby/Sinatra 应用程序,一切正常。然而,我现在正在尝试从同一台服务器运行第二个应用程序,我注意到了一些奇怪的事情。首先,这是我的 nginx.conf:

pid /tmp/nginx.pid;
error_log /tmp/nginx.error.log;


events {
worker_connections 1024;
accept_mutex off;
}


http {
default_type application/octet-stream;
access_log /tmp/nginx.access.log combined;


sendfile on;
tcp_nopush on;
tcp_nodelay off;


gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/xml text/css
text/comma-separated-values
text/javascript application/x-javascript
application/atom+xml;


upstream app {
server unix:/var/www/app/tmp/sockets/unicorn.sock fail_timeout=0;
}


server {
listen 80;
client_max_body_size 4G;
server_name FAKE.COM;


keepalive_timeout 5;


root /var/www/app/public;


location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;


if (!-f $request_filename) {
proxy_pass http://app;
break;
}
}


error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/app/public;
}
}
}
68,0-1        B

注意 server_name是如何设置为 FAKE.COM的,但是服务器通过其他域名响应所有访问该服务器的主机。我如何才能使那个特定的服务器只响应对 FAKE.COM的请求?

134941 次浏览

Nginx 配置中的第一个服务器块是没有特定服务器块的所有请求的默认服务器块。

所以在你的配置中,假设你真正的域名是 REAL.COM,当用户输入这个域名时,它会解析到你的服务器,因为这个设置没有服务器块,所以 FAKE.COM 的服务器块是第一个服务器块(在你的例子中只有服务器块) ,它会处理这个请求。

这就是为什么正确的 Nginx 配置有一个特定的默认服务器块,然后才是其他特定域的默认服务器块。

# Default server
server {
return 404;
}


server {
server_name domain_1;
[...]
}


server {
server_name domain_2;
[...]
}

等等

编辑

似乎有些用户对这个示例有些困惑,认为它仅限于一个 conf 文件等。

请注意,上面是一个简单的例子,OP 可以根据需要进行开发。

我个人使用单独的 vhost conf 文件,如下所示(CentOS/RHEL) :

http {
[...]
# Default server
server {
return 404;
}
# Other servers
include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/conf.d/将包含 domain _ 1。Conf,domain _ 2.Conf... domain _ n.Conf 将被包含在 nginx.conf 主文件的服务器块之后,它将始终是第一个文件,并且始终是默认文件,除非在其他地方用 default _ server 指令覆盖它。

在这种情况下,其他服务器的 conf 文件的文件名字母顺序就变得无关紧要了。

此外,这种安排提供了很大的灵活性,因为可以定义多个默认值。

在我的特定案例中,Apache 只监听内部接口上的8080端口,并将 PHP 和 Perl 脚本代理到 Apache。

但是,我运行了两个单独的应用程序,它们在检测到 Apache 没有在标准的80端口上运行时,都会在附加的 html 输出中返回“ : 8080”的链接,并尝试“帮助”我。

这会导致一个问题,即链接无效,因为无法从外部接口访问 Apache,而且链接应该指向端口80。

我通过为端口8080创建一个默认服务器来重定向这些请求来解决这个问题。

http {
[...]
# Default server block for undefined domains
server {
listen 80;
return 404;
}
# Default server block to redirect Port 8080 for all domains
server {
listen my.external.ip.addr:8080;
return 301 http://$host$request_uri;
}
# Other servers
include /etc/nginx/conf.d/*.conf;
}

由于常规服务器块中没有监听 Port 8080的内容,因此重定向默认服务器块通过其在 nginx.conf 中的位置透明地处理这些请求。

我实际上有四个这样的服务器块,这是一个简化的用例。

无可奉告:

如果你有几个虚拟主机上的几个 IP 在几个配置文件的网站-可用/,然后“默认”域的 IP 将采取从第一个文件按字母顺序。

正如 Pavel 所说,“ listen”指令 http://nginx.org/en/docs/http/ngx_http_core_module.html#listen有“ default _ server”参数

指定默认服务器的方法很少。

第一种方法 -如果将服务器配置保存在一个配置文件中(如上面的 Dayo 所示) ,则在列表中首先指定默认服务器。

第二种方法(更好) 更灵活-为 listen指令提供 default_server参数,例如:

server {
listen  *:80 default_server;
root /www/project/public/;
}

更多信息请点击:

当您将服务器配置保存在单独的文件中并且不希望按字母顺序命名这些文件时,这种方法更加有用。

我无法用其他任何答案来解决我的问题。我通过检查主机是否匹配并返回一个403(如果不匹配)来解决这个问题。(我有一些随机的网站指向我的网络服务器的内容。我猜是劫持搜索排名)

server {
listen 443;
server_name example.com;


if ($host != "example.com") {
return 403;
}


...
}

你应该有一个 什么都有的默认服务器,你可以返回 404或者更好的方法,通过返回 444来完全不响应(这样可以节省一些带宽) ,444是 nginx 特定的 HTTP 响应,它只是关闭连接,什么也不返回

server {
listen       80  default_server;
server_name  _; # some invalid name that won't match anything
return       444;
}

要回答你的问题-nginx 选择第一个服务器,如果没有匹配。参见 文件:

如果其值与任何服务器名称不匹配,或请求不匹配 包含这个头字段,然后 nginx 将请求路由到 此端口的默认服务器 默认服务器是第一个..。

现在,如果您希望拥有一个默认的 catch-all 服务器,比如说,它对所有请求都响应404,那么下面介绍如何做到这一点:

server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
ssl_certificate <path to cert>
ssl_certificate_key <path to key>
return 404;
}

注意,您需要指定证书/密钥(可以自签名) ,否则所有 SSL 连接都将失败,因为 nginx 将尝试接受使用这个 default _ server 的连接,并且找不到 cert/key。

server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 default_server;
listen [::]:443 default_server;
return 444;
}

如果您只是想忽略这些带有不需要的 Host或根本没有 Host的请求,那么创建一个接收服务器,每个可能的 address:port对都默认为接收服务器,并在那里执行 return 444;

不必为接收器支持 HTTP/2、 HTTP/3或 SSL 连接。对于不支持的连接,服务器只是拒绝这些连接。

对于受支持类型的连接,它只是立即挂起连接,而不需要发送响应,这就是 return 444;所做的。


从文件上看来的

Http://nginx.org/en/docs/http/request_processing.html

... NGINX 只测试请求的头字段“ Host”,以确定请求应该路由到哪个服务器。如果它的值与任何服务器名称都不匹配,或者请求根本不包含这个头字段,那么 NGINX 将把请求路由到这个端口的默认服务器。

Https://nginx.org/en/docs/http/ngx_http_core_module.html#listen

... 如果存在 default_server参数,将导致服务器成为指定 address:port对的默认服务器。

为了避免 ssl 的 nginx 配置失败,可能需要使用自签名证书。

但是请记住不要在 nginx 配置的其余部分使用自签名证书。

# /etc/nginx/sites-available/fallback
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;


include snippets/snakeoil.conf;


return 444;
}