We analyze the proxy methods based on HAProxy

Recently, I had to deal with proxying access to web servers using HAProxy. The main problem was encrypted access. Who cares about this topic, welcome to cat.

There are a number of web servers in our company. To save addresses, access to them is organized through HAProxy. Something like this:



In this case, the configuration of HAProxy itself is extremely simple ( example No. 1 ):

frontend http_frontend
bind *: 80
mode http
option httpclose
acl is_mytest1 hdr_end (host) -i mytest1.loc
use_backend mytest1_web if is_mytest1
acl is_mytest2 hdr_end (host) -i mytest2.loc
use_backend mytest2_web if is_mytest2

backend mytest1_web
mode http
cookie SERVERID insert indirect nocache
server mytestweb1 192.168.1.5:80 check cookie mytestweb1

backend mytest2_web
mode http
cookie SERVERID insert indirect nocache
server mytestweb2 192.168.1.10:80 check cookie mytestweb2


Here and below I will give not complete examples of the config file, but only those that are of interest us pieces.

Extremely simple - listen to port 80 and parse all incoming traffic. If mytest1.loc is requested, then it falls into the access-list is_mytest1, in this case the mytest1_web backend is used, in which we redirect traffic to the internal host 192.168.1.5, where this site is located. Similarly for mytest2.loc. Everything is extremely simple and at the same time we save real IP addresses.

The question of fault tolerance arose, especially since in a neighboring city we also have servers where we can raise these websites. Well, there is a virtual machine with Linux in the Amazon cloud, which does the same thing, but for sites located in the cloud. Can we use 2 HAProxy in a row? We take a test circuit like this and look:



HAProxy2 and HAProxy3 configurations have not changed, but a balancing parameter has been added to HAProxy1 ( example No. 2 ):

frontend http_frontend
bind *: 80
mode http
option httpclose
acl is_mytest1 hdr_end (host) -i mytest1.loc
use_backend mytest1 if is_mytest1
acl is_mytest2 hdr_end (host) -i mytest2.loc
use_backend mytest2_web if is_mytest2

backend mytest1_web
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server HAProxy1 1.1.1.1:80 check cookie haproxy1_1
server HAProxy2 3.3.3.3:80 check cookie haproxy2_1

backend mytest2_web
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server HAProxy1 1.1.1.1 cookie haproxy1_3
server HAProxy2 3.3.3.3:80 check cookie haproxy2_3


Everything worked fine. It would seem that you can rejoice, but here it was decided to redo the sites for work through SSL. And the problems started.

Let's go back to the beginning and consider everything from the beginning. The first assumption is that we do not need to encrypt traffic between the proxy server and the site itself. Second, we don’t need to worry about binding the certificate to the site, that is, we use self-signed certificates everywhere.



What do we need to do? Generate and install a self-signed certificate on our HAProxy server, then the client, accessing the site, will go to our proxy server, take its certificate, establish a secure connection to the server and then redirect to the website. Moreover, for all sites located behind the proxy server, one certificate will be used.

So let's get started. We generate:

openssl req -new -x509 -nodes -out server.crt -keyout server.key We

write in one file:

cat server.key> /etc/ssl/mytest.loc.pem
cat server.crt >> /etc/ssl/mytest.loc.pem


And edit the HAProxy configuration ( example 3 ):

frontend http_frontend
bind *: 80
mode http
option httpclose
acl is_mytest1 hdr_end (host) -i mytest1.loc
use_backend mytest1_web if is_mytest1
acl is_mytest2 hdr_end (host) -i mytest2.loc
use_backend mytest2_web if is_mytest2

backend mytest1_web
mode http
balance roundrobin
cookie SERVERID insert nocache indirect
server mytestweb1 check 192.168.1.5:80 cookie mytestweb1

backend mytest2_web
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server mytestweb2 192.168.1.10:80 check cookie mytestweb2

frontend https_frontend
bind *:443 ssl crt /etc/ssl/mytest.loc.pem
mode http
option httpclose
acl is_mytest1 hdr_end(host) -i mytest1.loc
use_backend mytest1_web if is_mytest1
acl is_mytest2 hdr_end(host) -i mytest2.loc
use_backend mytest2_web if is_mytest2


