BlocNotes

Notepad of a tinker, maker, hacker or whatever you call it :)

Configure HAProxy in reverse proxy with HTTP authentication

I am using a lot of web services on a server, and was bored to remember all addresses and change my firewall rules each time. So I use HAProxy to redirect all incoming http traffic to the right server/port by checking the requested URL.

Moreover, I configured it as an SSL endpoint, so every communication between a browser and HAProxy is encrypted, even if the service I am using is to able to do it.
The other pro of this solution is to be able to use a basic HTTP authentication whenever I want to restrict access to some services.

So I lost some time on the configuration, especially on one parameter that I never found on the internet, hope this can help other people.
It is not a full guide on how to configure HAProxy, lot of tutorials are on the internet, but it focuses on the essential parts.

HAProxy configuration file, located at /etc/haproxy/haproxy.cfg, is separated in 5 categories:

  1. Global
  2. Defaults
  3. Frontend
  4. Backend & userlist
  5. Proxy

1. Global

From the documentation:

Parameters in the “global” section are process-wide and often OS-specific. They are generally set once for all and do not need being changed once correct.”

So, the only one I put there is the following ssl-server-verify none.
It says that HAProxy will not complain if it has to connect to a server with untrusted certificate. Useful for self signed certificates, and can be placed in defaults section or each frontend.

2. Defaults

Set the parameters for all following frontend, until next defaults section.

3. Frontend

It is the entry point for the browser, you can set here how the incoming connection should be handled.
You can have as much endpoint as you want, unless they do not listen on same port.

frontend https
    bind :443 ssl crt /path/to/sslKey/cert.pem
    option forwardfor
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Forwarded-Host %[req.hdr(Host)]
    use_backend lighttpds if { path_beg /testhttps }
    use_backend lighttpdAuth if { path_beg /auth }
    use_backend headphones if { path_beg /music }
    use_backend lighttpdAuth if { path_beg /liste }
    default_backend lighttpd

Bind keyword will tell HAProxy to listen port 443, and the path to the SSL certificate.

The four following parameters are to tell the server that the connection goes through a proxy, send some informations on the client and the type of connection.
The parameter I never found over the web is http-request set-header X-Forwarded-Host %[req.hdr(Host)], which allow the service to write the host address instead of 127.0.0.1, if it is on same host.

Then is declared the backend to use (=services) on which conditions, and the default

4. Backend & userlist

Then comes the services you want to use

backend headphones
    server headphones localhost:85 ssl
    acl AuthOkay_UsersAuth http_auth(UsersAuth)
    http-request auth realm UserAuth if !AuthOkay_UsersAuth

The name just after “backend” keyword must be the one defined in the fronted list.
Then you can declare as much servers as you want, because HAProxy is also used as a load balancer, but in this case we only use one. Keyword ssl is not mandatory, it specifies that HAProxy must establish a secured connection.
Then the two last lines are for the basic HTTP authentication, in combination with the two following lines:

userlist UsersAuth
user userName1 insecure-password passwordForUserName1

Another thing to do is to tell each service that we access it through a prefix, it allow them to add it to the URL (ex: http://domainName/headphone instead of http://domainName/)
Each service has a different configuration scheme, some example

  • Node-Red : settings.js – httpRoot
  • Headphones – config.ini – http_root (For all services based on CherryPy)
  • KiwiIRC – config.js – conf.http_base_path
  • GateOne – 10.server.conf – url_prefix

5. Proxy

Use HAPRoxy as... a proxy, see HAProxy documentation for this stuff.

I hope this helps, because a lot of documentation about reverse proxy is based on Nginx, not HAProxy.