Quantcast
Channel: HAProxy community - Latest topics
Viewing all articles
Browse latest Browse all 4723

HA Proxy forwards based on URL

$
0
0

Hi,

So I’ve only just started out with HA proxy and my requirements aren’t anything too heavy but I’m still running into a few issues.

Goal
I have a single IP that I use port forwarding on to allow me to host many web servers behind an NGINX reverse proxy. I now have to get an RDS Gateway functioning behind that proxy. A week of tinkering has been only partially successful until I realised that this solution won’t work. I’ll not go into the details here.

Solution
I came accross this: https://www.haproxy.com/documentation/haproxy/deployment-guides/remote-desktop/rdp-gateway and thought this would be a viable (though a little messy), solution. The thought being that HA Proxy will be the first hop, listening on 80 and 443, examining the headers of inbound connections. If it sees rds.mydomain.com, it forwards the connection to the RDS Gateway. If it doesn’t match, it forwards to my NGINX reverse proxy. Having HA Proxy terminate the SSL connection is also attractive to me, especially when you consider things like this: https://betanews.com/2020/01/27/windows-remote-desktop-gateway-rce-exploit. So, thats the basics of what I’m aiming for.
For my initial testing, I have used most of the config found in the link above with some of my own additions. HA Proxy is listening on 81 and 443 (although only 81 is currently accessible while I nail this part of my problem down), it should check the headers, see that they are bound for webserver.mydomain.com, skip the config for rds.mydomain.com and forward to my test webserver.

Problem
Punching in http://webserver.mydomain.com:81 hits the HA Proxy server and forwards me to http://webserver.mydomain.com:81/RDWeb. Obviously the acl checking is not firing as I expected although I’m not totally clear why.

Code
You’ll have to excuse the heavily commented code. It’s for my benefit as I learn all the syntax (and possibly will help others point out where I’m getting confused).

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 30s
        user haproxy
        group haproxy
        daemon

        # 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
        # Define this connection type as HTTP. Defining this parameter allows for further parameters to be defined.
        mode            http
        # Define additional options. Descriptions to follow.
        option          httplog
        option          dontlognull
        option          http-keep-alive
        timeout         http-request 10s
        timeout         queue 1m
        timeout         connect 10s
        timeout         client 10s
        timeout         server 1m
        timeout         http-keep-alive 10s
        timeout         check 10s
        maxconn         1000
        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

    # Define one universal frontend to capture both HTTP & HTTPS traffic.
    frontend mydomain.com
            bind *:81
            bind *:443

            # Define an acl called "acl_rds" that looks for mydomain.com in the request header of the inbound connection.
            acl acl_rds hdr(host) -i rds.mydomain.com

            # Capture the host name from the request header for later use. Max length of header can be no more than 32
            # characters in length. We can only capure request and response headers in seperate streams. Request captures
            # on inbound traffic and responses on outbound traffic.
            capture request header Host len 32

            # Redirect request to /RDWeb if user tries to access the root (/).
            http-request redirect location /RDWeb/ if { path -i / /RDWeb }

            # Define an acl called "path_rdweb" that checks the path of inbound requests for "/RDWeb/".
            acl path_rdweb path_beg -i /RDWeb/

            # Deny the request unless the requested URL matches the acl defined above (path_rdweb). This prevents users
            # trying any sub-folders at rds.mydomain.com other than /RDWeb.
            http-request deny unless path_rdweb

            # Use the backend named "backend_rds" if you find the acl defined as "acl_rds".
            use_backend backend_rds if acl_rds

            # If the incoming connection does not match rds.mydomain.com, send the connection to the nginx proxy server.
            default_backend backend_nginx

    backend backend_rds
            # Use the balacing algorithm "leastconn". This algorithm is best suited for long connections rather than
            # website connections.
            balance leastconn

            # This is how ha-proxy will perform a health-check on the RDS server. It will check to see if the /RDWeb
            # path is accessible. As soon as it becomes inaccessible, the server in the pool (doesn't apply in this
            # specific config), is seen as being down. ha-proxy will continue checking this URL and the moment it
            # comes back up again, it the backend server will be added back into the pool.
            option httpchk GET /RDWeb

            # Insert a cookie called RDWEB. Append a “Cache-Control: nocache” to the cookie since this type of
            # traffic is supposed to be personnal and we don’t want any shared cache on the internet to cache it.
            cookie RDPWEB insert nocache

            # Override the default options for the default server - THIS MIGHT NOT BE NEEDED - POSSIBLE REMOVAL
            default-server inter 3s rise 2 fall 3

            # Define the first (and only in this specific config), backend server.
            server rds_gw 192.168.1.30:443 maxconn 1000 weight 10 ssl verify none check cookie rds_gw

    backend backend_nginx
            mode http
            balance roundrobin
            server srv1 192.168.1.29:80

Hopefully, someone can point out my errors. Once I get the redirect working, I can move onto testing the RDS portion.

Thanks for any suggestions you have.

1 post - 1 participant

Read full topic


Viewing all articles
Browse latest Browse all 4723

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>