Opened 10 years ago

Closed 9 years ago

Last modified 4 years ago

#629 closed defect (invalid)

Nginx as a reverse proxy will not pass headers that contain a period.

Reported by: Cameron Ortiz Owned by:
Priority: major Milestone:
Component: nginx-core Version: 1.6.x
Keywords: Cc:
uname -a: [root@cloud-server-01 ~]# uname -a
Linux cloud-server-01 2.6.32-431.29.2.el6.x86_64 #1 SMP Tue Sep 9 21:36:05 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: [root@cloud-server-01 ~]# nginx -V
nginx version: nginx/1.6.2
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_spdy_module --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

Description

When Nginx is configured as a reverse proxy it will not pass any http headers that have a name containing a period.

I was able to reproduce this issue by creating a very basic reverse proxy configuration in nginx to another server running apache:

[root@cloud-server-01 ~]# cat /etc/nginx/conf.d/headertest.conf
server {
	listen 166.78.134.122:80;
	location / {
		proxy_pass http://10.183.5.144;
	}
}

On the Apache server I created a small php script that would show the request headers:

[root@cloud-server-02 ~]# cat /var/www/html/index.php 

<?php
$headers = apache_request_headers();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}
?>

When I pass a header that has a period to the NginX server it does not get forwarded to the Apache server:

[ccortiz@ninja ~]$ curl -H 'test: this is a test' 166.78.134.122

Host: 10.183.5.144 <br />
Connection: close <br />
User-Agent: curl/7.32.0 <br />
Accept: */* <br />
test: this is a test <br />
Via: 1.1 537618-AUS2WWSG01.secops.rackspace.com 0A014411 <br />

[ccortiz@ninja ~]$ curl -H 'tes.t: this is a test' 166.78.134.122

Host: 10.183.5.144 <br />
Connection: close <br />
User-Agent: curl/7.32.0 <br />
Accept: */* <br />
Via: 1.1 537618-AUS2WWSG01.secops.rackspace.com 0A014411 <br />

I have attached a tcpdump that was ran on the nginx server. You can view this in wireshark to see that the header is coming into nginx but is not going out to the apache server.

Attachments (1)

tcpdump.pcap (4.6 KB ) - added by Cameron Ortiz 10 years ago.

Download all attachments as: .zip

Change History (6)

by Cameron Ortiz, 10 years ago

Attachment: tcpdump.pcap added

comment:1 by Valentin V. Bartenev, 10 years ago

Resolution: invalid
Status: newclosed

comment:2 by efge@…, 9 years ago

(I'm not the original submitter)

I'm asking for this to be reopened because the default behavior actually ignores headers which are valid. A period is a valid header field. Per RFC 2730 (HTTP 1.1 Message Syntax and Routing) (http://tools.ietf.org/html/rfc7230) we have:

  • 3.2: header-field = field-name ":" OWS field-value OWS
  • 3.2: field-name = token
  • 3.2.6: token = 1*tchar
  • 3.2.6: tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "(backquote)" / "|" / "~" / DIGIT / ALPHA
Last edited 9 years ago by efge@… (previous) (diff)

comment:3 by efge@…, 9 years ago

Resolution: invalid
Status: closedreopened

comment:4 by Maxim Dounin, 9 years ago

Resolution: invalid
Status: reopenedclosed

By default nginx ignores headers it considers invalid as per rules documented. The rules are composed based on what various standards define, what real browsers use, and the fact that other characters may be unsafe with various commonly used software, including nginx itself. Whether or not these headers match a grammar of a particular RFC is mostly irrelevant. The ignore_invalid_headers directive allows to control whether only headers matching the rules documented will be handled and passed to upstream servers by nginx, or any header will do.

There are no plans to change the default behaviour. If you disagree with the directive name - you may suggest renaming it. If you want to introduce some additional behaviour, e.g., to pass headers with dots, you may introduce an additional directive to do this, similar to underscores_in_headers. In either case please make it clear why the suggested change is needed. See Contributing Changes for some additional details.

comment:5 by Maxim Dounin, 4 years ago

See also #2184.

Note: See TracTickets for help on using tickets.