Hi,

Thanks for your answer ! In fact I already had a look at this example :-)

So here is my first use case : I need to setup a reverse proxy in front of 
WordPress containers running on the same host.
Of course, each of them is running on his own port and it's not 80.

At "back1.domain.local:8000" I have a working WP instance, without any extra 
post-installation setup.
I can perfectly reach and use "http://back1.domain.local:8000/wp-admin/";

Now let's put HAProxy in front of this :

---

global
        #log 127.0.0.1:514 local2
        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 30s
        user haproxy
        group haproxy
        daemon
        debug

        # Default SSL material locations
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private

        # See: 
https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
        ssl-default-bind-ciphers 
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
        ssl-default-bind-ciphersuites 
TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
        ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

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


#
# FE
#

frontend FE-http
    bind *:80

    #DDoS
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 20 }

    http-request add-header X-Forwarded-Proto http
    redirect scheme https if !{ ssl_fc }

frontend FE-https
    bind *:443 ssl crt  /etc/ssl/certs/www.pem

    log global
    option httplog
    option forwardfor
    option http-server-close

    #WP
    http-request add-header X-Forwarded-Proto https if { ssl_fc }
    http-request redirect scheme https unless { ssl_fc }

    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }

    # BE selection

    # [front1.domain.local]
    use_backend back1 if { hdr(host) -i front1.domain.local }

    # [front2.domain.local]
    use_backend back2 if { hdr(host) -i front2.domain.local }

#
# BE
#

# [ front1.domain.local]
backend back1
    #TODO : optional parameters
    http-response set-header X-Server %s
    balance leastconn
    server localhost 127.0.0.1:8000 check fall 3 rise 5 inter 5000

# [ front2.domain.local]
backend back2
    #TODO : optional parameters
    http-response set-header X-Server %s
    balance leastconn
    server localhost 127.0.0.1:8330 check fall 3 rise 5 inter 5000

---

If I try to reach "https://front1.domain.local/wp-admin/"; it is not working 
correctly.
I have to go through redirections and land at 
"https://back1.domain.local:8000/wp-login.php";, which is not usable.

---

00000000:FE-https.accept(0009)=000f from [192.168.56.1:1446] ALPN=<none>
00000000:FE-https.clireq[000f:ffffffff]: GET /wp-admin/ HTTP/1.1
00000000:FE-https.clihdr[000f:ffffffff]: host: front1.domain.local
00000000:FE-https.clihdr[000f:ffffffff]: user-agent: Mozilla/5.0 (Windows NT 
10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0
00000000:FE-https.clihdr[000f:ffffffff]: accept: 
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
00000000:FE-https.clihdr[000f:ffffffff]: accept-language: en-US,en;q=0.5
00000000:FE-https.clihdr[000f:ffffffff]: accept-encoding: gzip, deflate, br
00000000:FE-https.clihdr[000f:ffffffff]: cookie: 
wordpress_sec_0ca336a14ef7b2941859a7208fbdc453=back1%7C1613847137%7CX9zaOUs8JygWJfwMWFapApMEOx0O0ShNokjG0C9c77G%7C15d123459323feffd2a67a61f86b02e0e70dbe0447ebe1556847255faa797f9b;
 wordpress_test_cookie=WP%20Cookie%20check; 
wordpress_logged_in_0ca336a14ef7b2941859a7208fbdc453=back1%7C1613847137%7CX9zaOUs8JygWJfwMWFapApMEOx0O0ShNokjG0C9c77G%7C3bfc5914e1336d467cf4483f73a1bf5bc76698e4b4c42fa15c332139f9e6cac9;
 wp-settings-time-1=1613674470
00000000:FE-https.clihdr[000f:ffffffff]: upgrade-insecure-requests: 1
00000000:back1.srvrep[000f:0010]: HTTP/1.1 302 Found
00000000:back1.srvhdr[000f:0010]: date: Fri, 19 Feb 2021 07:33:39 GMT
00000000:back1.srvhdr[000f:0010]: server: Apache/2.4.38 (Debian)
00000000:back1.srvhdr[000f:0010]: x-powered-by: PHP/7.4.15
00000000:back1.srvhdr[000f:0010]: expires: Wed, 11 Jan 1984 05:00:00 GMT
00000000:back1.srvhdr[000f:0010]: cache-control: no-cache, must-revalidate, 
max-age=0
00000000:back1.srvhdr[000f:0010]: x-redirect-by: WordPress
00000000:back1.srvhdr[000f:0010]: location: 
https://back1.domain.local:8000/wp-login.php?redirect_to=https%3A%2F%2Ffront1.domain.local%2Fwp-admin%2F&reauth=1
00000000:back1.srvhdr[000f:0010]: content-length: 0
00000000:back1.srvhdr[000f:0010]: content-type: text/html; charset=UTF-8
00000000:back1.srvcls[000f:0010]
00000000:back1.clicls[000f:0010]
00000000:back1.closed[000f:0010]
[ALERT] 049/083340 (175851) : sendmsg()/writev() failed in logger #1: No such 
file or directory (errno=2)
00000001:FE-https.accept(0009)=000f from [192.168.56.1:1446] ALPN=<none>

---

But if I do some configuration tweaks in "wp-config.php", like adding the 
following two lines :
define('WP_HOME', 'https://front1.domain.local');
define('WP_SITEURL', 'https://front1.domain.local');

It seems to work correctly.

It is not an acceptable solution however, as these WP instances will be managed 
by people who are not really tech-savvy.

So I wonder if HAProxy could provide a setup with all the required 
modifications, rewritings, ... allowing both worlds to coexist in a transparent 
way :
- usable WP site while browsing the "real" URLs from the backend 
- usable WP site while browsing through HAProxy.

Right now WP is my concern, but I am sure this is a reusable "pattern" for 
future needs.

Regards
  



----- Mail original -----
De: "Aleksandar Lazic" <al-hapr...@none.at>
À: "spfma tech" <spfma.t...@e.mail.fr>, haproxy@formilux.org
Envoyé: Jeudi 18 Février 2021 16:34:18
Objet: Re: Apache Proxypass mimicing ?

HI.

On 18.02.21 10:12, spfma.t...@e.mail.fr wrote:
> Hi,
> I would like to setup a reverse proxy with SSL termination to allow something 
> like :

> https://front1.domain proxying http://back1.otherdomain:8000 (and maybe one 
> day back2)
> https://front2.domain proxying http://back3.otherdomain:5000
 >
