HTTP Proxy behavior for X-Forwarded-Host header - http

I have a question regarding how HTTP Proxies usually handle the "X-Forwarded-Host" header. Consider the following scenario where a client sends a HTTP request through a chain of proxies:
Client -> Proxy 1 (http://proxy1.com) -> Proxy 2 (http://proxy2.com) -> Server (http://server.com)
Proxy 1 sets the "X-Forwarded-Host" header to its own endpoint:
X-Forwarded-Host: proxy1.com
What behavior is expected from the second proxy? Does it replace the header and again use its own endpoint as the value (proxy2.com), or is it supposed to detect that a "X-Forwarded-Host" header is already present in the request and simply forward this header? Reading https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host:
The X-Forwarded-Host (XFH) header is a de-facto standard header for identifying the original host requested by the client in the Host HTTP request header.
I suspect it is the latter (simply forward the existing header), but I am not sure if this assumption is correct. Any help is appreciated.

Related

nginx ignore missing HTTP headers

Is there any way to tell nginx to ignore missing HTTP headers when proxying requests?
There is an existing proprietary HTTP Server sending requests without any header. The Server can not be configured. I need various endpoints from this server in a web application. Therefore I want to setup my nginx to proxy requests to this server. I have location configuration in my regular server.
location /api/ {
proxy_pass http://localhost:80/;
}
When calling corresponding URIs nginx complains:
upstream sent no valid HTTP/1.0 header while reading response header from upstream, client: 127.0.0.1, server: localhost, request: ....
Is there any way to tell nginx not to expect any headers, and just to forward the received payload?
Thanks for your help!
Kind regards,
Andreas
Edit: Ok, found server is using http 0.9, when calling curl directly to the server threw an error:
curl: (1) Received HTTP/0.9 when not allowed
Using the option --http0.9 got the desired result. (Which is received in a browser without further ado). Any chance to tell nginx to proxy to an http 0.9 server?
You can configure nginx to ignore missing headers by setting the proxy_ignore_headers directive to "X-Accel-Expires" and "Expires". This will tell nginx to ignore those specific headers and not expect them to be present when proxying requests.
You can add this to the location block in your nginx configuration:
proxy_ignore_headers X-Accel-Expires Expires;
Additionally, proxy_pass_request_headers off; could be used, this tells nginx to ignore all headers passed to the proxied server.
As for the payload, as long as the underlying protocol is HTTP, it should be fine, as the payload will be sent in the body of the HTTP request.
So your location block could look like this
location /api/ {
proxy_pass http://localhost:80/;
proxy_pass_request_headers off;
}
Please note that this is may not be recommended, as the missing headers may contain important information like authentication and should be handled correctly.

Difference between origin and x-forwarded-host http header

At work we use several websites with several virtual hosts.
I understand what a Virtual Host is, but I don't understand the difference between the Origin and X-forwarded-Host headers. (We use both of these headers at work.)
Examples from MDN:
X-forwarded-Host=X-Forwarded-Host: ==>X-Forwarded-Host: id42.example-cdn.com
Origin==Origin: "://" [ ":" ]==>Origin: https://developer.mozilla.org
From what I deduce from the above examples is that: X-forwarded-Host just contains the host and Origin contains the host plus the method and maybe the port.
Can someone told me if I'm wrong?
When a request is made to a website, the user-agent (browser) will add a Host header to the request. The value of this header will be domain name that the request is made to. This header can be used by the server to distinguish which website you are trying to visit, for instance when the same server hosts multiple websites.
If you are using a reverse proxy, the the Host header will contain the value of the reverse proxy itself. In order to know to the original host, the X-forwarded-Host can be used. This header contains what the proxy initially received as Host.
Example: If you make a GET request to https://stackoverflow.com, the Host (or after the proxy X-forwarded-Host) header will always have the value stackoverflow.com.
The Origin header is not related to this. This header tells you from which site the request is made.
For instance, if you have a <form> on example.com that makes a POST request to stackoverflow.com, the Host will be stackoverflow.com (the domain the request is sent to), while the Origin will have the value https://example.com.
For a demonstration you can visit this link: https://jsfiddle.net/parcqhn4/
If you open the "Network" tab in your developer tools and hit the "Submit" button, you can see that the Host header contains the value example.com (which is in the action of the <form>) while the Origin contains the value https://fiddle.jshell.net (which is container that the Fiddle runs in).

How to Remove Client Headers in Nginx before passing request to upstream server?

The Upstream server is wowza , which does not accept the custom headers if I don't enable them on application level.
Nginx is working as a proxy server, from the browser I want to send few custom headers which should be received and logged by Nginx Proxy but before forwarding request to upstream server those headers should be removed from the request.
So upstream server never come to know that there where any custom headers.
I tried proxy_hide_header as well as proxy_set_header "<header>" "" , but seems like they apply to response headers not the request headers.
And even if I accept to enable the headers on wowza, then again I am not able to find a way to enable headers at server level for all application. Currenlty I have to add headers to each newly created application which is not feasible for me to do.
Any help would be appreciated.
The proxy_set_header HEADER "" does exactly what you expect. See https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header.
If the value of a header field is an empty string then this field will not be passed to a proxied server:
proxy_set_header Accept-Encoding "";
I have just confirmed this is working as documented, I used Nginx v1.12.

Hide a client request header with a Nginx reverse proxy server

I have a Nginx websocket reverse proxy and I would like to hide a HTTP header from the client request.
proxy_hide_header hides the server response headers and can't be used for hiding client request headers.
I would like to do that because the websocket server behind nginx doesn't work well with the websocket extension "permessage-deflate" so I would like to remove the Sec-WebSocket-Extensions header from client requests.
You can set a header value to void and Nginx will drop it :
proxy_set_header Sec-WebSocket-Extensions "";
The official documentation explains the correct way to remove a client request header:
If the value of a header field is an empty string then this field will not be passed to a proxied server:
proxy_set_header Accept-Encoding "";
In case that wasn't clear, this is more than just a workaround to mask the value; the entire header will be dropped.

Do HTTP proxy servers modify request packets?

Is any request header added or modified to the HTTP request before forwarding to the server by a proxy server?
If so, are the changes done to the same packets, or are the contents used to create new request packets with the modifications?
There are a few different types of proxy servers. Because you've mentioned request headers, I'm going to assume that you're talking about HTTP proxy servers, which forward HTTP requests, not packets.
NOTE: In the special case of HTTPS requests (TLS/SSL via CONNECT), proxy servers will just forward the content of the TCP packets (and are unable to inspect the packets unless acting as a man-in-the-middle proxy).
Of course it depends on the proxy software and its configuration, but HTTP proxies are expected to follow the W3C Guidelines for Web Content Transformation Proxies, which states many things, but most relevantly:
Other than to convert between HEAD and GET proxies must not alter request methods.
If the request contains a Cache-Control: no-transform directive, proxies must not alter the request other than to comply with transparent HTTP behavior defined in RFC 2616 HTTP sections section 14.9.5 and section 13.5.2 and to add header fields as described in 4.1.6 Additional HTTP Header Fields.
Other than the modifications required by RFC 2616 HTTP proxies should not modify the values of header fields other than the User-Agent, Accept, Accept-Charset, Accept-Encoding, and Accept-Language header fields and must not delete header fields.
Proxies should add the IP address of the initiator of the request to the end of a comma separated list in an X-Forwarded-For HTTP header field.
Proxies must (in accordance with RFC 2616) include a Via HTTP header field.
In summary, you can generally expect these HTTP headers to be changed/added by a standards-compliant proxy:
User-Agent
Accept
Accept-Charset
Accept-Encoding
Accept-Language
X-Forwarded-For
Via

Resources