Skip to main content

HAProxy

HAProxy implementation Case Study


This tutorial covers HAProxy Deployment on Firewall and SELinux enabled Centos7 systems.
First of all lets get an overall idea about my situation. 
I've bought a domain call mycompany.com so all of my  hosted sites should be followed by this main domain.
As an example, if someone look for london.mycompany.com he should reach to London server, if someone look for chicago.mycompany.com he should reach to Chicago server
So, I've created a Cloudflare account and point mycompany.com to our public IP address and created two                 CNAME entries from Cloudflare by adding London and Chicago.




From the Cloudflare all the request to mycompany.com will forward to our public address and HAProxy may read those requests and Process them and forward them accordingly between two IIS servers.

Note that all HTTPs connection should terminated at HAProxy.  Please see my post HTTPS for HAProxy
In this chapter we will look in to Load balancing and ACL based traffic routing between IIS web servers
As the first step I will add hosts entries for my hosts file
 vi /etc/hosts
 10.0.3.121 iiswebsrv01
 10.0.3.131 iiswebsrv02
You may ping and verify the connectivity between HAProxy server and your web servers.
Download and Enable the EPEL Repositories and install the HAProxy
wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
yum -y install HAProxy
  
After Successful installation of HAProxy, you can start configuration on HAProxy.
Prior to edit the configuration file its recommended to keep a backup of existing HAProxy configuration file
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg_bak

Now Let’s look at our HAProxy configurations
HAProxy configuration file contains four types sections
  1. Global Section which contains global configurations
  2. Default Section for default configurations
  3. Frontend sections which expose to Public to accepts the requests
  4. Backend sections which  define who to be should serve the requests which are forwarding from front end section.
 global
        log 127.0.0.1   local2                      #1
        maxconn 1024                                #2
        user haproxy                                #3
        group haproxy                               #4
        daemon                                      #5
        stats socket /var/run/haproxy.sock mode 600 level admin    #6        
 tune.ssl.default-dh-param 2048                             #7

1. In global section it is configured where to store our HAProxy logs, in here our HAProxy logs will be stored by using local rsyslog server
2. Maximum Connection count which is supposed accommodate using my HAProxy Server
3. Define HAProxy user which is already created with the installation
4. Define HAProxy group
5. State that HAProxy should run as a daemon process
6. In HAProxy you can monitor the performance by using status page or socket, this for socket usage.
7. Define the Maximum size of the temporary DHE Key for TLS

Now we are done with our global configurations...

It’s time to start our configurations on HAProxy Default Configuration
In default section we configure the default parameter for all frontend and backend sections
defaults
        log     global                        #1
        option  tcplog                        #2
        option  dontlognull                   #3
        retries 3                             #4
        option  redispatch                    #5
        maxconn 1024                          #6
        timeout connect 50000ms               #7
        timeout client 500000ms               #8
        timeout server 500000ms               #9
1. Define the log mode to use which we have already dud in Global configuration
2. option tcplog will logging will keep the logs on tcp (Layer 4) level.
         Note that you may also use httplog if you're willing to log on http level
3. dontlognull will filter the  log entries, this will keep your logs clean (By default even a simple port probe will produce a log, due to that HAProxy in order to avoid these type of log entries you may use this option)
4. This will set the number of retries after a fail attempts to the server
5. If a server designated by a cookie and it is down, clients may stick to this because they cannot flush the cookie, so this client will not be able be to the access the particular service anymore. So, this will allow the HAProxy to break their persistence and redistribute them to a working server.
6. Define the maximum connection count
7. Set the maximum time to a client to wait for the response
8. Set maximum inactive time on the client side
9. Set maximum inactive time on the server side

Now our basic Configuration is done let’s start to configuring the parameters for frontends and backends.

In frontend sections it will accept the traffic from public entities and process them, and it will forward the traffic to relevant backend.
In following front end section, I will demonstrate how to read  HTTP headers and process them with basic ACLs and forward them to relevant backend sections.

