Reputation: 21
I have a web server (actually it's a CF environment, but that doesn't matter much) running behind a haproxy version 1.5-dev19 2013/06/17 that accepts requests only for a certain internal domain, let's call it: internal-address. Meaning, that HTTP requests only work if the host header is suffixed by internal-address, (like: Host: login.internal-address).
Users from the WAN can access this web server by connecting to an external address which has ip forwarding to the internal server. But when a user accesses the external address, the Host header is suffixed with external-address, and the web server behind the haproxy rejects the request.
I added reqirep entries in to haproxy configuration:
global
log 127.0.0.1 syslog info
daemon
user vcap
group vcap
maxconn 64000
spread-checks 4
defaults
log global
timeout connect 30000ms
timeout client 300000ms
timeout server 300000ms
frontend http-in
mode http
bind :80
option httplog
option forwardfor
reqadd X-Forwarded-Proto:\ http
default_backend http-routers
frontend https-in
mode http
bind :443 ssl crt /var/vcap/jobs/haproxy/config/cert.pem
option httplog
option forwardfor
option http-server-close
reqadd X-Forwarded-Proto:\ https
default_backend http-routers
frontend ssl-in
mode tcp
bind :4443 ssl crt /var/vcap/jobs/haproxy/config/cert.pem
default_backend tcp-routers
backend http-routers
mode http
balance roundrobin
reqirep ^Host:\ uaa.external-address Host:\ uaa.internal-address
reqirep ^Host:\ api.external-address Host:\ api.internal-address
reqirep ^Host:\ external-address:4443 Host:\ loggregator.internal-address:4443
server node0 172.20.0.1:8888 check inter 1000
backend tcp-routers
mode tcp
balance roundrobin
reqirep ^Host:\ external-address:4443 Host:\ loggregator.internal-address:4443
server node0 172.20.0.1:8888 check inter 1000
And every request sent to uaa.external-address or api.external-address is indeed changed and the web server behind the haproxy receives the request as if the Host header is suffixed with internal-address. But the 3rd rule:
reqirep ^Host:\ external-address:4443 Host:\ loggregator.internal-address:4443
Doesn't work :( The web server's access log shows the Host header is sent from external-address:4443 , which implies that the haproxy didn't match the Host header correctly and then the web server rejects the request. The request issued by the client is:
WEBSOCKET REQUEST: [2014-10-01T10:25:07+03:00]
GET /tail/?app=029a1269-67fe-46e2-85f7-e1b0b5d34193 HTTP/1.1
Host: wss://external-address:4443
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: [HIDDEN]
Origin: http://localhost
Authorization: [PRIVATE DATA HIDDEN]
Does anyone know what's wrong with the rule?
EDIT:
I deleted the rules from the backend and created more generic rules in the frontend, and it still doesn't work for websockets:
frontend https-in
mode http
bind :443 ssl crt /var/vcap/jobs/haproxy/config/cert.pem
option httplog
option forwardfor
option http-server-close
reqadd X-Forwarded-Proto:\ https
default_backend http-routers
reqirep ^Host:\ (.*).external-address(.*) Host:\ \1.internal-address\2
frontend ssl-in
mode tcp
bind :4443 ssl crt /var/vcap/jobs/haproxy/config/cert.pem
default_backend tcp-routers
reqirep ^Host:\ (.*).external-address(.*) Host:\ \1.internal-address\2
Thanks in advance.
Upvotes: 2
Views: 10041
Reputation: 1759
Which version of HAProxy are you running? If 1.4, please add 'option http-server-close' into your defaults section.
By default, 1.4 is in tunnel mode, which let HAProxy analyse the first request and response and transfer subsequent requests and responses as payload.
In 1.5, it should work out of the box. HAProxy uses a new mode "http-keep-alive" which allows HAProxy to analyse all the content all the time.
Baptiste
Upvotes: 1