HAProxy hdr_dom(host) -i can't detect subdomain.subdomain.domain.com - haproxy

Hi Im trying to route different domain names listening of the same port to different backend using acl in haproxy. How i have a problem when one of the domain names has two subdomains. So my frontend config looks like this
bind *:80
mode http
acl is_kibana_prod hdr_dom(host) -i kibana.domain.com
acl is_kibana_nprod hdr_dom(host) -i non-prod.kibana.domain.com
use_backend backend_kibana_prod if is_kibana_prod
use_backend backend_kibana_nprod if is_kibana_nprod
default_backend backend_default
When I make a request to bar.bar.bar.com the request goes to backend_foo. Can anyone help me on this?
Actual logs:
172.17.0.1:54982 [21/May/2020:03:50:08.978] http backend_kibana_prod/kibanaprod 0/0/2/9/11 302 279 - - ---- 1/1/0/0/0 0/0 {non-prod.kibana.domain.com} "GET / HTTP/1.1"
172.17.0.1:54982 [21/May/2020:03:50:08.989] http backend_kibana_prod/kibanaprod 0/0/0/32/37 200 85130 - - ---- 1/1/0/0/0 0/0 {non-prod.kibana.domain.com} "GET /login?next=%2F HTTP/1.1"

It turned out I need to use hdr(host) instead of hdr_dom(host)

Your configuration works for me in HAProxy 2.0. Below you can see I am capturing the Host header sent by the client within the request log and being sent to the appropriate backend for each host.
192.168.1.20:49506 [20/May/2020:23:29:33.869] fe_main backend_bar/s1 0/0/0/2/2 200 799 - - ---- 1/1/0/0/0 0/0 {bar.bar.bar.com} "GET / HTTP/1.1"
192.168.1.20:49508 [20/May/2020:23:29:35.799] fe_main backend_foo/s1 0/0/1/6/8 200 2080 - - ---- 1/1/0/0/0 0/0 {foo.foo.com} "GET / HTTP/1.1"
bind *:80
mode http
http-request capture hdr(Host) len 32
acl is_foo hdr_dom(host) -i foo.foo.com
acl is_bar hdr_dom(host) -i bar.bar.com
use_backend backend_foo if is_foo
use_backend backend_bar if is_bar
default_backend backend_default
backend backend_foo
server s1 192.168.1.71:80
backend backend_bar
server s1 192.168.1.122:80

Related

Haproxy ACL for query-string "Authorization"

I am trying to create ACL in Haproxy to query Authorization from request header and route to backend based on AccessID. I have used map file which are populated with AccessID and backend server. I am sure that my ACL is not working and hence I am getting 503 for incoming requests. Any help is appreciated!
Config File:
frontend main
bind *:80
capture request header Authorization len 50
acl GET_calls method GET HEAD OPTIONS
acl PUT_calls method PUT
use_backend %[urlp,map_sub(/etc/haproxy/PUT_Header.map)] if PUT_calls
Map File:
# AccessID backend server
JMYQ get_s1
P2BH get_s1
WEA1 get_s2
I have captured the request header in log and I see AccessID.
Apr 8 10:10:29 localhost haproxy[79517]: 0.11.4.1:929 [08/Apr/2022:10:10:29.232] main main/<NOSRV> -1/-1/-1/-1/0 503 212 - - SC-- 0/0/0/0/0 0/0 {Credential=WEA1} "PUT /common/Demo2.file HTTP/1.1"

Disable non-backend request and non haproxy restart log in haproxy