Кстати, проверять конфигурацию перед перезапуском — это очень полезная привычка:

haproxy -c -f /etc/haproxy/haproxy.cfg
Configuration file is valid


Проверяем и видим, что все отлично работает.

Well, now let's take the case when each site has its own certificate, not self-signed, but purchased. And it has a strict binding to the site name. In this case, we can solve the problem in two ways: place certificates for sites on a HAProxy server or proxy TCP instead of HTTP. But in both cases, we will not be able to get by with one IP address for our two sites.

Consider the first case:



The only difference between this case and the previous one (with self-signed certificates) is that here we have to listen to individual interfaces and issue a certificate depending on the interface ( example No. 4 ):

frontend http_frontend
bind *: 80
mode http
option httpclose
acl is_mytest1 hdr_end (host) -i mytest1.loc
use_backend mytest1_web if is_mytest1
acl is_mytest2 hdr_end(host) -i mytest2.loc
use_backend mytest2_web if is_mytest2

backend mytest1_web
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server mytestweb1 192.168.1.5:80 check cookie mytestweb1

backend mytest2_web
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server mytestweb2 192.168.1.10:80 check cookie mytestweb2

frontend https_frontend_site1
bind 1.1.1.1:443 ssl crt /etc/ssl/mytest.loc1.pem
mode http
option httpclose
acl is_mytest1 hdr_end(host) -i mytest1.loc
mytest1_web if is_mytest1 use_backend

frontend https_frontend_site2
bind 9.9.9.9:443 ssl crt /etc/ssl/mytest.loc2.pem
mode http
option httpclose
acl is_mytest2 hdr_end (host) -i mytest2.loc
use_backend mytest2_web if is_mytest2


Like all clear if traffic came to the interface with the address 1.1.1.1, which means that the client requests the site mytest1.loc. So, we issue him a certificate of this site and then proxy to backend mytest1_web .

In the second case, we forward all the TCP traffic that came to us on port 443. This is worth doing, for example, when, for whatever reason, you do not want site certificates to be stored on a proxy server. Or, for example, do not trust the internal network between proxies and web servers.



Configuration HAProxy will be approximately as follows ( Example №5 ):

frontend mytest1_frontend
bind 1.1.1.1:443
mode tcp
use_backend mytest1_webssl

backend mytest1_webssl
mode tcp
option ssl-hello-chk
server mytestweb 192.168.1.5:443

frontend mytest2_frontend
bind 9.9.9.9:443
mode tcp
use_backend mytest2_webssl

backend mytest2_webssl
mode tcp
option ssl-hello-chk
server mytestweb 192.168.1.10-00-0043


It seems like a pretty clear configuration. Perhaps it’s worth saying that since we forward all TCP traffic, we cannot analyze it, and therefore the presence of any access-lists in the frontend part will throw an error.

It is time to return to our task with the division of web sites in different cities. To begin with, consider a simpler case:



Since we have the Internet between HAProxy1 and HAProxy2, even when using self-signed certificates we cannot use HTTP PROXY MODE on HAProxy1, otherwise all meaning in encrypting such a connection is lost. We will use tcp mode on HAProxy1, and http mode on HAProxy2.

Configuration for HAProxy1 ( example No. 6 ):

frontend https_frontend
bind *:443
mode tcp
use_backend https_web

backend https_web
mode tcp
option ssl-hello-chk
server haproxy2 1.1.1.1:443


Конфигурация для HAProxy2 будет идентична конфигурации в примере №3ю

Настало время добавить вторую часть серверов:


Конфигурация для HAProxy1 (пример №7):

frontend https_frontend
bind *:443
mode tcp
use_backend https_web

backend https_web
mode tcp
balance roundrobin
option ssl-hello-chk
server haproxy2 1.1.1.1:443 check
server haproxy3 3.3.3.3:443 check


All the difference between this example and the previous one is the presence of balancing and fault tolerance between HAProxy2 and HAProxy3, which, according to our condition, should be in different cities.

Well, the last example would be if there are self-signed certificates. Suppose that they are installed on HAProxy servers - as in example No. 4 : The



configuration for HAProxy1 will be as in the previous example, and for HAProxy2 - as in example No. 4 . The same for HAProxy3 with minor changes to the real addresses of the frontend part.

