alibaba / tengine

A distribution of Nginx with some advanced features
https://tengine.taobao.org
BSD 2-Clause "Simplified" License
12.83k stars 2.52k forks source link

error_page #467

Closed zysyl closed 10 years ago

zysyl commented 10 years ago

Hi. i want create custom error_page for blocked some ua. in "server" i create if ($http_user_agent ~* "BOT/0.1") {return 505;} error_page 505 =403 /block.html; location = /block.html { root "/etc/nginx/errorpages/"; allow all; } but it return default page 403. for example error_page 502 503 504 =429 /50x.html; location /50x.html { root "/etc/nginx/errorpages/"; allow all; } return custom page

chobits commented 10 years ago

Thanks for your report.

Another configure for reproducing this problem:

server {
    root html;

    listen  8080;

    if ($http_x ~* "bar") { return 505; }
    if ($arg_x ~* "bar")  { return 505; }

    error_page 505 =403 /505;

    location = /505 {
        return 512 "505 PAGE\n";
    }
}

Run curl localhost/?x=bar, get "505 PAGE" with status code 403. --> Right Run curl localhost/ -H 'x: bar', get default 403 page. --> Wrong

chobits commented 10 years ago

@zysyl Can you give us the output information of command sbin/nginx -V? It will help us debug.

zysyl commented 10 years ago

Tengine version: Tengine/2.0.0 (nginx/1.4.4) TLS SNI support enabled configure arguments: --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-pcre-jit --with-debug --with-file-aio --with-http_addition_module --with-http_dav_module --with-http_flv_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_mp4_module --with-http_perl_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-ipv6 --with-mail --with-mail_ssl_module --with-syslog --with-http_upstream_check_module --add-module=/build/buildd/tengine-2.0.0/debian/modules/headers-more-nginx-module --add-module=/build/buildd/tengine-2.0.0/debian/modules/ngx_http_auth_pam_module --add-module=/build/buildd/tengine-2.0.0/debian/modules/ngx_cache_purge --add-module=/build/buildd/tengine-2.0.0/debian/modules/nginx-dav-ext-module --add-module=/build/buildd/tengine-2.0.0/debian/modules/ngx_devel_kit --add-module=/build/buildd/tengine-2.0.0/debian/modules/echo-nginx-module --add-module=/build/buildd/tengine-2.0.0/debian/modules/nginx-push-stream-module --add-module=/build/buildd/tengine-2.0.0/debian/modules/lua-nginx-module --add-module=/build/buildd/tengine-2.0.0/debian/modules/nginx-upload-module --add-module=/build/buildd/tengine-2.0.0/debian/modules/nginx-upload-progress-module --add-module=/build/buildd/tengine-2.0.0/debian/modules/nginx-upstream-fair --add-module=/build/buildd/tengine-2.0.0/debian/modules/ngx_http_pinba_module --add-module=/build/buildd/tengine-2.0.0/debian/modules/ngx_http_substitutions_filter_module --add-module=/build/buildd/tengine-2.0.0/debian/modules/nginx-rtmp-module --add-module=/build/buildd/tengine-2.0.0/debian/modules/nginx-x-rid-header --with-ld-opt=-lossp-uuid loaded modules: ngx_core_module (static) ngx_errlog_module (static) ngx_conf_module (static) ngx_dso_module (static) ngx_rtmp_module (static) ngx_rtmp_core_module (static) ngx_rtmp_cmd_module (static) ngx_rtmp_codec_module (static) ngx_rtmp_access_module (static) ngx_rtmp_record_module (static) ngx_rtmp_live_module (static) ngx_rtmp_play_module (static) ngx_rtmp_flv_module (static) ngx_rtmp_mp4_module (static) ngx_rtmp_netcall_module (static) ngx_rtmp_relay_module (static) ngx_rtmp_exec_module (static) ngx_rtmp_auto_push_module (static) ngx_rtmp_notify_module (static) ngx_rtmp_log_module (static) ngx_rtmp_limit_module (static) ngx_rtmp_hls_module (static) ngx_rtmp_dash_module (static) ngx_syslog_module (static) ngx_events_module (static) ngx_event_core_module (static) ngx_epoll_module (static) ngx_procs_module (static) ngx_proc_core_module (static) ngx_openssl_module (static) ngx_regex_module (static) ngx_http_module (static) ngx_http_core_module (static) ngx_http_log_module (static) ngx_http_upstream_module (static) ngx_http_static_module (static) ngx_http_gzip_static_module (static) ngx_http_dav_module (static) ngx_http_autoindex_module (static) ngx_http_index_module (static) ngx_http_random_index_module (static) ngx_http_auth_basic_module (static) ngx_http_access_module (static) ngx_http_limit_conn_module (static) ngx_http_limit_req_module (static) ngx_http_realip_module (static) ngx_http_geo_module (static) ngx_http_geoip_module (static) ngx_http_map_module (static) ngx_http_split_clients_module (static) ngx_http_referer_module (static) ngx_http_rewrite_module (static) ngx_http_ssl_module (static) ngx_http_proxy_module (static) ngx_http_fastcgi_module (static) ngx_http_uwsgi_module (static) ngx_http_scgi_module (static) ngx_http_perl_module (static) ngx_http_memcached_module (static) ngx_http_empty_gif_module (static) ngx_http_browser_module (static) ngx_http_user_agent_module (static) ngx_http_secure_link_module (static) ngx_http_flv_module (static) ngx_http_mp4_module (static) ngx_http_upstream_ip_hash_module (static) ngx_http_upstream_consistent_hash_module (static) ngx_http_upstream_check_module (static) ngx_http_upstream_least_conn_module (static) ngx_http_upstream_keepalive_module (static) ngx_http_stub_status_module (static) ngx_http_auth_pam_module (static) ngx_http_cache_purge_module (static) ngx_http_dav_ext_module (static) ndk_http_module (static) ngx_http_push_stream_module (static) ngx_http_upload_module (static) ngx_http_upstream_fair_module (static) ngx_http_pinba_module (static) ngx_rtmp_stat_module (static) ngx_rtmp_control_module (static) ngx_x_rid_header_module (static) ngx_http_write_filter_module (static) ngx_http_header_filter_module (static) ngx_http_chunked_filter_module (static) ngx_http_range_header_filter_module (static) ngx_http_gzip_filter_module (static) ngx_http_postpone_filter_module (static) ngx_http_ssi_filter_module (static) ngx_http_charset_filter_module (static) ngx_http_xslt_filter_module (static) ngx_http_image_filter_module (static) ngx_http_sub_filter_module (static) ngx_http_addition_filter_module (static) ngx_http_userid_filter_module (static) ngx_http_footer_filter_module (static) ngx_http_trim_filter_module (static) ngx_http_uploadprogress_module (static) ngx_http_headers_filter_module (static) ngx_http_upstream_session_sticky_module (static) ngx_http_headers_more_filter_module (static) ngx_http_echo_module (static) ngx_http_lua_module (static) ngx_http_subs_filter_module (static) ngx_http_copy_filter_module (static) ngx_http_range_body_filter_module (static) ngx_http_not_modified_filter_module (static) ngx_mail_module (static) ngx_mail_core_module (static) ngx_mail_ssl_module (static) ngx_mail_pop3_module (static) ngx_mail_imap_module (static) ngx_mail_smtp_module (static) ngx_mail_auth_http_module (static) ngx_mail_proxy_module (static)

