Friday, November 13, 2020

Set Up Highly Available Web Servers with Keepalived and Floating IPs


Keepalived runs on an active LVS server as well as one or more optional backup LVS server. The active LVS server serves two roles:
  • To balance the load across the real servers.
  • To check the integrity of the services on each real server.
The active (master) server informs the backup server of its active status using the Virtual Router Redundancy Protocol (VRRP), which requires the master server to send out advertisements at regular intervals. If the active server stops sending advertisements, a new master is elected.

Prerequisites 

  • Need two linux servers any web server configured and should be up and running.
  • Port 80 should we open from firewall level
In this example I am using two CentOS-7 servers and I am using nginx as my webserver. You can use any OS and webserver as you like.


Nginx Server 1 --> 192.168.1.17
Nginx Server 2 --> 192.168.1.18




Install and configure Keepalived

Thin this setup we need another additional IP which need to configure as our VIP. This VIP can we assign to either "Webserver 1" or "Webserver-2".

In this example we are using 192.168.1.20 as our VIP.


  • Create a loopback interface in each servers (Webserver-1 and Webserver-2)
Go to below location and create a file call "ifcfg-lo:vip". This file should contain below content.

DEVICE=lo:vip
IPADDR=192.168.1.20 # Change this to your VIP
NETMASK=255.255.255.255
#NETWORK=
# If you're having problems with gated making 127.0.0.0/8 a martian,
# you can change this to something else (255.255.255.255, for example)
#BROADCAST=
ONBOOT=yes
NAME=loopback



  • Then UP the newly created interface
ifup ifcfg-lo:vip
 

 

  • Install keepalived in both servers
yum install keepalived


  • Enable the keepalived service
systemctl enable keepalived
 

  • Goto keepalived configuration folder and backup the existing configuration file. 

  • Create a nginx status check script with below content.

#!/bin/bash

_status=`pgrep -f "nginx.conf" | wc -l`

if [ $_status -gt 0 ];
then
        exit 0
else
        exit 1
fi

  • Set Execution permission for that script
chmod 755 /usr/bin/status_nginx
 
  • Create a keepalived.conf file and add below content in each server.
Values highlighted in yellow should be change according to your environment.

In Webserver-1 

vrrp_script chk_nginx_status {
    script "/usr/bin/status_nginx"
    interval 10
}

vrrp_instance Float_NGINX {
    state BACKUP
    interface enp0s3 #Interface ID
    virtual_router_id 93 #This should be unique within the network
    priority 101        #101 on master, 100 on backup
    advert_int 1
    nopreempt

    track_script {
        chk_nginx_status #Nginx status check script
    }

    virtual_ipaddress {
        192.168.1.20/24 #VIP need to assign
    }
}
 
virtual_server 192.168.1.20 80 {
        lvs_sched rr
        lvs_method DR
        protocol TCP
        real_server 192.168.1.17 80 {
        weight 1
        TCP_CHECK {
                connect_port 80
                connect_timeout 3
                retry 3
                delay_before_retry 2
                }
        }
        real_server 192.168.1.18 80 {
        weight 1
        TCP_CHECK {
                connect_port 80
                connect_timeout 3
                retry 3
                delay_before_retry 2
                }
        }
}

In Webserver-2

vrrp_script chk_nginx_status {
    script "/usr/bin/status_nginx"
    interval 10
}

vrrp_instance Float_NGINX {
    state BACKUP
    interface enp0s3 #Interface ID
    virtual_router_id 93 #This should be unique within the network
    priority 100        #101 on master, 100 on backup
    advert_int 1
    nopreempt

    track_script {
        chk_nginx_status #Nginx status check script
    }

    virtual_ipaddress {
        192.168.1.20/24 #VIP need to assign
    }
}
 
virtual_server 192.168.1.20 80 {
        lvs_sched rr
        lvs_method DR
        protocol TCP
        real_server 192.168.1.17 80 {
        weight 1
        TCP_CHECK {
                connect_port 80
                connect_timeout 3
                retry 3
                delay_before_retry 2
                }
        }
        real_server 192.168.1.18 80 {
        weight 1
        TCP_CHECK {
                connect_port 80
                connect_timeout 3
                retry 3
                delay_before_retry 2
                }
        }

} 

  • vrrp_instance defines an individual instance of the VRRP protocol running on an interface. I have arbitrarily named this instance VI_1.
  • state defines the initial state that the instance should start in.
  • interface defines the interface that VRRP runs on.
  • virtual_router_id is the unique identifier that you learned about in the first article of this series.
  • priority is the advertised priority that you learned about in the first article of this series. As you will learn in the next article, priorities can be adjusted at runtime.
  • advert_int specifies the frequency that advertisements are sent at (1 second, in this case).
  • virtual_ipaddress defines the IP addresses (there can be multiple) that VRRP is responsible for.