It is also worth saying that you can configure all 3 HAProxy servers in TCP MODE - and this will also be a workable solution.

And finally, I would like to say: if someone knows some fundamentally different solutions for this task, I would be grateful if you share them.

A small update. I thought here that if we forward traffic, then we don’t need to use a set of different IP addresses on HAProxy2 and HAProxy3, it is much easier to just use different ports.
Let's look at this scheme:


We have two different host sites in different cities. One is behind HAProxy2 and the second is behind HAProxy3. And the central proxy server on which the balancing task lies, while the sites www.mytest1.loc and www.mytest2.loc must be balanced, and the site www.mytest3.locexists only on one site, so access to it should only be forwarded through a proxy server. All sites should be accessible both via HTTP and HTTPS with non-signed certificates.
Configuration HAProxy1:
frontend http_frontend
bind *: 80
mode http
option httpclose
acl is_mytest1 hdr_end (host) -i mytest1.loc
use_backend mytest1_web if is_mytest1
acl is_mytest2 hdr_end (host) -i mytest2.loc
use_backend mytest2_web if is_mytest2
acl is_mytest3 hdr_end (host) - i mytest3.loc
use_backend mytest3_web if is_mytest3

backend mytest1_web
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server mytestweb1 1.1.1.1:80 check cookie mytestweb1
server mytestweb1 2.2.2.2:80 check cookie mytestweb1

backend mytest2_web
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server mytestweb2 1.1.1.1:80 check cookie mytestweb2
server mytestweb2 2.2.2.2:80 check mytestweb2

backend mytest3_web
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server mytestweb3 2.2.2.2:80 check cookie mytestweb3

frontend mytest1_frontend
bind 3.3.3.3-00-0043
mode tcp
use_backend mytest_webssl1

backend mytest_webssl1
mode
tp balance
option ssl-hello-chk
server mytestweb1 1.1.1.1► 5551
server mytestweb2 2.2.2.2►5551

frontend mytest2_frontend
bind 4.4.4.4-00-0043
mode tcp
use_backend mytest_webssl2

backend mytest_webssl2
mode tcp
balance roundrobin
option ssl-hello-
ch.1.1 55552
server mytestweb2 2.2.2.2Point5552

frontend mytest3_frontend
bind 5.5.5.5-00-0043
mode tcp
use_backend mytest_webssl3

backend mytest_webssl3
mode tcp
balance roundrobin
option ssl-hello-chk
server mytestweb2 2.2.2.2►5553

And configuration

frontend_front http3
bind *: 80
mode http
option httpclose
acl is_mytest1 hdr_end (host) -i mytest1.loc
use_backend mytest1_web if is_mytest1
acl is_mytest2 hdr_end (host) -i mytest2.loc
use_backend mytest2_web if
is_mytest2
aclr_test_l__test_lb_lb the if is_mytest3 mytest3_web

the frontend mytest1_frontend
the bind 2.2.2.2:55551 an ssl crt /etc/ssl/mytest1.loc.pem
mode http
option httpclose
option forwardfor
reqadd the X-Forwarded-the Proto: \ https
use_backend mytest1_web

the frontend mytest2_frontend
the bind 2.2.2.2:55552 an ssl crt /etc/ssl/mytest2.loc.pem
mode http
option httpclose
option forwardfor
reqadd X-Forwarded-Proto: \ https
use_backend mytest2_web

frontend mytest3_frontend
bind 2.2.2.2-025553 ssl crt /etc/ssl/mytest3.loc.pem
mode http
option httpclose
option forwardfor
reqadd X-Forwarded-Proto: \ https
use_back

backend mytest1_web
mode http
balance roundrobin
stats enable
cookie SERVERID insert indirect nocache
server mytestweb1 192.168.1.5:80 check cookie mytestweb1

backend mytest2_web
mode http
balance roundrobin
stats enable
cookie SERVERID insert indirect nocache
server mytestweb2 192.168.1.10:80 check cookie mytestweb2

backend mytest3_web
mode http
balance roundrobin
stats enable
cookie SERVERID insert indirect nocache
server mytestweb3 192.168.1.15:80 check cookie mytestweb3

Also popular now: