Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

35.11. FAQ

35.11.1. 405 Not Allowed?

35.11.1.1. 405 Not Allowed?

35.11.1.1.

405 Not Allowed?

静态页面POST会提示405 Not Allowed错误.

					
# curl -d name=neo http://www.mydoamin.com/index.html
<html>
<head><title>405 Not Allowed</title></head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx</center>
</body>
</html>
					
					
server {
    listen       80 default;
    server_name  myid.mydomain.com;

    charset utf-8;
    access_log  /var/log/nginx/myid.mydomain.com.access.log  main;

    if ($http_user_agent ~* ^$){
      return 412;
    }
    ###########################

    location / {
        root   /www/mydomain.com/myid.mydomain.com;
        index  index.html index.php;
        #error_page 405 =200 $request_filename;
    }

    #error_page  404              /404.html;
    #
    error_page 405 =200 @405;
    location @405 {
        #proxy_set_header  Host            $host;
        proxy_method GET;
        proxy_pass http://myid.mydomain.com;

    }


    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
					

35.11.2. 413 Request Entity Too Large

上传文件大小限制

35.11.2.1. 413 Request Entity Too Large

35.11.2.1.

413 Request Entity Too Large

error.log 提示:

client intended to send too large body

client_max_body_size 8m;

修改 /etc/nginx/nginx.conf 文件。

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    server_tokens off;
    gzip  on;
    gzip_min_length 1k;
    gzip_types text/plain text/html text/css application/javascript text/javascript application/x-javascript text/xml application/xml application/xml+rss application/json;
    gzip_vary on;

    client_max_body_size 8m;

    include /etc/nginx/conf.d/*.conf;
}
					

35.11.3. 499 Client Closed Request

35.11.3.1. Nginx access.log 日志显示

35.11.3.1.

Nginx access.log 日志显示

111.85.11.15 - - [25/Jun/2016:19:20:35 +0800] "GET /xxx/xxx/xxx.jsp HTTP/1.1" 499 88 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 JianKongBao Monitor 1.1"

配置 proxy_ignore_client_abort on;

    location / {

		ssi on;
		proxy_set_header Accept-Encoding "";
		proxy_pass http://127.0.0.1:8080;
        proxy_set_header    Host    $host;
        proxy_set_header    X-Real-IP   $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_ignore_client_abort  on;
    }
					

35.11.4. 502 Bad Gateway?

35.11.4.1. 502 Bad Gateway

35.11.4.1.

502 Bad Gateway

error.log 提示:

upstream sent too big header while reading response header from upstream?

修改fastcgi配置

location ~ \.php$ {

	fastcgi_buffers 8 16k;
	fastcgi_buffer_size 32k;
	。。。
	。。。
}
					

35.11.5. 504 Gateway Time-out

35.11.5.1. 504 Gateway Time-out

35.11.5.1.

504 Gateway Time-out

问题一般出现在 nginx 通过 proxy_pass 代理其他服务的场景

由于代理的后端服务处理时间较长,超过了timeout阀值,就会报出 504 错误

修改fastcgi配置

client_max_body_size     50m; //文件大小限制,默认1m
client_header_timeout    1m;
client_body_timeout      1m;
proxy_connect_timeout     60s;
proxy_read_timeout      1m;
proxy_send_timeout      1m;		

每个参数的意思:

client_max_body_size	限制上传数据的的大小,若超过所设定的大小,返回413错误。
client_header_timeout	读取请求头的超时时间,若超过所设定的大小,返回408错误。
client_body_timeout		读取请求实体的超时时间,若超过所设定的大小,返回413错误。
proxy_connect_timeout	此参数为等待的最长时间,默认为60秒,官方推荐最长不要超过75秒。
proxy_read_timeout		http请求代理后,nginx会等待处理结果。此参数即为服务器响应时间,默认60秒。
proxy_send_timeout		http请求被服务器处理完后,把数据传返回给Nginx的用时,默认60秒。			
					

35.11.6. proxy_pass

nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /etc/nginx/conf.d/www.mydomain.com.conf:25
nginx: configuration file /etc/nginx/nginx.conf test failed
		

在location,if中使用证则匹配proxy_pass末尾不能写/

	if ($request_uri ~* "^/info/{cn|tw}/{news|info}/\d\.html") {
		proxy_pass http://info.example.com/;
		break;
	}

    location ~ ^/info/ {
                proxy_pass http://info.example.com/;
                break;
    }
		

proxy_pass http://info.example.com/; 改为 proxy_pass http://info.example.com; 可以解决

35.11.7. proxy_pass SESSION 丢失问题

如果用户Cookie信息没有经过 proxy_pass 传递给最终服务器,SESSION信息将丢失,解决方案

proxy_set_header   Cookie $http_cookie;
		

35.11.8. [alert] 55785#0: *11449 socket() failed (24: Too many open files) while connecting to upstream

配置 worker_rlimit_nofile 参数即可

user  nginx;
worker_processes  8;
worker_rlimit_nofile 65530;
		

配置 ulimit 也能达到同样效果,但我更喜欢 worker_rlimit_nofile 因为它仅仅作用于nginx,而不是全局配置。

35.11.9. server_name 与 SSI 注意事项

server_name www.example.com www.example.net www.example.org;
		

下来SSI标签无论你使用那个域名访问,输出永远是server_name的第一域名www.example.com

		
<!--#echo var="SERVER_NAME"-->
		
		

需要通过SERVER_NAME判定展示不同结果时需要注意。

35.11.10. location 跨 document_root 引用,引用 document_root 之外的资源

下面的例子是 Document root 是 /www/netkiller.com/m.netkiller.com, 我们需要 /www/netkiller.com/www.netkiller.com 中的资源。

		
server {
    listen       80;
    server_name  m.netkiller.com;

    charset utf-8;
    access_log  /var/log/nginx/m.netkiller.com.access.log;
    error_log  /var/log/nginx/m.netkiller.com.error.log;

    location / {
		root /www/netkiller.com/m.netkiller.com;
		index.html
    }

    location /module {
        root /www/netkiller.com/www.netkiller.com;
    }	

}

		
		
		
server {
    listen       80;
    server_name  m.netkiller.com;

    charset utf-8;
    access_log  /var/log/nginx/m.netkiller.com.access.log;
    error_log  /var/log/nginx/m.netkiller.com.error.log;

    location / {
		root /www/netkiller.com/m.netkiller.com;
		index.html
    }

    location ^~ /module/ {
        root /www/netkiller.com/www.netkiller.com;
    }	

}
		
		

上面的例子location /module 是指 /www/netkiller.com/www.netkiller.com + /module,如果 /www/netkiller.com/www.netkiller.com 目录下面没有 module 目录是出现404, error.log显示 "/www/netkiller.cn/www.netkiller.cn/module/index.html" failed (2: No such file or directory)

35.11.11. nginx: [warn] duplicate MIME type "text/html" in /etc/nginx/nginx.conf

text/html 是 gzip_types 默认值,所以不要将text/html加入到gzip_types列表内

35.11.12. 127.0.0.1:8080 failed

链接本地端口失败,已经关闭防火墙,同时使用 curl http://127.0.0.1:8080 一切正常

日志片段

		
2018/09/07 12:31:27 [crit] 10202#10202: *4 connect() to [::1]:8080 failed (13: Permission denied) while connecting to upstream, client: 47.90.97.183, server: www.api.netkiller.cn, request: "GET /api/ HTTP/2.0", upstream: "http://[::1]:8080/api/", host: "api.netkiller.cn"
2018/09/07 12:31:27 [warn] 10202#10202: *4 upstream server temporarily disabled while connecting to upstream, client: 47.90.97.183, server: www.api.netkiller.cn, request: "GET /api/ HTTP/2.0", upstream: "http://[::1]:8080/api/", host: "api.netkiller.cn"
2018/09/07 12:31:27 [crit] 10202#10202: *4 connect() to 127.0.0.1:8080 failed (13: Permission denied) while connecting to upstream, client: 47.90.97.183, server: www.api.netkiller.cn, request: "GET /api/ HTTP/2.0", upstream: "http://127.0.0.1:8080/api/", host: "api.netkiller.cn"
2018/09/07 12:31:27 [warn] 10202#10202: *4 upstream server temporarily disabled while connecting to upstream, client: 47.90.97.183, server: www.api.netkiller.cn, request: "GET /api/ HTTP/2.0", upstream: "http://127.0.0.1:8080/api/", host: "api.netkiller.cn"
		
		

问题出现在 AWS 亚马逊云主机。经过筛查发现是 SELINUX 问题

		
[root@netkiller ~]# cat /var/log/audit/audit.log | grep nginx | grep denied | more

type=AVC msg=audit(1536320093.274:345): avc:  denied  { sys_resource } for  pid=9544 comm="nginx" capability=24  scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=capabi
lity
type=AVC msg=audit(1536320093.274:346): avc:  denied  { sys_resource } for  pid=9545 comm="nginx" capability=24  scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=capabi
lity
type=AVC msg=audit(1536320093.275:347): avc:  denied  { sys_resource } for  pid=9546 comm="nginx" capability=24  scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=capabi
lity
type=AVC msg=audit(1536321850.706:459): avc:  denied  { sys_resource } for  pid=9798 comm="nginx" capability=24  scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=capabi
lity
type=AVC msg=audit(1536321850.707:460): avc:  denied  { sys_resource } for  pid=9799 comm="nginx" capability=24  scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=capabi
lity
type=AVC msg=audit(1536321920.108:461): avc:  denied  { name_connect } for  pid=9796 comm="nginx" dest=8080 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_cache_port_t:s0 tclass=t
cp_socket
type=AVC msg=audit(1536321920.109:462): avc:  denied  { name_connect } for  pid=9796 comm="nginx" dest=8080 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_cache_port_t:s0 tclass=t
cp_socket		
		
		

35.11.13. failed (13: Permission denied) while connecting to upstream

问题分析,此问题出在 SELINUX

		
2021/07/13 02:18:52 [crit] 6671#0: *3 connect() to 192.168.60.7:8000 failed (13: Permission denied) while connecting to upstream, client: 192.168.90.137, server: www.netkiller.cn, request: "GET / HTTP/2.0", upstream: "http://192.168.60.7:8000/", host: "www.netkiller.cn"		
		
		

查看 SELINUX 设置

		
[root@localhost ~]# getsebool -a | grep httpd
httpd_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_connect_ftp --> off
httpd_can_connect_ldap --> off
httpd_can_connect_mythtv --> off
httpd_can_connect_zabbix --> off
httpd_can_network_connect --> on
httpd_can_network_connect_cobbler --> off
httpd_can_network_connect_db --> off
httpd_can_network_memcache --> off
httpd_can_network_relay --> off
httpd_can_sendmail --> off
httpd_dbus_avahi --> off
httpd_dbus_sssd --> off
httpd_dontaudit_search_dirs --> off
httpd_enable_cgi --> on
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> off
httpd_execmem --> off
httpd_graceful_shutdown --> off
httpd_manage_ipa --> off
httpd_mod_auth_ntlm_winbind --> off
httpd_mod_auth_pam --> off
httpd_read_user_content --> off
httpd_run_ipa --> off
httpd_run_preupgrade --> off
httpd_run_stickshift --> off
httpd_serve_cobbler_files --> off
httpd_setrlimit --> off
httpd_ssi_exec --> off
httpd_sys_script_anon_write --> off
httpd_tmp_exec --> off
httpd_tty_comm --> off
httpd_unified --> off
httpd_use_cifs --> off
httpd_use_fusefs --> off
httpd_use_gpg --> off
httpd_use_nfs --> off
httpd_use_opencryptoki --> off
httpd_use_openstack --> off
httpd_use_sasl --> off
httpd_verify_dns --> off
		
		
		

设置此选项可以解决

		
[root@localhost ~]# setsebool -P httpd_can_network_connect true 		
		
		

35.11.14. upstream sent too big header while reading response header from upstream

解决方案

		
		proxy_buffer_size  64k;
        proxy_buffers   32 64k;
        proxy_busy_buffers_size 128k;		
		
		

完整例子

		
server {
    listen       80;
    listen       443 ssl http2;
    server_name  www.netkiller.cn;

    ssl_certificate "/etc/pki/nginx/server.crt";
    ssl_certificate_key "/etc/pki/nginx/private/server.key";
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers PROFILE=SYSTEM;
    ssl_prefer_server_ciphers on;

    access_log /var/log/nginx/www.netkiller.cn.access.log;
    error_log /var/log/nginx/www.netkiller.cn.error.log;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
        #proxy_set_header Host $host;
        #proxy_set_header X-Real-IP $remote_addr;
        #proxy_set_header REMOTE-HOST $remote_addr;
        #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffer_size  64k;
        proxy_buffers   32 64k;
        proxy_busy_buffers_size 128k;
        proxy_pass http://192.168.30.50;
    }

    error_page 497 https://$host$uri?$args;

    if ($scheme = http) {
        return 301 https://$server_name$request_uri;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}
		
		

35.11.15. 很目录 index.html 正常访问,其他文件都是 404

情景模拟

		
server {
    listen       80;
    listen       443 ssl http2;
    server_name  www.netkiller.cn;

    access_log /var/log/nginx/www.netkiller.cn.access.log;
    error_log /var/log/nginx/www.netkiller.cn.error.log;

    error_page 497 https://$host$uri?$args;
	
    if ($scheme = http) {
	    return 301 https://$server_name$request_uri;
    }
    
    location / {
        root   /opt/netkiller.cn/www.netkiller.cn;	
	    index  index.html;
    }

    location /api/ {
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://gateway.netkiller.cn:8080/;
        proxy_connect_timeout 120;
        proxy_send_timeout 120;
        proxy_read_timeout 120;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}
		
		

问题分析,这个问题是因为 root 目录指向放在了 location / 下面造成的。解决方案:

		
server {
    listen       80;
    listen       443 ssl http2;
    server_name  www.netkiller.cn;

    access_log /var/log/nginx/www.netkiller.cn.access.log;
    error_log /var/log/nginx/www.netkiller.cn.error.log;

    error_page 497 https://$host$uri?$args;
	
    if ($scheme = http) {
	    return 301 https://$server_name$request_uri;
    }
    
    root   /opt/netkiller.cn/www.netkiller.cn;	
    location / {
        index  index.html;
    }

    location /api/ {
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://gateway.netkiller.cn:8080/;
        proxy_connect_timeout 120;
        proxy_send_timeout 120;
        proxy_read_timeout 120;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}				
		
		

35.11.16. nginx: [warn] the "listen ... http2" directive is deprecated, use the "http2" directive instead

下面方式已经被弃用

		
server
{
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	……
}		
		
		

解决方案

		
server
{
	listen 443 ssl;
	listen [::]:443 ssl;
	http2 on;
	……
}