Now check the VIP is successfuly assign to a server. It can be Webserver-1 or Webserver-2

You can simply type "ip addr" command to verify this.



You have to install "ipvsadm" package to inspect the virtual server table. From this tool you can see available nodes under your keepalived instance.



Type below command to get the available instance 

ipvsadm -L -n


Now brows the website with VIP in your browser.


Now Try to shutdown the web-server which VIP current being assign. Once you shutdown it, VIP should automatically assign to other server. Try to access your side also after you shutdown the server.

Thursday, November 12, 2020

Apache with Self Signed Certificate

Apache with Self Signed Certificate

PREREQUISITE

  • Linux server with apache installed (Port 80 and 443 should open from FW)
  • There should be a DNS entry for your site. Local host entry is enough.
  • "openssl" package should be installed in your server.
  • Download this file to your server and extract. (Download Link)

In this example I am using Ubuntu 20.04 LTS server. Command can be different  you are using OS like Redhat or CentOS.

My site name is : my-testweb.nocompany.lk
We server IP     : 192.168.1.23

Add host entry for your site.


Step 01: Install Apache


apt install apache2


After install enable the service and start the apache2 service

systemctl enable apache2
systemctl start apache2


Now try to access default site using host name. 


Step 02: Create a Custom Page


Now create a virtual host configuration file with your custom website in below location.

Location : "/etc/apache2/sites-available"


<VirtualHost *:80>

        ServerName my-testweb.nocompany.lk
        ServerAlias my-testweb.nocompany.lk

        DocumentRoot /var/www/html/my-site

        ErrorLog ${APACHE_LOG_DIR}/my-testweb.nocompany.lk-error.log
        CustomLog ${APACHE_LOG_DIR}/my-testweb.nocompany.lk-access.log combined

</VirtualHost>

Create "DocumentRoot" folder and create simple index.html file.


Include that config file to site-enable folder.

Go to "/etc/apache2/sites-enabled" folder and execute this command.

ln -s ../sites-available/my-site.conf my-site.conf


Now restart the apache service and check.

systemctl restart apache2


Step 03: Obtain Self-sign Certificate


Download this file to your server and extract. (Download Link)


First generate CA certificate

Execute "./createCA.sh" to proceed.
Put strong password during CA certificate generation. 
For Common name, you can put your company name.


Cert Path.: sslCA/cacert.pem
Key Path.: sslCA/private/cakey.pem

Now generate host certificate and sign with CA certificate

Execute "./createHostCert.sh" to proceed. Please make sure to put your web site name under "Common Name". You can keep rest of the things default. Challenge password also you and keep as a blank. Just press enter. You have to put password you put for CA certificate for "cakey.pem"  


Press "y" to sign the certificate.

Once you successfully completed, it will generate two files. 
  • hostcert.pem --> Sign certificate for your website
  • hostkey.pem --> Key for your website certificate
Create a folder under "/etc/apache2/" call "ssl" and copy those files to "ssl" folder with below names.


Step 04: Make your Site Secure

Now enable SSL module for apache. Execute below command to do this. You have to restart the apache service to apply the changes. 

a2enmod ssl


Now open virtual host configuration file you created before and add another virtual host configuration block as follow.

You have to include certificated files you obtained to configuration files.

<VirtualHost *:443>

        ServerName my-testweb.nocompany.lk
        ServerAlias my-testweb.nocompany.lk

        DocumentRoot /var/www/html/my-site

        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/my-testweb.crt
        SSLCertificateKeyFile /etc/apache2/ssl/my-testweb.key

        ErrorLog ${APACHE_LOG_DIR}/ssl-my-testweb.nocompany.lk-error.log
        CustomLog ${APACHE_LOG_DIR}/ssl-my-testweb.nocompany.lk-access.log combined

</VirtualHost>



Restart the apache service to apply the changers.

systemctl restart apache2

Step 05: Import CA Certificate to your Browser

Now, you have to import CA certificate you generate previously, to your browser. First copy the CA certificate where your normal user can access. You can copy it to user's home directory.



Open your browser and go to where certificate and import. It can be different from browser to browser. Here I am using Firefox.



Go to Authorities tab and select "Import"


Then you have to navigate to CA certificate file. Once you select and open you have to trust this CA certificate for website. Then press "OK" button.


You can verify by go through CA list whether it is successfully imported or not.


Now brows your site with https and check whether certificated is downloading without any issue.



 

Wednesday, November 11, 2020

Apache with Letsencrypt


