1

I'm a newbie with HAProxy, and I want to use it to redirects HTTPS incoming requests to my HTTP backends servers.

I know, how it is possible to do it with Nginx, like this :

#SSL for all
server {
    listen 443 ssl ;
    server_name www.example.com;
    absolute_redirect off;
    proxy_redirect off;

    access_log /var/log/nginx/example.com-ssl-access.log;
    error_log /var/log/nginx/example.com-ssl-error.log;

    ssl_protocols TLSv1.2 TLSv1.1 TLSv1 ;
    ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; 
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; 


    location / {
        proxy_pass http://bo.example.com;
    }
}

But I don't know how I can do it with HAProxy ?

I have already tried several things. But each time I only had HTTPS to HTTPS redirects.

Can you help me ?

This is my current HAProxy configuration :

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 5s
    user haproxy
    group haproxy
    daemon

    tune.ssl.default-dh-param 2048

defaults

    log     global

    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http
    stats enable
    stats hide-version
    stats refresh 30s
    stats uri /hastats

frontend www-http
        # Frontend listen port - 80
    bind *:80
    #Mode de fonctionnement
    mode http

    reqadd X-Forwarded-Proto:\ http

    # Test URI to see if its a letsencrypt request
    acl letsencrypt-acl path_beg /.well-known/acme-challenge/
    use_backend letsencrypt-backend if letsencrypt-acl

    # Set the default backend
    default_backend www-backend
    # Enable send X-Forwarded-For header
    #option forwardfor
    #option httpchk GET /
    # log reqs http
    #option httplog

    # acl
    #acl prod_acl  hdr(host) prod.local

    #use_backend apache_backend_servers if prod acl


# Define frontend ssl
frontend www-ssl
        bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
        reqadd X-Forwarded-Proto:\ https
        default_backend www-backend


# define backend

backend www-backend
    mode http
    option httpchk
    option forwardfor except 127.0.0.1

    http-request add-header X-Forwarded-Proto https if { ssl_fc }
    
    redirect scheme http if { hdr(Host) -i example.com } { ssl_fc }
    balance roundrobin
    #Define the backend servers
    server  web1    XXX.XXX.XXX.101  check inter 3s port 80
    server  web2    XXX.XXX.XXX.102  check inter 3s port 80

backend letsencrypt-backend
    server letsencrypt 127.0.0.1:8080
4
  • 2
    ".... redirects HTTPS incoming requests to my HTTP backends servers ..." - given that the backend servers are at the backend and thus likely behind HAproxy and not directly reachable from the outside, you don't want to redirect. Redirection just instructs the client (browser) to directly access the given new URL, but the client cannot reach this new URL since it is in the backend. Instead you want to forward the request by functioning as a reverse proxy with TLS termination, which is also what you do with nginx. Oct 15, 2020 at 19:15
  • 1
    And when using the correct search terms haproxy reverse proxy tls termination you can easily find how it is done: How To Implement SSL Termination With HAProxy .... Oct 15, 2020 at 19:19
  • Okay, thank you , I will modify the title and follow your link.
    – outstore
    Oct 16, 2020 at 8:20
  • @SteffenUllrich : Thank you, now it's working great. In addition to your link, I used equally this : How To Secure HAProxy with Let's Encrypt on Ubuntu 14.04 . I'm on Debian 10, but it still works.
    – outstore
    Oct 16, 2020 at 15:17

1 Answer 1

0

I prepared a clean working sample, from which you can set up a clean configuration and add the functions you require. In general, what I teach people learning about different applications and topics is, that they should be able to understand the basic function of each line of configuration.

This can be achieved by reading the documentation on the topic and thinking logically.

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    user haproxy
    group haproxy
    daemon
    tune.ssl.default-dh-param 2048

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000

frontend www
    bind *:80
    bind *:443 ssl crt /etc/ssl/localcerts/apache-full.pem
    option forwardfor
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Forwarded-Proto http if !{ ssl_fc }

    acl letsencrypt-acl path_beg /.well-known/acme-challenge/
    use_backend letsencrypt-backend if letsencrypt-acl

    default_backend www-backend

backend www-backend
    option httpchk
    balance roundrobin
    server web1 10.0.0.1:80 check inter 3s
    server web2 10.0.0.2:80 check inter 3s

backend letsencrypt-backend
    server letsencrypt 127.0.0.1:8080

In the example above, the TLS is properly terminated and proxied as plain HTTP to the upstreams (servers).

The header "X-Forwarded-Proto" is set to "https", if the request came in via HTTPS. Otherwise it will be "http".

The layer 4 check to the upstreams will not require an additional port, because if a port is defined with the IP, it will automatically be used as check port, too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.