Haproxy solr healthcheck with authentication - haproxy

here is my config file
listen solr 0.0.0.0:8983
mode http
balance roundrobin
option httpchk GET "/solr/select/?q=id:1234" HTTP/1.1
server solr_slave 1.1.1.1:8983 maxconn 5000 weight 256 check
server solr_master 2.2.2.2:8983 maxconn 5000 weight 1 check
the problem is that my solr server is protected using basic http password authentication and hence the health check fails always
how do i tell haproxy to use those credentials during the health checks?

A little late, but I just came across the same problem, and wanted to share the solution with the world. First, you base64-encode the credentials:
$ echo -n "user:pass" | base64
dXNlcjpwYXNz
(Make sure you use the -n switch so you don't append a newline.)
The option httpchk allows you to add arbitrary HTTP headers to the request; this feature isn't documented very well. (According to this discussion, future versions of Haproxy might get a more user-friendly method.) To use basic authentication:
option httpchk GET /solr/ HTTP/1.0\r\nAuthorization:\ Basic\ dXNlcjpwYXNz
Note that I used HTTP 1.0; for 1.1, you also need a Host header.

Related

Use haproxy as a reverse proxy with an application behind Internet proxy

I need to integrate several web applications on-premise and off-site under a common internally hosted URL. The on-premise applications are in the same data center as the haproxy, but the off-site applications can only be reached via a http proxy because the server on which haproxy is running has no direct Internet access. Therefore I have to use a http Internet proxy, SOCKS might be an option too.
How can I tell haproxy that a backend can only be reached via proxy ?
I would rather not use an additional component like socksify / proxifier / proxychains / tsocks / ... because this introduces additional overhead.
This picture shows the components involved in the setup:
When I run this on a machine with direct Internet connection I can use this config and it works just fine:
frontend main
bind *:8000
acl is_extweb1 path_beg -i /policies
acl is_extweb2 path_beg -i /produkte
use_backend externalweb1 if is_extweb1
use_backend externalweb2 if is_extweb2
backend externalweb1
server static www.google.com:80 check
backend externalweb2
server static www.gmx.net:80 check
(Obviously these are not the URLs I am talking to, this is just an example)
Haproxy is able to check the external applications and routes traffic to them:
In the safe environment of the company I work at I have to use a proxy and haproxy is unable to connect to the external applications.
How can I enable haproxy to use those external web application servers behind a http proxy (no authentication needed) while providing access to them through a common http page / via browser ?
How about to use delegate ( http://delegate.org/documents/ ) for this, just as an idea.
haproxy -> delegate -f -vv -P127.0.0.1:8081 PROXY=<your-proxy>
http://delegate9.org/delegate/Manual.shtml?PROXY
I know it's not that elegant but it could work.
I have tested this setup with a local squid and this curl call
echo 'GET http://www.php.net/' |curl -v telnet://127.0.0.1:8081
The curl call simluates the haproxy tcp call.
I was intrigued to make it work but i really could not find anything in the haproxy documentation, so i googled a bit and found that nginx might do the trick, but it didn't for me, after a bit more of googleing i ended up finding a configuration for apache that works.
here is the important part:
Listen 80
SSLProxyEngine on
ProxyPass /example/ https://www.example.com/
ProxyPassReverse /example/ https://www.example.com/
ProxyRemote https://www.example.com/ http://corporateproxy:port
ProxyPass /google/ https://www.google.com/
ProxyPassReverse /google/ https://www.google.com/
ProxyRemote https://www.google.com/ http://corporateproxy:port
i'm quite sure there should be a way to translate this configuration to nginx and even to haproxy... if i manage to find the time i will update the answer with my findings.
for apache to work you should also enable a few modules, i put up a github repository with a basic docker configuration that showcases feel free to have a look at that to see the full working configuration.

JWT Validation in HAProxy

I have an HAProxy configured to accept requests to *.mysubdomain.com. The HAProxy will parse the subdomain (prod or dev from prod.mysubdomain.com or dev.mysubdomain.com) and forward to the correct backend. Two backends exist, one for prod and one for dev. Each backend contains two server entries pointing towards Marathon LB instances on each subdomain.
The subdomains require a JWT cookie for authentication on the backend. I have the public key to check the validity of the JWT, but would like to do so in the HAProxy. Is there a way to add my own code to perform the JWT validity check within the HAProxy configuration?
The HAProxy configuration file is as follows:
global
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
mode http
# Returns true when one of the headers contains one of the strings either isolated or delimited by dots. This is used to perform domain name matching.
acl host_dev hdr_dom(host) -i dev
acl host_prod hdr_dom(host) -i prod
acl jwtPresent req.cook(JWT) -m found
use_backend prod_domain if jwtPresent host_prod
use_backend dev_domain if jwtPresent host_dev
default_backend prod_domain
backend prod_domain
balance roundrobin
server prodDomain1 "${MARATHON_LB_PROD_1}" maxconn 32 check
server prodDomain2 "${MARATHON_LB_PROD_2}" maxconn 32 check
backend dev_domain
balance roundrobin
server devDomain1 "${MARATHON_LB_DEV_1}" maxconn 32 check
server devDomain2 "${MARATHON_LB_DEV_2}" maxconn 32 check
HAProxy can act as an API gateway and validate JWT tokens against a public key. They have written a blog post and provided sample code to show you how.
The post is here: https://www.haproxy.com/blog/using-haproxy-as-an-api-gateway-part-2-authentication/
The sample lua code is here: https://github.com/haproxytech/haproxy-lua-jwt
As the other answer pointed out, you have to use Lua script. You can use existing implementations from lua-resty-jwt or Kong.
Notes:
Those code-bases are not concise. A simple copy & paste won't work. So you have to extract the bare minimum you need.
You can't have dependencies in your Lua script. Only plain vanilla Lua. So you have to get rid of all require statements.
The tricky part is the HMAC implementation.
Avoid any I/O operation in your Lua script, e.g. file, database, network operations.
It's not an easy undertaking. Good luck! It's something worth sharing.
As far as I could tell, HAProxy does not have the functionality to perform the logic for validating the JWT. Instead, I implemented a script in Lua for haproxy.cfg to call to perform the validation:
global
maxconn 256
lua-load /choose_backend.lua
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn]
http-request set-var(txn.backend_name) lua.backend_select()
use_backend %[var(txn.backend_name)]
backend prod_domain
balance roundrobin
server prodDomain1 "${MARATHON_LB_PROD_1}" maxconn 32 check
server prodDomain2 "${MARATHON_LB_PROD_2}" maxconn 32 check
backend dev_domain
balance roundrobin
server devDomain1 "${MARATHON_LB_DEV_1}" maxconn 32 check
server devDomain2 "${MARATHON_LB_DEV_2}" maxconn 32 check

How to load balance and redirect with haproxy

Content on both servers are located in http://localhost:88/web/portal
I have configured haproxy with the following config block
listen webfarm 0.0.0.0:8080
mode http
stats enable
stats uri /haproxy?stats
balance roundrobin
option httpclose
option forwardfor
server webserver01 192.168.1.10:88 check
server webserver02 192.168.1.20:88 check
How would I get haproxy to redirect further into directories? I was trying to do redirects locally via apache but all I am getting is loops.
This is untested but something like this may be what you are looking for:
frontend my_frontend
mode http
bind *:8080
stats enable
stats uri /haproxy?stats
default_backend my_backend
backend my_backend
balance roundrobin
option httpclose
option forwardfor
reqrep ^(.*) /web/portal\1
server webserver01 192.168.1.10:88 check
server webserver02 192.168.1.20:88 check
The key change is the reqrep line which takes in the requested uri and prepends /web/portal to it (at least it should).
Sorry it is not in the same format as your example but I just copied it from some of my config and changed it. Let me know if that works for your situation.

Force HTTPS in Neo4j configuration

Is is possible force HTTPS URLs even when the X-Forwarded-Host header is not present?
Update:
We are using HAProxy in front of the Neo4j server. The configuration is
frontend proxy-ssl
bind 0.0.0.0:1591 ssl crt /etc/haproxy/server.pem
reqadd X-Forwarded-Proto:\ https
default_backend neo-1
This works well when every connection contains only one request. However, for Neo4j drivers which uses keep-alive (like Py2neo), the header is added only to the first request.
Without the X-Forwarded-Proto header, the generated URLs are http://host:1591, instead of https://host:1591.
According to the HAProxy documentation, this is the normal behavior:
since HAProxy's HTTP engine does not support keep-alive, only headers
passed during the first request of a TCP session will be seen. All subsequent
headers will be considered data only and not analyzed. Furthermore, HAProxy
never touches data contents, it stops analysis at the end of headers.
The workaround is to add option http-server-close in the frontend, so it will force that every request is in its own connection, but it will be nicer if we can support keep-alive.
Put something like Apache or Nginx in front of your Neo4j server to perform that task.
In terms of py2neo, I can add some functionality to cater for this situation quite easily. What if I were to include X-Forwarded-Proto: https for all https connections? Would that cause a problem in cases where a proxy isn't used?

how to balance to a specific server if hostname matches x.domaine.com (Haproxy)

as mentioned in the title, i've set an Haproxy loadbalancer with a basic configuration, what i'd like to do is to always redirect request to the first server if the hostname matches x.domaine.com, but keep the balancing for domaine.com, is it possible with Haproxy, and if so how can i do it.
her's my configuration
listen webcluster *:80
mode http
balance roundrobin
option httpchk HEAD / HTTP/1.0
option forwardfor
cookie LSW_WEB insert
option httpclose
server bigSRV 192.168.1.10:8082 cookie LSW_WEB01 check
server miniSRV 192.168.2.10:8082 cookie LSW_WEB01 check
thanks in advence
after hours of digging i finally got it to work, so i'm going to answer my own question in case if samone have the same issue
generally i created a frontend that listen on port:80 and in which i defined 2 ACLs that uses the "if" statement to check the http header and then redirect to one of the backends defined, if no request matches the conditions, we redirect to default backend, here's how it's done (on haproxy.cfg) :
frontend http-proxy
bind *:80
acl is_www hdr(host) -i www.domain.com
acl is_x hdr(host) -i x.domain.com
use_backend clusterWWW if is_www
use_backend clusterX if is_x
default_backend clusterWWW
backend clusterWWW
server bigSRV 192.168.1.10:8082 cookie LSW_WEB01 check
server miniSRV 192.168.2.10:8082 cookie LSW_WEB01 check
backend clusterX
server bigSRV 192.168.1.10:8082 cookie LSW_WEB01 check