core: Too many headers http 400 Error while using revers proxies

The problem

Environment

  • Home Assistant Core release with the issue: 115
  • Last working Home Assistant Core release (if known): 114
  • Operating environment (OS/Container/Supervised/Core): Container
  • Integration causing this issue: pull request 38696
  • Link to integration documentation on our website: PR 38696

Problem-relevant configuration.yaml

  trusted_proxies:
    - 192.168.7.1

Traceback/Error logs

2020-09-21 11:42:47 ERROR (MainThread) [homeassistant.components.http.forwarded] Too many headers for X-Forwarded-For: ['2607:fb90:6c82:27ae:994f:c5b0:3564:2d32', '108.162.216.49']
2020-09-21 11:42:47 ERROR (MainThread) [homeassistant.components.http.forwarded] Too many headers for X-Forwarded-For: ['2607:fb90:6c82:27ae:994f:c5b0:3564:2d32', '162.158.74.124']
2020-09-21 11:42:49 ERROR (MainThread) [homeassistant.components.http.forwarded] Too many headers for X-Forwarded-For: ['2607:fb90:6c82:27ae:994f:c5b0:3564:2d32', '162.158.75.187']

Additional information

In the past I’ve never had to provide the proxy addresses of Cloudflare as my Firewall only allows those IPs to come in. As Cloudflare does everything in subnet IPs do I need to put the full subnet into my configuration.yaml? Will it accept standard IP subneting for the reverse proxy addresses? i.e. 0.0.0.0/24

Thank you for your help with this item.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 27 (4 by maintainers)

Most upvoted comments

Sorry, I should have looked it up, instead of speaking from top of my mind (which was incorrect).

http-request replace-value x-forwarded-for ^ "%[hdr(x-forwarded-for)], %[src]"

☝️ That is another solution that might put you into a workable direction.

From HAProxy documentation:

Since HAProxy works in reverse-proxy mode, the servers see its IP address as
their client address. This is sometimes annoying when the client's IP address
is expected in server logs. To solve this problem, the well-known HTTP header
"X-Forwarded-For" may be added by HAProxy to all requests sent to the server.
This header contains a value representing the client's IP address. Since this
header is always appended at the end of the existing header list, the server
must be configured to always use the last occurrence of this header only. See
the server's manual to find how to enable use of this standard header. Note
that only the last occurrence of the header must be used, since it is really
possible that the client has already brought one.

It really looks that haproxy send this header two times (I made little PHP script, it looked ok, but I am not sure if it will show duplicate headers or not) So I made this workaround in haproxy config

option forwardfor header cf-forwarded-for

on my HASS backend, because I have option forwardfor in default and it cant be “turned off” via no option setting.

Hope this will help somebody

@frenck While it’s possible to work around that issue, I still think the Home Assistant webserver (and many other webserver implementations out there) fails to follow the de-facto standard for comma separated HTTP header values. For these headers both representations should be equivalent:

x-forwarded-for: A,B

<===>

x-forwarded-for: A
x-forwarded-for: B

From what I read, HA chooses to print this message to avoid ambivalence (as there seem to be problems in the past where HA used the wrong header). IMHO there shouldn’t be “wrong” values as this header contains a chain. If the request goes through multipe proxies, the x-forwarded-for will either get appended to the existing header or a new x-forwarded-for is added. In either way, the first value should be the IP address of the actual client.

There is an informative comment in the HAProxy repo: https://github.com/haproxy/haproxy/issues/44#issuecomment-472611751

The “best” workaround is discussed in the HAProxy forums: https://discourse.haproxy.org/t/appending-to-the-xff-header-does-not-work-as-expected/6415/2

This comment is particuarily interesting:

Be careful with this. By appending a value to an existing header instead of adding a new header, you’re giving the client all the keys to manipulate its contents and format, allowing it to be unparsable by the last server in the chain, effectively opening a security issue. While originally the extra header used to be a technical limitation, it’s now a reliability feature. If your server is having difficulties parsing header lists, it should be fixed instead of hacking on a header without prior checking that its contents will not cause trouble.

I really think this issue should be opened again.

So in my case I have 2 frontends in HA Proxy for HomeAssistant. One is for internal usage and the other for external. I turned off the x-forwarded-for on the external HA Proxy and now I’m cooking with gas. Thank you @frenck for the explanation.

@mcarbonneaux Please read my comment above. HAProxy is NOT the problem here. It’s the HASSIO webserver not following the HTTP standard. The devs just seem ignorant about this…

pfsense haproxy hass

I don’t really understand these things, but I finally figured it out! Again, had HAProxy reverse proxying everything just fine for some time. Then, several months ago - Home Assistant broke externally with the Too many headers error throwing up Cloudflare IPs and random LTE ones.

Finally figured it out, and here is the picture of my new action on my backend. I had to do it this way, because I use 2 frontends only, http & https with https having checked the “Use “forwardfor” option” box.

This was after trying multiple edits of copying and pasting what frenck wrote, and other threads all over. Hope this helps someone.