frontend http_handler
         bind *:80                                                                #1
         bind *:443 ssl crt /etc/haproxy/certs/hrms.itcstaging.com-0001.pem       #2
         mode http                                                                #3
         option httplog                                                           #4
         log global                                                               #5
         
                acl acl_london  hdr_beg(host) -i london                           #6
                acl acl_chicago hdr_beg(host) -i chicago                          #7
                use_backend be_london if acl_london                               #8
                use_backend be_chicago if acl_chicago                             #9
                default_backend be_welcome                                        #10
This frontend will accept all http and https request and process them with a ACL.  

1,2 In order to accept the traffic from port 80 (http) and 443 (https), shall we bind both 80,443 ports to a front end. Note that for https traffic it is required to have a SSL certificate.

Here in this tutorial I've created a SSL certificate using let’s encrypt (https://letsencrypt.org) (Please see my post HTTPs for HAProxy)

3 since our primary objective is to read those HTTP/HTTPs headers and forward the traffic accordingly we may use 'mode http', if you use the TCP mode instead you load balancing will be based on layer 4, if so we won't be able to read the HTTP header in our ACL

4 Here I have enable HTTP logging of HTTP/HTTPs Request

5 Add logs to the global syslog service

In HAProxy an ACL can define the "acl" keyword, ACLs can be defined in either backend or fronted. (In our scenario ACL have to be defined in the frontend section)

                acl <Name of the ACL> <criterion> [flags][option] values

6,7 I've initiated two acls for my two sites one london(acl_london) and one for chicago(acl_chicago), now as per the requirement it's required to read http headers and forward the traffic based on the content of the http headers.

In here I've used hdr_beg criterion which will test the http header with defined keyword. alternately you may use hdr(host)  which will test against the exact match of the header content.
Here with hdr_beg(host) I've use -i option ignore the case.
So, if there is any http request which contain london key word will activate the ACL "acl_london" and if there is any http request whoch contain chicago it will activate "acl_chicago"
Now we have defined the conditions for the ACLs, now we should instruct HAProxy to what should happen if that particular ACL entry is true

8,9 use_backend can be used to switch backends depends on the ACL output
               
                use_backend <desired backend> {if | unless} [Condition]
               
In our scenario if acl_london is true it should use the london backend (be_london), if acl_chicago is true it should use the chicago backend (be_chicago)

10. Now in practical scenarios, some HTTP requests may hit our frontends but failed on the ACLs, which means our ACLs happens to unidentified the which backend to use, on those kinds of scenarios we may use default_backend option which is not compulsory here

Now traffic come to our frontends and test against the ACLs, it’s time to define our backends to accommodate HTTP request and forward them to desired destination
backend be_london
                balance leastcon                                                  #1
                redirect scheme https if !{ ssl_fc }                              #2          
                option forceclose                                                 #3
                option forwardfor                                                 #4
                stick match src                                                   #5
                stick-table type ip size 200k expire 30m                          #6
                mode http                                                         #7
                reqadd X-Forwarded-Proto:\ http                                   #8
                cookie SERVERID insert indirect nocache                           #9
                option httpchk GET /check.aspx?testsrv=londonsrv01:8080           #10
                http-check expect string 200\ OK                                  #11
                server london_01 iiswebsrv01:94 cookie L01 check                  #12
                server london_02 iiswebsrv02:94 cookie L02 check                  #12

1 balance key word state the balancing which balancing algorithm to use when HAProxy selecting the destination servers
               
                balance <algorithms> [argument]
               
HAProxy proxy provides various balancing algorithms to balance the load between the servers
  • leastconcon : Selects the server with the least number of connections--This is recommended for longer sessions. Servers in the same backend are also rotated in a round-robin fashion. 
  • roundrobin : Round Robin selects servers in turns. This is the default algorithm. 
  • source : This selects which server to use based on a hash of the source IP i.e. user's IP address. This is one method to ensure that a user will connect to the same server. 
