Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CONNECT method: too strict checking of Host header #1159

Closed
bzed opened this issue Mar 3, 2021 · 4 comments
Closed

CONNECT method: too strict checking of Host header #1159

bzed opened this issue Mar 3, 2021 · 4 comments
Labels
status: works as designed This issue stems from a misunderstanding of how HAProxy is supposed to work.

Comments

@bzed
Copy link

bzed commented Mar 3, 2021

Detailed description of the problem

Since ~ 2.2 haproxy shows a very strict checking of the Host header for the CONNECT method:

[03/Mar/2021:09:58:01.361] frontend squid (#2): invalid request
  backend <NONE> (#-1), server <NONE> (#-1), event #0, src 127.0.0.1:39074
  buffer starts at 0 (including 0 out), 16318 free,
  len 66, wraps at 16384, error at position 46
  H1 connection flags 0x00000000, H1 stream flags 0x00000012
  H1 msg state MSG_HDR_L2_LWS(24), H1 msg flags 0x00001410
  H1 chunk len 0 bytes, H1 body len 0 bytes :

  00000  CONNECT www.googleapis.com:443 HTTP/1.1\n
  00040  Host: www.googleapis.com\n
  00065  \n

Using

CONNECT www.googleapis.com:443 HTTP/1.1
Host: www.googleapis.com:443

works well as before.

Expected behavior

While I think that a strict Host/Connect string checkign makes sense, it is also common not to have the standard https port in the Host header. This breaks the proxy handling of current java and python3 versions for example. The only client I was able to find that actually sends the port number by default was curl.

Also I'd at least expect a proper log message in the http-log instead of receiving a 400 error without log message at all - the error is shown in show errors only.

Steps to reproduce the behavior

  1. install squid or just let some other tool listen on a port
  2. haproxy config:
frontend squid
  bind 127.0.0.1:3128 
  mode http
  default_backend squid-backend

backend squid-backend
  balance roundrobin
  mode http
  server squid 127.0.0.1:12345
  1. send a connect request:
% nc localhost 3128
CONNECT www.googleapis.com:443 HTTP/1.1
Host: www.googleapis.com

this one works:

% nc localhost 3128
CONNECT www.googleapis.com:443 HTTP/1.1
Host: www.googleapis.com:443

Do you have any idea what may have caused this?
Wild guess: htx or some security fix to do a better check on Host headers for proxied connections.

Do you have an idea how to solve the issue?

I've tried to do a workaround by rewriting the Host header - doesn't work.

What is your configuration?

See above.

Output of haproxy -vv and uname -a

HA-Proxy version 2.2.9-1 2021/02/06 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2025.
Known bugs: http://www.haproxy.org/bugs/bugs-2.2.9.html
Running on: Linux 5.10.0-3-amd64 #1 SMP Debian 5.10.13-1 (2021-02-06) x86_64
Build options :
  TARGET  = linux-glibc
  CPU     = generic
  CC      = gcc
  CFLAGS  = -O2 -g -O2 -ffile-prefix-map=/build/haproxy-KCirew/haproxy-2.2.9=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wall -Wextra -Wdeclaration-after-statement -fwrapv -Wno-address-of-packed-member -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wno-stringop-overflow -Wno-cast-function-type -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference
  OPTIONS = USE_PCRE2=1 USE_PCRE2_JIT=1 USE_OPENSSL=1 USE_LUA=1 USE_ZLIB=1 USE_SYSTEMD=1
  DEBUG   = 

Feature list : +EPOLL -KQUEUE +NETFILTER -PCRE -PCRE_JIT +PCRE2 +PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED +BACKTRACE -STATIC_PCRE -STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT +CRYPT_H +GETADDRINFO +OPENSSL +LUA +FUTEX +ACCEPT4 -CLOSEFROM +ZLIB -SLZ +CPU_AFFINITY +TFO +NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL +SYSTEMD -OBSOLETE_LINKER +PRCTL +THREAD_DUMP -EVPORTS

Default settings :
  bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_THREADS=64, default=8).
Built with OpenSSL version : OpenSSL 1.1.1i  8 Dec 2020
Running on OpenSSL version : OpenSSL 1.1.1j  16 Feb 2021
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with Lua version : Lua 5.3.3
Built with network namespace support.
Built with zlib version : 1.2.11
Running on zlib version : 1.2.11
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE2 version : 10.36 2020-12-04
PCRE2 library supports JIT : yes
Encrypted password support via crypt(3): yes
Built with gcc compiler version 10.2.1 20210110
Built with the Prometheus exporter as a service

Available polling systems :
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
            fcgi : mode=HTTP       side=BE        mux=FCGI
       <default> : mode=HTTP       side=FE|BE     mux=H1
              h2 : mode=HTTP       side=FE|BE     mux=H2
       <default> : mode=TCP        side=FE|BE     mux=PASS

Available services : prometheus-exporter
Available filters :
	[SPOE] spoe
	[COMP] compression
	[TRACE] trace
	[CACHE] cache
	[FCGI] fcgi-app


Linux hostname 5.10.0-3-amd64 #1 SMP Debian 5.10.13-1 (2021-02-06) x86_64 GNU/Linux

Debian testing/unstable, also happens with the backport to buster.


If HAProxy crashed: Last outputs and backtraces

no crash

Additional information (if helpful)

Same behaviour with haproxy 2.3.5 from Debian/experimental.

@bzed bzed added status: needs-triage This issue needs to be triaged. type: bug This issue describes a bug. labels Mar 3, 2021
@lukastribus lukastribus added status: works as designed This issue stems from a misunderstanding of how HAProxy is supposed to work. and removed status: needs-triage This issue needs to be triaged. type: bug This issue describes a bug. labels Mar 3, 2021
@lukastribus
Copy link
Member

RFC7231 #4.3.6:

A client sending a CONNECT request MUST send the authority form of
request-target (Section 5.3 of [RFC7230]); i.e., the request-target consists
of only the host name and port number of the tunnel destination, separated
by a colon. For example,

CONNECT server.example.com:80 HTTP/1.1
Host: server.example.com:80

Haproxy enforces this. You can disable the check with accept-invalid-http-request.

Also I'd at least expect a proper log message in the http-log instead of receiving a 400 error without log message at all - the error is shown in show errors only.

I disagree, this is exactly what show errors is for.

@TimWolla
Copy link
Member

TimWolla commented Mar 3, 2021

Haproxy enforces this.

Technically the RFC says nothing about the host header, but only about the request-target (this is the thing between CONNECT and HTTP). What HAProxy however enforces is that the authority within the request-target matches the host header. So we are rather talking about RFC 7230#5.4 here:

If the target URI includes an authority component, then a
client MUST send a field-value for Host that is identical to that
authority component, excluding any userinfo subcomponent and its "@"
delimiter (Section 2.7.1).

@TimWolla
Copy link
Member

TimWolla commented Mar 3, 2021

Relevant commit is this one: 531b83e

@bzed
Copy link
Author

bzed commented Mar 3, 2021

Thanks a lot for the explanation and sorry for not spotting that in the changelog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: works as designed This issue stems from a misunderstanding of how HAProxy is supposed to work.
Projects
None yet
Development

No branches or pull requests

3 participants