haproxy and 'fixing" host names in http requests - haproxy

I'm starting to use haproxy to balance across nginx servers (in order to load balance the rails instances behind those nginxen). I want to 301 redirect all names that aren't the www name to the www name (and all http -> https). So I write this, which doesn't quite work. What actually happens is that http -> https, but all the names on https return 200 rather than 301 for all but www.staging.example.com. In addition, I was hoping to 301, say http://staging.example.com/ directly to https://www.staging.example.com/, but instead it just 301's to https://staging.example.com/
frontend www-http
bind 1.2.3.4:80
acl redirect_canonical req_ssl_sni -i staging.example.com
acl redirect_canonical req_ssl_sni -i myname.example.com
http-request redirect code 301 location https://www.staging.example.com%[capture.req.uri] if\
redirect_canonical
http-request redirect code 301 scheme https if !{ ssl_fc }
reqadd X-Forwarded-Proto:\ http
default_backend railswebapp-backend
frontend www-https
bind 1.2.3.4:443 ssl crt /etc/haproxy/ssl/
# 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
acl redirect_canonical req_ssl_sni -i staging.example.com
acl redirect_canonical req_ssl_sni -i myname.example.com
http-request redirect code 301 location https://www.staging.example.com%[capture.req.uri] if\
redirect_canonical
reqadd X-Forwarded-Proto:\ https
default_backend railswebapp-backend
Any pointers on what I'm doing wrong?
Update
The corrected block is this:
frontend www-http
bind 1.2.3.4:80
acl redirect_canonical hdr(host) -i staging.example.com
acl redirect_canonical hdr(host) -i myname.example.com
http-request redirect code 301 location https://www.staging.example.com%[capture.req.uri] if\
redirect_canonical
http-request redirect code 301 scheme https if !{ ssl_fc }
reqadd X-Forwarded-Proto:\ http
default_backend railswebapp-backend
frontend www-https
bind 1.2.3.4:443 ssl crt /etc/haproxy/ssl/
# 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
acl redirect_canonical ssl_fc_sni -i staging.example.com
acl redirect_canonical ssl_fc_sni -i myname.example.com
http-request redirect code 301 location https://www.staging.example.com%[capture.req.uri] if\
redirect_canonical
reqadd X-Forwarded-Proto:\ https
default_backend railswebapp-backend

Related

Specific routing for subdomains and wildcard domain on HAProxy

How could I achieve the correcting routing for specific subdomains and then route any domains that doesnt match any of the previous ACLSs?
frontend web_dashs
mode http
bind *:443 ssl crt /etc/ssl/domain/
http-request add-header X-Forwarded-Proto https
redirect scheme https if !{ ssl_fc }
acl domain_a hdr_sub(host) -i a.domain.com
acl domain_b hdr_sub(host) -i b.domain.com
acl wilds hdr(host) -i
# Default Route to normal backends
use_backend backend_a if domain_a
use_backend backend_b if domain_b
use_backend backend_c if wilds
Basically, what i'm trying to do is basically:
a. ----> backend A
b. ----> backend B
*.-----> backend C
Thanks in advance.
ACL is not needed for matching the rest, just use default_backend:
frontend web_dashs
mode http
bind *:443 ssl crt /etc/ssl/domain/
http-request add-header X-Forwarded-Proto https
redirect scheme https if !{ ssl_fc }
acl domain_a hdr_sub(host) -i a.domain.com
acl domain_b hdr_sub(host) -i b.domain.com
use_backend backend_a if domain_a
use_backend backend_b if domain_b
default_backend backend_c

Have to restart Haproxy every few minutes

(Ubuntu 16.04, 6 cores, 24GB Ram, Haproxy 1.8.0)
I've read so much about how easy haproxy is, so we set it up, did some basic testing / load testing and things looked good. Put it into production last night, things look good, until we start getting production traffic. I have to restart haproxy every few minutes b/c sites just stop responding. The stats website isnt showing me any stats that look alarming, and the machine is hardly using any resources.
Basically here is what we see - We restart haproxy, everything works great, then a few minutes later we have to restart it again (under production load).
Looking at the stats page I see the backend gets to around 50k sessions and then stuff just stops working.
Here is my config, can you check it out and help me understand how I should tune it?
global
log 127.0.0.1:22514 local2 debug
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
timeout connect 50000000
timeout client 50000000
timeout server 50000000
maxconn 80000
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
frontend loadbalanced_main
log global
bind *:80
mode http
redirect scheme https if !{ ssl_fc }
acl web1 hdr(host) -i -m sub 1.a.com
acl web2 hdr(host) -i -m sub 2.a.com
acl web3 hdr(host) -i -m sub 3.a.com
use_backend ordweb1 if web1
use_backend ordweb2 if web2
use_backend ordweb3 if web3
default_backend loadbalanced_nodes
frontend loadbalanced_main_ssl
log global
bind *:443 ssl crt /etc/ssl/private/a.com.pem crt /etc/ssl/private/b.com.pem
reqadd X-Forwarded-Proto:\ https
acl web1 hdr(host) -i -m sub 1.a.com
acl web1 hdr(host) -i -m sub 1.b.com
acl web2 hdr(host) -i -m sub 2.a.com
acl web2 hdr(host) -i -m sub 2.b.com
acl web3 hdr(host) -i -m sub 3.a.com
acl web3 hdr(host) -i -m sub 3.b.com
use_backend ordweb1 if web1
use_backend ordweb2 if web2
use_backend ordweb3 if web3
default_backend loadbalanced_nodes
backend ordweb1
mode http
redirect scheme https if !{ ssl_fc }
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server ordweb1 10.154.18.100:80 cookie check
backend ordweb2
mode http
redirect scheme https if !{ ssl_fc }
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server ordweb2 10.154.18.8:80 cookie check
backend ordweb3
mode http
redirect scheme https if !{ ssl_fc }
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server ordweb3 10.154.18.9:80 cookie check
backend loadbalanced_nodes
mode http
redirect scheme https if !{ ssl_fc }
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
cookie SRV insert indirect nocache
server ordweb1 10.154.18.100:80 check cookie ordweb1
server ordweb2 10.154.18.8:80 check cookie ordweb2
server ordweb3 10.154.18.9:80 check cookie ordweb3
listen stats
bind *:1936
stats enable
stats uri /
stats hide-version
stats auth nope:blah