2 Now for the security purposes I prefer only to use HTTPS. so in the backends, here we forcefully filter the traffic only to use HTTPs.
Note that In TCP mode, HAProxy doesn't actually even terminate SSL, it just passes the packets on to the backend.
For additional information, ssl_fc: Returns true when the front connection was made via an SSL/TLS transport layer and is locally deciphered.

4 This will enable X-Forwarding the HTTP connections.
                What is X-Forwarding, HAProxy act as a revers proxy which we already know. when it comes to your server side, the server will only see the ip address of HAProxy server as the client address which sometimes it may cause some issues. By using X-Forwarding, HAProxy will append the original IP address of the client when requests are sending to the server.

3 By default HAProxy operates in keep alive mode with the connection and keep connection idle from both the Client and Server.
 Simply " option forceclose" will check if “Connection: close" header is already set in each direction and will add the Connection close if not including headers and will kill the connection. (Also, any "Connection" header different from "close" will also be removed) 

5 stick match statement define a rule to extract the stickiness criterion from an incoming request or connection.

6 This is to configure the sticky table. These stick tables will keep learned data on the memory from the connection. Note that restarting the service will remove those sticky entries (To overcome this issue you may implement HAProxy peering with secondary HAProxy server).  
               
7 mode http is optional since  we have already define it on default Section .

8 In here we are adding a header to all HTTP request's which are passing through this backend (Header transformations only apply to traffic which passes through HAProxy)

9 Adding Cookie values to  HTTP requests. This value will be checked in incoming requests, and the first operational server possessing the same value will be selected. In return, in cookie insertion or rewrite modes, this value will be assigned to the cookie sent to the client.

10 Before forward the traffic to the destination servers it is wise to check the availability of those servers using httpchk. It will point to "from where" HAProxy should get this information.
                Additionally, I've created a separate sites on both of my chicago and london servers which will give us an output saying "200 OK", based on the readiness of this content HAProxy will figure it out that particular destination server is ready serve. (I've put this sample html script later on this tutorial)
               
11 Now HAProxy test previous readings from the httpchk and test it

It’s time to us to define our backend servers. Back end servers can define using "server".
                server <name> <server address>[:[port]] [param*]
               
12 Here in our configuration I've defined a name for particular cookies from london_01 server.
The check parameter will do the test based on our previous html script

And you may add the other Back End servers as well.

Now we are done with the configuration..

Once you complete the HAProxy configuration you may check the configurations by     

haproxy -f /etc/haproxy/haproxy.cfg -c

To restart the HAProxy

systemctl restart haproxy
You may fall in to some SELinux related issue, which some destination ports are not allowed by SELinux in Such a scenario you may use following command,

semanage port --add --type http_port_t --proto tcp <port>
               
You may require to open firewall ports, to do that use     

firewall-cmd --permanent --add-port=\tcp
firewall-cmd --reload



Complete Configuration Sample



global
        log 127.0.0.1   local2
        maxconn 1024
        user haproxy
        group haproxy
        daemon
        stats socket /var/run/haproxy.sock mode 600 level admin         
  tune.ssl.default-dh-param 2048     

defaults
        log     global
        option  tcplog
        option  dontlognull
        retries 3
        option  redispatch
        maxconn 1024
        timeout connect 50000ms
        timeout client 500000ms
        timeout server 500000ms

###########################
#Front Ends Configurations#
###########################
frontend http_handler
 bind *:80
 bind *:443 ssl crt /etc/haproxy/certs/hrms.itcstaging.com-0001.pem
 mode http
 option httplog
        log global

 acl acl_london  hdr_beg(host) -i london        
 acl acl_chicago hdr_beg(host) -i chicago
 

 use_backend be_london if acl_london         
 use_backend be_chicago if acl_chicago         
 default_backend be_welcome     

