Can I use HAProxy to convert outgoing requests? - haproxy

I would like to use HAProxy like this:
client -> server
(example:8080) | (example:80)
|
HAProxy
Traffic going out from inside the server to `example:8080` change to `example:80`

Yes it can, you can use http-request set-header to update the headers sent by the client, such as the "Host" header. You can also define the backend server to listen on any port that you want.

Related

Using haproxy to forward or redirect a URL

I am looking to perform something quite simple.
Using haproxy I would like to forward any requests from the URL http://webmail.rutest.org or https://webmail.rutest.org to https://outlook.com/rutest.org
BASICALLY:
We currently own the domain rutest.org. What I intend to do is create a DNS "A" record for "webmail" IP address 24.103.122.18. This will then go to a FortiGate Router which has 2 port forwarding rules for 80 and 443 to an internal IP address 10.1.1.18. 10.1.1.18 will be the haproxy server. Once that request gets there, I want haproxy to say ok, you want http://webmail.rockefeller.edu or https://webmail.rockefeller.edu then send the user to https://outlook.com/rutest.org
The users browser should then reflect this URL redirection.
Can this be done? If so, what are the entries needed in the haproxy.cfg?
You can try the following, untested.
listen webmail
bind :80 v4v6
# here should be your certificates
bind :::443 v4v6 alpn h2,http/1.1 ssl crt /etc/ssl/haproxy/
http-request redirect location https://outlook.com/rutest.org if hdr(host) -i webmail.rockefeller.edu
The documentation: http-request redirect

HAProxy redirect port and mask url

I have a couple of webservers that are reachable directly through the following URL:
https://abcd.example.com:8445/desktop/container/landing.jsp?locale=en_US
https://wxyz.example.com:8445/desktop/container/landing.jsp?locale=en_US
I need to use HAProxy to loadbalance between the two and use the following URLs instead when hitting the frontend:
http://1234.example.com/desktop/container/landing.jsp?locale=en_US
or
https://1234.example.com:8445/desktop/container/landing.jsp?locale=en_US
So other requirements beside the two above:
If initial traffic is port 80, convert to port 8445
Mask the URL so that on the browser while it redirected to https and port to 8445, the host remains intact, like so: https://1234.example.com:8445/desktop/container/landing.jsp?locale=en_US
Here's my config so far:
frontend WebApp_frontend
mode http
bind 10.4.34.11:80
acl is80 dst_port 80
http-request set-uri https://%[req.hdr(Host)]:8445%[path]?%[query] if is80
default_backend WebApp-backend
backend WebApp_backend
description WebApp
balance roundrobin
mode http
server webserver1 10.2.89.222:8445 check inter 5s fall 3 rise 5 downinter 1m ssl verify none
server webserver2 10.4.89.223:8445 check inter 5s fall 3 rise 5 downinter 1m ssl verify none
The problem I'm facing right now is that when you access the frontend, HAProxy will redirect you to any of the webservers and force your client to hit the webserver directly instead of through the HAProxy. I need the connection to remain through the HAProxy.
If all your application is doing is redirecting to HTTPs then you should probably just handle that directly within HAProxy. You might want to also explore whether your application supports X-Forwarded-Proto and X-Forwarded-Host.
Another option is you can have HAProxy rewrite the redirects from the backend application to the hostname you choose. Using HAProxy 2.1 you would do something like this:
http-response replace-header location https?://[^:/]*(:?[0-9]+/.*) https://1234.example.com\1 if { status 301:302 }

How to get IP of backend selected?

I am using HAProxy with multiple backends and some ACLs to select a backend, I want my client (for testing purposes and etc) to know the ip of the backend that was selected.
For example, Client sends request to HAProxy which loadbalances between ip A and ip B. In the response header, I want the ip of A if A was selected by HAProxy and I want the ip of B if B was selected. I know of %[dst] but it returns the ip of the HAProxy server instead.
Right now I'm putting http-response set-header X-Forwarded-Host %[dst]:%[dst_port] in the frontend and it is returning the ip and port of the HAProxy
found the answer, its %si:%sp. cbonte.github.io/haproxy-dconv/1.7/configuration.html#8.2.4

haproxy: extract host and port from req.hdr(host)

I am using haproxy version 1.5.4.
req.hdr(host) provides host:port, ex: If I issue a request http://abc:9080, then req.hdr(Host) equals abc:8080, is there any way I can get only hostname or IP address, 1.1.1. if request is sent as http://1.1.1.1:9080
My use case is I want to use that IP/Host in redirecting to SSL port.
Your inputs appreciated.
With regards,
-N-

Transmission Torrent behind HAProxy - HTTP Response Header used as session identifier and stickiness token

I've been trying, and failing so far, to run Transmission behind HAProxy.
If I just add a new backend and route traffic as follows:
frontend http-in
bind *:80
reqadd X-Forwarded-Proto:\ http
acl host1 hdr_end(host) -i web.host1.host
use_backend apache_backend if host1
acl transmission_host hdr_end(host) -i transmission.host1.host
use_backend transmission_backend if transmission_host
Then I get a 409 conflict error stating I have an invalid session-id header. That's pretty obvious and expected since there's a proxy in the middle.
I thought of recompiling transmission to get rid of the check, but decided in the end to face the challenge of learning a bit more of HAProxy. What did I have in mind?
Client reaches HAProxy
HAProxy connects to transmission-daemon
Daemon replies with X-Transmission-Session-Id
HAProxy stores the Session-Id somehow and replaces Session-Id sent by the client with the one captured by HAProxy.
After a lot of Googling and playing with the settings, I got an almost working configuration:
frontend http-in
bind *:80
reqadd X-Forwarded-Proto:\ http
capture response header X-Transmission-Session-Id len 48
acl host1 hdr_end(host) -i web.host1.host
use_backend apache_backend if host1
acl transmission_host hdr_end(host) -i transmission.host1.host
use_backend transmission_backend if transmission_host
backend transmission_backend
mode http
http-request set-header X-Transmission-Session-Id %hs
server transmission-daemon transmission.intranet:9091
My configuration examples are summarized.
It works, sort of. I get a login prompt for transmission, but the page loads incredibly slow. I'm more than 10 minutes in and still don't have it fully loaded.
More pages go through this proxy: HTTP, HTTPS, TCP, some load balanced, some set as fail-overs. They all load normally and fast. If I connect directly to the transmission-daemon server, it loads fast as well.
I'll keep looking around.
Any ideas?
Thanks in advance!
3 years later,
from what I've seen in https://gist.github.com/yuezhu/93184b8d8d9f7d0ada0a186cbcda9273
you should capture request and response in frontend http-in,
I didn't dug much more, but the backend seems to need
stick-table type binary len 48 size 30k expire 30m
stick store-response hdr(X-Transmission-Session-Id)
stick on hdr(X-Transmission-Session-Id)
to work