为什么nginx响应任何域名?

我有一个Ruby / Sinatra应用程序运行nginx,一切都很好。 但是,我现在试图从同一台服务器运行第二个应用程序,我注意到一些奇怪的东西。 首先,这是我的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请求?

nginxconfiguration中的第一个服务器块是所有请求的默认值,这些请求发生在没有特定服务器块的服务器上。

因此,在你的configuration中,假设你的真实域是REAL.COM,当用户input时,它将parsing到你的服务器,并且由于这个设置没有服务器块,所以FAKE.COM的服务器块是第一个服务器块(在你的情况只有服务器块),将处理该请求。

这就是为什么适当的Nginxconfiguration有一个特定的服务器块默认情况下之前跟其他人的特定域。

 # 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文件的文件名的字母顺序变得不相关。

另外,这种安排给了很大的灵活性,可以定义多个默认值。

在我的具体情况下,我只在内部接口上监听端口8080上的Apache,并将PHP和Perl脚本代理到Apache。

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

这会导致链接无效,因为无法从外部接口访问Apache,链接应指向端口80。

我通过为端口8080创build默认服务器来redirect这些请求来解决这个问题。

 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; } 

由于常规服务器块中没有任何内容在端口8080上侦听,所以redirect默认服务器块通过在nginx.conf中的位置来透明地处理此类请求。

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

你应该有一个默认的服务器来抓包 ,你可以返回404或更好的不响应(将节省一些带宽)通过返回444这是nginx特定的HTTP响应,只需closures连接,并返回什么

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

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

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

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

第一种方法 – 如果将服务器configuration保存在一个configuration文件中,如上面的Dayo所示,请首先在列表中指定默认服务器。

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

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

更多的信息在这里: Nginx的文档/听

将服务器configuration保存在单独的文件中,而不想按字母顺序命名这些文件时,这种方式更有用。

小评论回答:

如果您在sites-available /中的多个configuration文件中的多个IP上有几个虚拟主机,那么IP的“默认”域将按字母顺序从第一个文件中获取。

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

要回答你的问题 – 如果没有匹配,nginxselect第一个服务器。 请参阅文档 :

如果它的值与任何服务器名称不匹配,或者请求中根本不包含这个头域,那么nginx会将请求路由到这个端口的默认服务器。 在上面的configuration中,默认服务器是第一个…

现在,如果你想有一个默认的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接受连接,并且不会find证书/密钥。