###########################
#Back  Ends Configurations#
###########################
backend be_london
 balance leastcon           
 redirect scheme https if !{ ssl_fc }                                   
        option forceclose          
 option forwardfor          
        stick match src           
        stick-table type ip size 200k expire 30m    
        mode http            
        reqadd X-Forwarded-Proto:\ http       
        cookie SERVERID insert indirect nocache     
        option httpchk GET /check.aspx?testsrv=iiswebsrv01:8080 
        http-check expect string 200\ OK      
        server london_01 iiswebsrv01:94 cookie L01 check  
 server london_02 iiswebsrv02:94 cookie L02 check  

backend be_chicago
 balance leastcon           
 redirect scheme https if !{ ssl_fc }                                   
        option forceclose          
 option forwardfor          
        stick match src           
        stick-table type ip size 200k expire 30m    
        mode http            
        reqadd X-Forwarded-Proto:\ http       
        cookie SERVERID insert indirect nocache     
        option httpchk GET /check.aspx?testsrv=iiswebsrv01:8080 
        http-check expect string 200\ OK      
        server london_01 iiswebsrv01:94 cookie L01 check  
 server london_02 iiswebsrv02:94 cookie L02 check  


Sample HTTP check html Script

<!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
         <head>
             <title>
             Mediatools Check
             </title>
         </head>
         <body id="bodyID">
                200 OK
         </body>
</html>

Comments

Post a Comment

Popular posts from this blog

Asterisk on Docker

This Document covers asterisk basic installation on docker. Since till now there is no official asterisk image on Docker hub we will use Debian core to install the asterisk. Prerequisites Linux host to install docker, Internet connectivity and docker account to download docker images. 1. Installing Docker (Ensure your Internet connectivity) Centos 7           #wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm           #rpm -ivh epel-release-latest-7.noarch.rpm           #yum install docker  Install Docker on RHEL and CentOS 6          # yum install epel-release          # yum install docker-io 2. Start Docker Centos 7          # systemctl start docker          # systemctl status docker          # systemctl enable docker  On RHEL/CentOS 6          # service docker start          # service docker status          # chkconfig docker on Our Asterisk PBX will reside on Debain, So first we must set our Debian container

Simple Squid (Proxy server) Configuration

1.  SETUP THE INITIAL NETWORK CONNECTIVITY ON CENTOS After installing centos completely configured the network interfaces as follows, 1. Add a network interface to centos virtual machine as “Lan segment”(Centos lan) 2. And configure the ip address for that LAN segment If this centos machine has only one NIC we have to create two vlans and trunk them.             One to connect to the internet.            One to connect to the local area network interface which we created earlier 3. Using fedora(Another vm guest os) verify the network connectivity 4. Pinging to the LAN-segment that we created in order to verify the internet connectivity. Now we are connected to the private network that we created using centos earlier. Note that in this scenario centos is act as a router. So we are going to convert this centos virtual machine to router, in order to do that we need to inform it to kernel and configure it. Using sysctl command,

Asterisk Gateway Interface - Perl

Asterisk Gateway Interface 1. What is Asterisk Gateway Interface?  In simple word AGI is Language Independent API to programmers to control the call flow on their Asterisk PBXs. Asterisk provides more than its own dial-plan, to control to the call flow or lets say call logics. So which means you may use either one of Dialplan Asterisk Manager Interface (AMI) Asterisk Gateway Interface (AGI) to manipulate your call logics. Before we move on to AGI lets briefly discuss about each one of above, Dialplan Dial plan is Asterisk native call logics performer, it's fast, easy to learn and efficient. But this configuration script is more closer to assembly program (If you have any previous experience on assembly), the main drawback of the Asterisk Dialplan in it's lack of support on standard procedural  language as an example when you want create a loop.  Any way in the following tutorials we will only discuss about the AGI, But we can't avoi

FreePBX-Installation