how to redirect a url like https://example.com to https://www.example.com in haproxy

I know how to redirect from:
http example.com to https www.example.com
and
http www.example.com to https www.example.com
but don't know how to redirect from:
https example.com to https www.example.com in Haproxy
redirect prefix https://www.example.com code 301 if { hdr(host) -i example.com } in both frontend
frontend weblb
bind *:80
acl is_www hdr_beg(host) ilanni.com
redirect prefix https://www.ilanni.com code 301 if is_www
acl is_host hdr_beg(host) wwww.ilanni.com
redirect scheme https if !{ ssl_fc }
bind *:443 ssl crt /etc/haproxy/ilanni.com.pem
use_backend sellerserver if is_host
backend sellerserver
balance source
server web1 127.0.0.1:8111 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3

haproxy redirect scheme https if !$request_uri

If it's possible to disable https on some url, i try this, but it's not working.
I need a piece of my site without https and redirect
frontend http
bind *:80
mode http
acl folder path_beg -i ^/somefolder/subfolder/.* ^/somefolder/subfolder2/.*
redirect scheme https if !folder
option http-server-close
reqadd X-Forwarded-Proto:\ http
option forwardfor header X-Real-IP
default_backend nodes
frontend https
bind *:443
mode http
option http-server-close
reqadd X-Forwarded-Proto:\ https
option forwardfor header X-Real-IP
default_backend nodes
backend nodes
balance leastconn
server server1 10.10.10.7:80 cookie A check
server server2 10.10.10.8:80 cookie A check
Access list
acl folder path_dir -i /somefolder/subfolder/ /somefolder/subfolder2/
In backend you need rule
redirect scheme https if !folder !{ ssl_fc }
After that - all site has redirect to htts, but if uri contains /somefolder/subfolder/ or /somefolder/subfolder2/ it's be able to connect by http.
In nginx you need add some rules if you wanna redirect https to http
if ( $http_x_forwarded_proto = "https" ) {
rewrite ^/somefolder/subfolder2/ http://domain//somefolder/subfolder2/ permanent;
}

HAProxy redirect based on path?

I need to redirect certain paths to https - frontend secured
The reason for this is that i want certain parts of my web application to only be allowed to run over https.
I've figured out how to redirect all traffic by changing my HAproxy conf like this:
frontend unsecured *:80
#timeout client 86400000
#redirect prefix http://domain.com code 301
mode http
timeout client 120s
But how can i configure it to only redirect certain sub-folder on my domain?
What i would like is to redirect only the following URLs:
http://domain.com/info
http://domain.com/echo
http://domain.com/broadcast
http://domain.com/close
http://domain.com/probe
http://domain.com/cd* (wildcard)
Is this possible?
You should use acl to match you criteria.
frontend unsecured *:80
acl is-unsecure-path01 path_beg /info
acl is-unsecure-path02 path_beg /echo
acl is-unsecure-path03 path_beg /broadcast
acl is-unsecure-path04 path_beg /close
acl is-unsecure-path05 path_beg /probe
acl is-unsecure-path06 path_beg /cd
use_backend application-backend if is-unsecure-path01
use_backend application-backend if is-unsecure-path02
use_backend application-backend if is-unsecure-path03
use_backend application-backend if is-unsecure-path04
use_backend application-backend if is-unsecure-path05
use_backend application-backend if is-unsecure-path06
backend application-backend
redirect scheme https if !{ ssl_fc }
This one should do the trick
frontend http
bind *:80
acl is-secure path_reg ^\/(info|echo|close|cd.*)
redirect scheme https code 301 if is-secure !{ ssl_fc }
use_backend the-app unless is-secure
frontend https
bind *:443 ssl crt /usr/local/etc/haproxy/ssl
use_backend the-app
backend the-app
server account-1 account:80 check
NOTE: Change the SSL cert path on your app.