Let's Encrypt is a non-profit certificate authority run by Internet Security Research Group (ISRG) that provides X.509 certificates for Transport Layer Security (TLS) encryption at no charge. It launched on April 12, 2016.

Let's Encrypt certificates are valid for 90 days, during which renewal can take place at any time. The offer is accompanied by an automated process designed to overcome manual creation, validation, signing, installation, and renewal of certificates for secure websites. The project claims its goal is to make encrypted connections to World Wide Web servers ubiquitous.[6] By eliminating payment, web server configuration, validation email management and certificate renewal tasks, it is meant to significantly lower the complexity of setting up and maintaining TLS encryption.[1]

[1] Wikipedia

PREREQUISITE

  • Linux server with apache installed (Port 80 and 443 should open for public)
  • There should be a DNS entry for your site.
  • Enable "add-apt-repository universe" repo.
  • "certbot" packages should be install in your server.

In this example I am using Ubuntu 20.04 LTS server. Command can be different  you are using OS like Redhat or CentOS.



Step 01: Install Apache


apt install apache2



After install enable the service and start the apache2 service

systemctl enable apache2
systemctl start apache2



Now try to access your site using host name. 



Step 02: Create a Custom Page


Now create a virtual host configuration file with your custom website in below location.



<VirtualHost *:80>

        ServerName <Your-Site>
        ServerAlias <Your-Site>

        DocumentRoot /var/www/html/my-site

        ErrorLog ${APACHE_LOG_DIR}/vidu-test-error.log
        CustomLog ${APACHE_LOG_DIR}/vidu-test-access.log combined

</VirtualHost>

Create "DocumentRoot" folder and create simple index.html file.



Include that config file to site-enable folder.



Now restart the apache service and check.




Step 03: Obtain Letsencrypt Certificate


Enable "add-apt-repository universe" repo.



Now install "certbot"



Execute below command to obtain certificates.

certbot certonly --webroot --webroot-path /var/www/html/my-site -d <Your-Site> -m <Your-Email>



Step 04: Make your Site Secure

Now enable SSL module for apache. Execute below command to do this. You have to restart the apache service to apply the changes. 


Now open virtual host configuration file you created before and and add another virtual host configuration block as follow.

You have to include certificated files you obtained from letsencrypt.

<VirtualHost *:443>

        ServerName <Your-Site>
        ServerAlias <Your-Site>

        DocumentRoot /var/www/html/my-site

        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/vidu-test.ddns.net/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/vidu-test.ddns.net/privkey.pem

        ErrorLog ${APACHE_LOG_DIR}/ssl-vidu-test-error.log
        CustomLog ${APACHE_LOG_DIR}/ssl-vidu-test-access.log combined

</VirtualHost>

Restart the apache service to apply the changers.

systemctl restart apache2

Now its time to brows your site with https. 



Check your web site with SSL-LAB




You can add below configurations for your conf file to achieve "A" Grade.

To achieve, you have to disable insecure SSL cipher suit and insecure SSL protocols 

SSLCipherSuite "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA"

SSLProtocol -all +TLSv1.3 +TLSv1.2
SSLHonorCipherOrder On
SSLCompression off


Now you are one more step behind to achieve "A+" grade.

To do that you have to enable "mod_header" module in apache. You can include that module by executing this command.

Goto "/etc/apache2/mods-enabled" folder and create a symlink to "headers.load".

ln -s ../mods-available/headers.load headers.load


Now include below headers to conf file. 

Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff

After adding all the configurations.

<VirtualHost *:80>

        ServerName vidu-test.ddns.net
        ServerAlias vidu-test.ddns.net

        DocumentRoot /var/www/html/my-site

        ErrorLog ${APACHE_LOG_DIR}/vidu-test-error.log
        CustomLog ${APACHE_LOG_DIR}/vidu-test-access.log combined

</VirtualHost>

<VirtualHost *:443>

        ServerName vidu-test.ddns.net
        ServerAlias vidu-test.ddns.net

        DocumentRoot /var/www/html/my-site

        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/vidu-test.ddns.net/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/vidu-test.ddns.net/privkey.pem

        SSLCipherSuite "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA"

        SSLProtocol -all +TLSv1.3 +TLSv1.2
        SSLHonorCipherOrder On
        SSLCompression off

        Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
        Header always set X-Frame-Options DENY
        Header always set X-Content-Type-Options nosniff

        ErrorLog ${APACHE_LOG_DIR}/ssl-vidu-test-error.log
        CustomLog ${APACHE_LOG_DIR}/ssl-vidu-test-access.log combined

</VirtualHost>

Now restart the apahe service and check your site from SSL Lab.