FreePBX-Installation 1. Pre-installation In order to setup call center server first we have to confirm that our system is full filled the minimum requirements. This asterisk deployment is based on RedHat distribution aka CentOS.  To full-fill the above requirement we are going to setup asterisk 11 on CentOS 6.5 (x64). 1.2 CentOS 6.5x64 installation  It is recommended to install CentOS 6.5x64 minimum version and manually install all the other package as our requirement.  At the beginning it recommended to configure the logical disk drives aka Raid.  Note that some of the server-rigs will not compatible to centos 6.5x64, most of the time it’s because the particular server’s Raid drivers might not be found in centos 6.5x64 disk. In such scenario please follow the below instruction. First we have to download the Raid driver from relevant vendor. (If it’s HP you will find somewhat like this hpvsa-X.X.X-X.rhel6u.5x86_64.dd). Note that if the dr

Discussion : SIP vs BRI/PRI

SIP SIP standards for Session Initiation Protocol and It's Purely IP based.  BRI/PRI PRI stands for Primary Rate Interface and It contains One 64Kbps T1 or E1 Chanel for Signaling AKA Channel D and 23 T1 or 30 E1 Channels as Bearing Chanel aka Channel B.\ BRI standards for Basic Rate Interface and Contain Two Barer channel and One Signaling Chnnel AKA 2B+D. Further Both Both PRI and BRI are ISDN services and also data rate of PRI is 2.048Mbps while 128-144Kbps. ISDN : Integrated Service Digital Network / It's Some Dumb Network SIP vs BRI/PRI SIP does Best effort Delivery as same as IP traffic do, while BRI/PRI Provide QoS. If someone requires to attain QoS through SIP something like MPLS will do with a considerable amount cost. SIP is more flexible than BRI/PRI because it can be accommodated by company existing data network while BRI/PRI reuires to have a dedicated link for it self.

RHEL Recover your root Password

Root Password recovery In this tutorial I will demonstrate you how to recover you lost password. This tutorial is for RHEL 7 Password recovery. Before we go further I would like to brief Linux boot process, When pushed power button your PC/Server it will powered on and the system firmware will runs POST (Power On Self Test) which will check and initiate attached hardware. You can do modifications to these process by BIOS/UFFI configuration After POST, system firmware will look for bootable device in other words it look for Master Boor Record (MBR) Then the System will reads the boot loader from the disk and let boot loader to take control of the system Now the boot loader loads its configuration from disk, at that point you may display the boot options Depends on your selection boot loader will load the kernel and initramfs from disk to you memory(RAM). Initramfs  is some gziped archive contains kernel modules for hardware all hardware which requ

Perl - Database Transactions

Database Transactions with Perl To understand what is a database transaction lets look at a simple bank withdrawal and deposit scenario. Assume that you have two bank accounts call A and B, and you need withdraw some amount from account A and Deposit it on account B. In this scenario what happen if you couldn't withdraw money from your account A, the deposit part won't carry out. Again if you couldn't deposit the money to your account B you have to deposit them back on account A (Which means a roll back). So in the  context of Database, Transaction is refer to  a sequence of jobs which is supposed to run as a whole. So in other words, it should happen as whole or not. So as in our following example, we have 3 Database queries which should perform as a whole. Further assume that our first Database query is supposed to perform a insert if successful, second query  should update a table if successful, third query  should delete an entry from a table.  So i

Share-A-Directory-between-two-server-NFS

Share-A-Directory-between-two-server-NFS Please grant the relevant permission on the shell scripts ./client_Export.sh Takes three argument as follows 1. server ip address to be exported 2. client directory which should be exported to the particular server 3. options aka permission for the expoted folder rw: This option allows the client server to both read and write within the shared directory sync: Sync confirms requests to the shared directory only once the changes have been committed. no_subtree_check: This option prevents the subtree checking. When a shared directory is the subdirectory of a larger filesystem, nfs performs scans of every directory above it, in order to verify its permissions and details. Disabling the subtree check may increase the reliability of NFS, but reduce security. no_root_squash: This phrase allows root to connect to the designated directory E