i just want to save log for backend request and the restarting of haproxy service in haproxy,
this is the configuration of my haproxy.
[appadmin#sltxh5gvt4c rsyslog.d]$ cat /etc/rsyslog.conf
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
# Save haproxy log
local3.* /var/log/haproxylog/haproxy.log
# Save keepalived log
local2.* /var/log/keepalived/keepalived.log
++++++++++ this is haproxy.cfg
defaults
option forwardfor
log global
option httplog
log 127.0.0.1 local3
frontend case3
bind :80
mode http
log global
option httpclose
timeout client 5000
acl sabrix path_beg -i /sabrix
acl geolink path_beg -i /axis2
use_backend sabrix_servers if sabrix
use_backend us_geolink if geolink
capture request header Host len 64
capture request header User-Agent len 128
capture request header X-Forwarded-For len 100
capture request header Referer len 200
capture response header Server len 40
capture response header Server-ID len 40
log-format %ci:%cp\ %si:%sp\ %ST\ %r\ %b\ %f\ %bi\
+++++++++++++++++++++++++ haproxy.log
2020-06-14T23:33:36+08:00 localhost haproxy[27891]: 10.12.12.12:42164 -:- 400 <BADREQ> case3 case3 -
2020-06-14T23:33:42+08:00 localhost haproxy[27891]: 10.12.12.12:42204 -:- 400 <BADREQ> case3 case3 -
2020-06-14T23:33:48+08:00 localhost haproxy[27891]: 10.12.12.12:42244 -:- 400 <BADREQ> case3 case3 -
i don't want to save such logs in my haproxy.log, how to change my configuration files ?
thanks
You can't do this in haproxy, the best way to discard this log lines is with rsyslog.
:msg, contains, "BADREQ" ~
There are more information about discarding unwanted messages in this document.
https://www.rsyslog.com/discarding-unwanted-messages/
This looks similar to this question.
rsyslog filtering and forwarding
i tried to edit /etc/rsyslog.conf
# ignore BADREQ in haproxy.log
:msg, contains, "BADREQ" /var/log/haproxylog/haproxy.log
or
# ignore BADREQ in haproxy.log
:msg, contains, "BADREQ" stop
both don't work.
i check haproxy.cfg, i got the answer, we just need add
option dontlognull
to haproxy.cfg

How to redirect to domain name with https using haproxy

I tried to receive request and want to redirect it to other host using dns name and exposed with https protocol. For example, my server is http://8.8.8.8:10101/partnerA/getUser. I want haproxy redirect this to https://partner.com/partnerA/getUser (same path as the source).
I also want to filter by path for another redirect destination such as http://8.8.8.8:10101/partnerB/getMarketShare will redirected by HAProxy to https://subdomainb.differentpartner.com/partnerB/getMarketShare(notice the path also follow the same rule, but based on path it will give different host name.
I tried below haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
bind *:10101
acl url_partnerA path_beg -i /partnerA
acl url_partnerB path_beg -i /partnerB
http-request redirect scheme https if url_partnerA
http-request redirect scheme https if url_partnerB
http-request redirect prefix https://partnerA.com if url_partnerA
http-request redirect prefix https://subdomainb.differentpartner.com/ if url_partnerA
default_backend app
#---------------------------------------------------------------------
# round robin balancing between the various backends
backend app
balance roundrobin
# server app1 127.0.0.1:11003 check
But everytime I access (I use http) POST http://8.8.8.8:10101/partnerA/getUser, the log from haproxy -f haproxy10101.cfg -d will give me this
00000000:main.accept(0005)=0009 from [8.8.8.8:48554] ALPN=<none>
00000000:main.clireq[0009:ffffffff]: POST /partnerA/getUser HTTP/1.1
00000000:main.clihdr[0009:ffffffff]: Host: 8.8.8.8:10101
00000000:main.clihdr[0009:ffffffff]: User-Agent: curl/7.47.0
00000000:main.clihdr[0009:ffffffff]: Accept: */*
00000000:main.clihdr[0009:ffffffff]: Authorization: Basic dGNhc2g6RzBqM2tmMHJsMWYzIQ==
00000000:main.clihdr[0009:ffffffff]: Content-Type: application/json
00000000:main.clihdr[0009:ffffffff]: Postman-Token: 45a236c-740a-4859-a13a-1c45195a99f2
00000000:main.clihdr[0009:ffffffff]: cache-control: no-cache
00000000:main.clihdr[0009:ffffffff]: Content-Length: 218
00000000:main.clicls[0009:ffffffff]
00000000:main.closed[0009:ffffffff]
Anything I miss to make it work? Thanks

How to link frontend to backend when the path request are different?

I have an Haproxy set with https offloadin, and I'm trying to correctly point the requests made to frontend to it's corresponding backend, but bumped into some obstacles.
I have a backend server on http://:9000/abc (NOT in root of the webserver) and when I set a frontend with https:///abc the pointing works as expected and I see the login page.
But I also have another backend server, which is on http://:8888 (IN the root of webserver, it makes it's own redirect to http://:8888/def) and I want it to be accessible by https:///def. But in this case the pointing doesn't work.
How can I make https:///def point to http://:8888 ? Heres is my .cfg
Using HAproxy 1.7
# Automaticaly generated, dont edit manually.
# Generated on: 2019-01-28 13:59
global
maxconn 1000
stats socket /tmp/haproxy.socket level admin
uid 80
gid 80
nbproc 1
hard-stop-after 15m
chroot /tmp/haproxy_chroot
daemon
tune.ssl.default-dh-param 2048
server-state-file /tmp/haproxy_server_state
listen HAProxyLocalStats
bind 127.0.0.1:2200 name localstats
mode http
stats enable
stats refresh 10
stats admin if TRUE
stats show-legends
stats uri /haproxy/haproxy_stats.php?haproxystats=1
timeout client 5000
timeout connect 5000
timeout server 5000
frontend shared-frontend-merged
bind 200.129.168.14:443 name 200.129.168.14:443 no-sslv3 ssl crt-list /var/etc/haproxy/shared-frontend.crt_list
mode http
log global
option http-keep-alive
option forwardfor
acl https ssl_fc
http-request set-header X-Forwarded-Proto http if !https
http-request set-header X-Forwarded-Proto https if https
timeout client 30000
acl aclcrt_shared-frontend var(txn.txnhost) -m reg -i ^ifamcmc\.ddns\.net(:([0-9]){1,5})?$
acl ACL1 var(txn.txnpath) -m sub -i abc
acl ACL2 var(txn.txnpath) -m sub -i def
http-request set-var(txn.txnhost) hdr(host)
http-request set-var(txn.txnpath) path
use_backend glpi_ipvANY if ACL1
use_backend ciweb_ipvANY if ACL2
frontend http-to-https
bind 200.129.168.14:80 name 200.129.168.14:80
mode http
log global
option http-keep-alive
timeout client 30000
http-request redirect scheme https
backend abc_ipvANY
mode http
id 102
log global
timeout connect 30000
timeout server 30000
retries 3
option httpchk OPTIONS /
server abc 10.100.0.30:9000 id 103 check inter 1000
backend def_ipvANY
mode http
id 104
log global
timeout connect 30000
timeout server 30000
retries 3
option httpchk OPTIONS /
server def 10.100.0.40:8888 id 105 check inter 1000
I expect that access to https:///def correctly points to the backend at http://:8888
https://<my.address.com>/abc ------> http://<internal_ip>:9000/abc (OK)
https://<my.address.com>/def ------> http://<internal_ip_2>:8888 (NOT OK)
Have your HAProxy system do initially forwarding based on ports, and then wildcards on your directory.
Please see below:
frontend a-frontend-conf
# Declare an ACL using path_beg (Path Begins)
acl path_images path_beg /images
# Use backend server1 if acl condition path_images is fulfilled
use_backend server1 if path_images
backend server1
[...]
Source: https://serverfault.com/questions/659793/haproxy-how-to-balance-traffic-within-directory-reached

HAProxy frontend rule matching order

I have a haproxy configuration as follows. (haproxy 1.7) We want to catch all OPTIONS request and respond directly to them instead of routing the requests to backends (which have basic auth enabled).
This was working fine when we developed it but now it seems to not be matching the rules in order (not sure what we have/haven't done which has caused this):
global
log 127.0.0.1 local1
tune.ssl.default-dh-param 2048
lua-load /etc/haproxy/cors.lua
stats socket /var/run/haproxy.sock mode 400
# Default certificate and key directories
ca-base /etc/ssl/private
crt-base /etc/ssl/private
# User lists used to enforce HTTP Basic Authentication
userlist ul_100123-2ovt9rsu
user app1 password $6$lCjf6VnWhI$kcjmpWdV.odeYf4psUhcVKs49ZtPk3MDhg5wtLNUx658A3EWdDHJQqs9xCD1d.7zG05M2nwOxdkC6o/MSpifv0
userlist ul_100123-9uvsclqr
user app1 password $6$DlcLoDMMu$wDm3O0W1eiQuk8gI.GmpzI1.jbBf.UYQ.KM73nHa1tGZJNfzkDpVnLUhh7v7C9yPHB1oo0cRrFnfOdeyAf/eU1
# Front-end for public services which have SSL termination at the router.
frontend term
bind *:443 accept-proxy ssl no-sslv3 crt router/fred-external.pem crt router/fred-external.ace.pem crt router
reqadd X-Forwarded-Proto:\ https
rspidel ^(Server|X-Powered-By):
option forwardfor
mode http
http-request use-service lua.cors-response if METH_OPTIONS { req.hdr(origin) -m found }
acl host_match_100123-2ovt9rsu ssl_fc_sni -i 2ovt9rsu.fredurl.com
use_backend b_term_100123-2ovt9rsu if host_match_100123-2ovt9rsu
......
If I curl -X OPTIONS to 2ovt9rsu.fredurl.com it matches the 2nd rule and forwards me to the b_term_100123-2ovt9rsu backend which then fails as I haven't provided auth creds.
If I curl -X OPTIONS to Anything.fredurl.com it matches the first http-request and responds with the cors response as expected.
Why does the 2ovt9rsu.fredurl.com not match the first http-request rule and then return the cors-response?
In the logs we can see
Nov 7 18:24:09 localhost haproxy[37302]: 94.45.23.22:49853 [07/Nov/2017:18:24:09.807] term~ b_term_100123-2ovt9rsu/<lua.cors-response> -1/-1/-1/-1/73 401 249 - - PR-- 0/0/0/0/3 0/0 "OPTIONS / HTTP/1.1"
when the request gets forwarded to the backend
http-request gets executed before use_backend, the config looks good to me, have you set origin header when you curl ?