chobits commented 10 years ago

hi @zysyl , It is not a bug. I tested nginx-1.7.2 and tengine-2.0.3. They does the same. I will explain why it is not a bug.

With your nginx config as following:

if ($http_user_agent ~* "BOT/0.1") {return 505;}    <<< (1)
error_page 505 =403 /block.html;                    <<< (2)
location = /block.html {
    root "/etc/nginx/errorpages/";
    allow all;
}
  1. (1) request with 'User-Agent: BOT/0.1' header comes in, it runs "return 505".
  2. (2) error_page directive overwrite 505 to 403 and redirect uri to "/block.html", then nginx does internal redirect to "/block.html" with err_status=403. Note that this internal redirect will rerun all http handlers
  3. (1) It reruns "return 505". Because 505 has been overwritten to 403 in step 2, it runs "return 403" actually. Then default 403 error page will be sent to client.


If you want to block "User-Agent: BOT/0.1" with "/block.html" page, you can use the following config. Note that named location (@block) will be matched directly without reruning all http handlers.

 if ($http_user_agent ~* "BOT/0.1") {return 505;}
 error_page 505 =403 @block;
 location @block {
    rewrite .* /block.html break;
    root "/etc/nginx/errorpages/";
 }


BTW, with the following config, why it gets "/block.html" page to request "/?x=bar".

if ($arg_x ~* "bar") {return 505;}        <<< (1)    
error_page 505 =403 /block.html;          <<< (2)
location = /block.html {
    root "/etc/nginx/errorpages/";
    allow all;
}

Note that error_page directive redirects uri to "/block.html", which also clears arguments in request. When it reruns (1), $arg_x ~* "BOT/0.1" is false. Then it matches "location = /block.html" and returns "/block.html" page.

zysyl commented 10 years ago

tnx for explain