> Common things I already configured using Apache's mod_proxy.
> I am not an HAProxy expert, I only used it in tcp mode for simple and 
> efficient load balancing.

I would suggest to take a look into the following articles.

https://www.haproxy.com/blog/how-to-map-domain-names-to-backend-server-pools-with-haproxy/
https://www.haproxy.com/blog/introduction-to-haproxy-maps/

> I have read this very interresting article 
> https://www.haproxy.com/fr/blog/howto-write-apache-proxypass-rules-in-haproxy/
>  
> but it seems directives belong to former versions, and I was not able to get 
> the expected result.
 >
> One of my important use-case is Apache backends hosting WordPress.
> There are numerous examples here and there, but I always end with URLs like 
> https://front1.domain/wp-admin 
> redirected to http://front1.domain:8000/wp-admin or 
> https://back1.otherdomain:8000/wp-admin aso ...
 >
> I know WP is redirecting to URLs related to it's configured URLs , so I guess 
> some 
> headers rewriting are required, but I don't know how to do that.
> I am looking for a generic way to perform the required rewrites, without 
> depending 
> on fixed URL patterns. Is it only possible with HAProxy ? Some very old posts 
> suggested it was not, but there were from around nine years ago.
> I have not been able to find answers so far (some search results show 
> appealing 
> descriptions but sites are not responding) so I am looking for some help here.

Well you will need some pattern that the computer can follow.

For example based on which criteria should a program know what it should to on 
the URL?

Request: https://front1.domain/wp-admin

Redirect to http://front1.domain:8000/wp-admin when what happen?
Send request to https://back1.otherdomain:8000/wp-admin when what happen?

I would start with that config 
https://github.com/Tyrell66/SoHo/blob/master/haproxy-2020.05.02.cfg

Here a slightly adopted version.


```
frontend http-in
       bind *:80

        # Prevent DDoS
        stick-table type ip size 100k expire 30s store http_req_rate(10s)
        http-request track-sc0 src
        http-request deny deny_status 429 if { sc_http_req_rate(0) gt 20 }

       http-request add-header X-Forwarded-Proto http
       redirect scheme https if !{ ssl_fc }


frontend https-in
        # /etc/haproxy/certs/ contains both .pem for default and second domain 
names.
   bind *:443 ...

        http-response replace-header Location ^http://(.*)$     https://\1
         http-request add-header X-Forwarded-Proto https

        http-request set-header X-Forwarded-Proto https
        http-request set-header X-Forwarded-Port 443
        capture request header X-Forwarded-For len 15

# Strip off Proxy headers to prevent HTTpoxy (https://httpoxy.org/)
   http-request del-header Proxy

        ## Secure headers 
https://blog.devcloud.hosting/securing-haproxy-and-nginx-via-http-headers-54020d460283
        ## Test your config with https://securityheaders.com/
        ## and https://observatory.mozilla.org/

        http-response set-header X-XSS-Protection 1;mode=block
        http-response set-header X-Content-Type-Options nosniff
        http-response set-header Referrer-Policy no-referrer-when-downgrade
        http-response set-header X-Frame-Options SAMEORIGIN
        http-response del-header X-Powered-By
        http-response del-header Server


   # This line is for HSTS:
   http-response set-header Strict-Transport-Security "max-age=63072000; 
includeSubdomains; preload;"


       use_backend %[req.hdr(host),lower,map(hosts.map,be_static)]

backend be_static
   server default_static xxx.xxx.xx

backend be_domain1
        http-request replace-uri ^/gc/(.*) /guacamole/\1
       server host1              192.168.1.13:58080/guacamole/#

...

```

file hosts.map
```
front1.domain be_domain1
front2.domain be_domain2

```

You can also set maps for path and host with ports.
As you can see HAProxy should be able to full fill your requirement as long as 
you can
define it for you and the program/Computer ;-)

Maybe this article could also help you to protect the WP installations for 
attacks.
https://www.haproxy.com/blog/wordpress-cms-brute-force-protection-with-haproxy/

> Thanks

Welcome

Alex

Reply via email to