Haproxy SNI vs HTTP Host ACL check performance - performance

I have a HAproxy 1.5 setup which offloads SSL in front of a couple of webservers (this way, they deal only with HTTP)
My SSL certificate is a wildcard and we are balancing to different backends based on the FQDN.
My frontend config look like this :
...
frontend my-frontend
bind ip:443 ssl crt /var/etc/haproxy/wildcard_cert.pem
mode http
log global
option httplog
option forwardfor
use_backend my-backend if { ssl_fc_sni my.domain.org }
use_backend my-backend2 if { ssl_fc_sni my2.domain.org }
acl is-domain hdr(host) -i my.domain.org
acl is-domain2 hdr(host) -i my2.domain.org
use_backend my-backend if is-domain
use_backend my-backend2 if is-domain2
...
The special option ssl_fc_sni can be used in case of SSL offloading to access to the SNI value (where the other option req_ssl_sni applies in case of SSL pass-through)
http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#ssl_fc_sni
I wanted to know if ssl_fc_sni perform faster than HTTP Header extraction ACLs? Is there a chance for HAProxy to extract the SNI value and use it before reading the HTTP content, extracting the Host: Header and computing my second ACL?
Or the performance are just the same?
Thanks,

I've asked the same question on the haproxy mailing list and I got an answer:
ssl_fc_sni performs faster than hdr(host), but it will be imperceptible.
It's a bad idea to use the SNI value as a backend selector. The basic hdr(host) is definitely more standard, clean and safe.
Mailing list archive :
http://marc.info/?l=haproxy&m=144490809910124&w=2

Related

Ha Proxy with 3 springboot applications

I have 3 spring boot applications, each running on a different port. Can someone guide me how to set up Ha Proxy to demonstarte load balancing between the 3 applications (can make multiple instances). Is there any feature in spring boot which integrates Ha Proxy? What are the thing that I have to change in the config file of Ha Proxy?
Actually, there are several ways one can achieve this. But, I don't think there is anything in spring boot to integrate with HAProxy, because they two are different processes and they two work independently and nothing linked to each other as you might know what spring boot does. And HAProxy is a load balancer, and also a proxy server for TCP and HTTP process that are distributed across multiple servers.
That explains the first part of your question.
Now actually, how can you achieve this is entirely based on how you want to set this up.
Run individual applications as service like you did, and route traffic to each of them based on url.
Another deploying the individual applications on a single tomcat and taking the help of context path in your application properties you can route traffic from outside world to tomcat while tomcat takes care of everything.
And there might be other ways to do this, someone can add in the future to this answer. But either way you need to use a proxy server to do this, it could be either HAProxy, Nginx, or anything that fits the purpose.
So, taking your approach let's assume you are running your applications on port 8081, 8082, 8083. Your HAProxy setting should look something like this.
frontend www_http
mode http
bind *:80
bind *:443 ssl crt /etc/ssl/certs/mycompany.pem
# passing on that browser is using https
reqadd X-Forwarded-Proto:\ https
# for Clickjacking
rspadd X-Frame-Options:\ SAMEORIGIN
# prevent browser from using non-secure
rspadd Strict-Transport-Security:\ max-age=15768000
redirect scheme https code 301 if !{ ssl_fc }
stats enable
stats refresh 30s
stats show-node
stats realm Haproxy\ Statistics
stats uri /haproxy?stats
acl app1 hdr(host) -i app1.mycompany.com
acl app2 hdr(host) -i app2.mycompany.com
acl app3 hdr(host) -i app3.mycompany.com
# Just incase if you are using path instead of subdomain. But it's commented.
# acl app1 url_beg /app1
# acl app2 url_beg /app2
# acl app3 url_beg /app3
use_backend app_1_backend if app1
use_backend app_2_backend if app2
use_backend app_3_backend if app3
# backend for app 1
backend app_1_backend
timeout client 300000
timeout server 300000
redirect scheme https if !{ ssl_fc }
server app-1 127.0.0.1:8081 check
http-response set-header X-TS-Server-ID %s
# backend for app 2
backend app_2_backend
timeout client 300000
timeout server 300000
redirect scheme https if !{ ssl_fc }
server app-2 127.0.0.1:8082 check
http-response set-header X-TS-Server-ID %s
# backend for app 3
backend app_3_backend
timeout client 300000
timeout server 300000
redirect scheme https if !{ ssl_fc }
server app-3 127.0.0.1:8083 check
http-response set-header X-TS-Server-ID %s
This is some basic setup, but you can add your options and change everything as you like.
Hope this helps.

Tinyproxy Reverse Proxy "Access denied"

I'm using tinyproxy to reverse proxy. I have three subdomains pointed to the same server, and we need them to point to specific ports internally. That is, port 80 from any particular subdomain, mapped to a particular port. See the config example below.
The config looks like this:
Port 80
#Allow 127.0.0.1
#ReverseOnly yes
upstream 127.0.0.1:8115 "website.example.com"
upstream 127.0.0.1:3000 "api.example.com"
upstream 127.0.0.1:9000 "socket.example.com"
When I pull up any subdomain, all I get is:
Access denied
The administrator of this proxy has not configured it to service requests from your host.
Generated by tinyproxy version 1.8.3.
I cannot find adequate documentation anywhere. I'm thinking of contacting the maintainers. Please help.
I hope you already got the answer, but if you have not, here is the setting to allow client connecting to your proxy:
#
# Allow: Customization of authorization controls. If there are any
# access control keywords then the default action is to DENY. Otherwise,
# the default action is ALLOW.
#
# The order of the controls are important. All incoming connections are
# tested against the controls based on order.
#
Allow 127.0.0.1
#Allow 192.168.0.0/16
#Allow 172.16.0.0/12
#Allow 10.0.0.0/8
Allow 0.0.0.0/0
In my example here, I allow 0.0.0.0/0 because I'm configuring a reverse proxy from the Internet to my other VPS.
Also, your configuration above is for forward proxy, not reverse proxy.
To enable reverse proxy function, you need at least the following:
ConnectPort 80
ConnectPort 443
ReversePath "/" "http://<your server IP>:8080/"
ReverseOnly Yes
ReverseMagic Yes

Appending Path to Host HAPROXY

I am new to haproxy (actually proxy'ing in general) and I can't figure out how to add a path to my backend. I have my backend defined as:
server server1 ns.foo.com:7170 check
I want to add /web such that the request is directed to https://ns.foo.com:7170/web.
Thanks,
Mark
What you need is HTTP rewriting
https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#rewriting-http-urls
Adding this to your backend should solve your problem:
acl p_root path -i /
http-request set-path /web if p_root
If you would like to send a request coming in a given port to a specific path,
you can modify the request either in the frontend or backend configuration by specifying a http-request rule using the set-path action
For example if you would like to send any request to a /web then you should write
http-request set-path /web
into your backend configuration
Otherwise if you would like to prepend the incoming request path with /web
(so for example
localhost:[port]/somepath
should go to
serverhost:[serverport]/web/somepath) as Mawardy asked.
Then you should also use the %[path] variable like this
http-request set-path /web/%[path]
I have created a proof of concept of a spring server running with 2 instances in docker
which are loadbalanced with a HA proxy in docker that also modifies the path depending on which server won the loadbalancing.
For this the ha proxy is configured to loadbalance between its own frontends which has their own backend with their modified path
The configuration looks like this
defaults
retries 3
maxconn 20
timeout connect 5s
timeout client 6s
timeout server 6s
frontend http-in
bind *:9002
mode http
use_backend proxy-backend
backend proxy-backend
balance roundrobin
mode http
option forwardfor
http-response set-header X-Forwarded-Port %[dst_port]
http-response set-header X-ProxyServer %s
server proxy-server-1 localhost:9000
server proxy-server-2 localhost:9001
frontend proxy-in1
bind *:9000
mode http
use_backend poc-server2
frontend http-in2
bind *:9001
mode http
use_backend poc-server1
backend poc-server1
mode http
http-response set-header X-Server %s
http-request set-path /api/one/%[path]
server poc-server-1 proxypochost1:9000
backend poc-server2
mode http
http-response set-header X-Server %s
http-request set-path /api/two/%[path]
server poc-server-2 proxypochost2:9001
For more information you can check the whole project with some additional information in its readme here: ha-proxy-poc

HAproxy with multiple https sites

We have couple of http sites running behind load balancer ( with failover capability using hearbeat) and one https site. Everything is running fine but now i want to
add another https site. I couldn't find any references for hosting multiple https sites.
Has anyone hosted multiple https sites using HAproxy ? Can you please tell me how can i achieve this ? pls help me with your inputs.
Thanks,
Santhosh
You have to write rules to pick the backend either based on the frontend (IP address), Host header or TLS SNI ("Server Name Indicator"). What's best depends on your application really. If you need support for clients that don't support SNI (really old); then they won't get real TLS and you have to pick the backend based on the Host header.
Since I wrote the answer below haproxy has added ssl as a new feature. I use it on https://manage.ntppool.org/ and it's working nicely. You need the latest 1.5 development release (or 1.6 if that's out by the time you read this).
In HAProxy 1.8 http/2 is supported, too.
In 2012 the answer was:
HAProxy itself doesn't support SSL, you have to run an "SSL unwrapped" in front. Popular options are stunnel and stud. For HTTP you can also use Apache or Nginx.
You can launch any number of HTTPS enabled website using HAProxy. You have to do SSL offloading at HAProxy box. And ha-proxy will redirect requests to your server(site-box) via HTTP. You can distinguish between requests coming for your 2 different https website by parsing your URI, after SSL-ffloading at HA-Proxy
See HA-Proxy docs for more details, see hdr_dom and acl sections this will solve your problem.
Just for reference, you can get it with:
frontend http
bind :80
redirect scheme https code 301 if !{ ssl_fc }
frontend https
bind :443 ssl crt /etc/haproxy/ssl
reqadd X-Forwarded-Proto:\ https
option http-server-close
option forwardfor
# ACL for example1.com
acl ACL_example1.com hdr(host) -i example1.com
use_backend backend1 if ACL_example1.com
# ACL for example2.com
acl ACL_example2.com hdr(host) -i example2.com
use_backend backend2 if ACL_example2.com
backend backend1
balance roundrobin
server server1 192.168.1.10:80 check
server server2 192.168.1.20:80 check
backend backend2
balance roundrobin
server server3 192.168.1.30:80 check
server server4 192.168.1.40:80 check
In /etc/haproxy/ssl you must to have certificates in .pem format containing crt and key:
example1.com.pem
example2.com.pem
And use HAProxy above version 1.5

How to work with HTTPS for multiple domains and and sub-domains on localhost?

I am using
Apache
Ruby and Ruby on Rails 3
Mac Os running "Snow Leopard"
and I would like to use HTTPS on localhost for my domains and sub-domains.
I have already set everything (I think correctly):
I generated a wildcard certificate for my domains and sub-domains (example: *.sitename.com)
I have set base-named virtualhosts in the http.conf file listening on port :433 and :80
My browser accept certificates also if it alerts me that those aren't safe and I can have access to pages using HTTPS
From the official Apache guide I read that it is not possible to do that using name-based virtualhost, but I also read someone that made that in some way (what?! I don't understand...).
So, is it possible or not to use HTTPS in localhost for multiple domains and sub-domains? If so, what I must "to do"\"to check" for working with that?
UPDATE for #sarnold
typhoeus appears to use libcurl, and
libcurl appears to support SNI -- is
your version of libcurl new enough to
support SNI? Does typhoeous know how
to enable it? (Do clients of libcurl
need to "enable" it SNI themselves?)
I think so because I can access all sub_domains over HTTPS and libcurl should be updated:
curl -V--version
curl 7.21.2 (x86_64-apple-darwin10.5.0) libcurl/7.21.2 OpenSSL/1.0.0c zlib/1.2.5 libidn/1.19
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: IDN IPv6 Largefile NTLM SSL libz
# Typhoeus request
Typhoeus::Request.get("https://<sub_domain_name>.<domain_name>.com/")
How can I check if "Do clients of libcurl need to "enable" it SNI themselves?"?
The techniques for doing name-based virtual servers with SSL/TLS aren't great choices, but the Server Name Indication extension allows browsers to request a specific site by name, allowing different certificates to be used with different sites. Not all browsers support SNI yet.
Though one might ask what value there is is in having multiple certificates if they are all served out of the same process with the same privileges, anything to improve the user's TLS experience has to be worth the hassle. :)

Resources