Powered by Blogger.

How to Secure CentOS 7 Server with ModSecurity

ModSecurity is an open source web application firewall which enables web application defenders to gain visibility into HTTP traffic and provides powerful rule sets to enhance high security and protection. It provides a full package with real-time web monitoring, logging and access control. The rule sets can be customized and managed according to the user preferences. The freedom to choose what to do is an essential advantage of ModSecurity and really adds to the context of an open source. With full access to the source code, we've the ability to customize and extend the tool to fit our needs.


In this article, I'm explaining how to install and configure ModSecurity on a CentOS 7 server. Let's walk through the installation steps.

First of all, I would like to verify the server settings, mainly the present Apache version and the modules installed.


[root@server1 ~]# httpd -V
Server version: Apache/2.4.6 (CentOS)
Server built: Nov 19 2015 21:43:13
Server's Module Magic Number: 20120211:24
Server loaded: APR 1.4.8, APR-UTIL 1.5.2
Compiled using: APR 1.4.8, APR-UTIL 1.5.2
Architecture: 64-bit
Server MPM: prefork
threaded: no
forked: yes (variable process count)
Server compiled with....
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=256
-D HTTPD_ROOT="/etc/httpd"
-D SUEXEC_BIN="/usr/sbin/suexec"
-D DEFAULT_PIDLOG="/run/httpd/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"

You can use these command to identify the dynamically compiled modules enabled with Apache.


[root@server1 ~]# httpd -M
Loaded Modules:
core_module (static)
so_module (static)
http_module (static)
access_compat_module (shared)
actions_module (shared)
alias_module (shared)
allowmethods_module (shared)
auth_basic_module (shared)
auth_digest_module (shared)
authn_anon_module (shared)
authn_core_module (shared)
authn_dbd_module (shared)
authn_dbm_module (shared)
authn_file_module (shared)
authn_socache_module (shared)
authz_core_module (shared)
authz_dbd_module (shared)
authz_dbm_module (shared)
authz_groupfile_module (shared)
authz_host_module (shared)
authz_owner_module (shared)
authz_user_module (shared)
autoindex_module (shared)
cache_module (shared)
cache_disk_module (shared)
data_module (shared)
dbd_module (shared)
deflate_module (shared)
dir_module (shared)
dumpio_module (shared)
echo_module (shared)
env_module (shared)
expires_module (shared)
ext_filter_module (shared)
filter_module (shared)
headers_module (shared)
include_module (shared)
info_module (shared)
log_config_module (shared)
logio_module (shared)
mime_magic_module (shared)
mime_module (shared)
negotiation_module (shared)
remoteip_module (shared)
reqtimeout_module (shared)
rewrite_module (shared)
setenvif_module (shared)
slotmem_plain_module (shared)
slotmem_shm_module (shared)
socache_dbm_module (shared)
socache_memcache_module (shared)
socache_shmcb_module (shared)
status_module (shared)
substitute_module (shared)
suexec_module (shared)
unique_id_module (shared)
unixd_module (shared)
userdir_module (shared)
version_module (shared)
vhost_alias_module (shared)
dav_module (shared)
dav_fs_module (shared)
dav_lock_module (shared)
lua_module (shared)
mpm_prefork_module (shared)
proxy_module (shared)
lbmethod_bybusyness_module (shared)
lbmethod_byrequests_module (shared)
lbmethod_bytraffic_module (shared)
lbmethod_heartbeat_module (shared)
proxy_ajp_module (shared)
proxy_balancer_module (shared)
proxy_connect_module (shared)
proxy_express_module (shared)
proxy_fcgi_module (shared)
proxy_fdpass_module (shared)
proxy_ftp_module (shared)
proxy_http_module (shared)
proxy_scgi_module (shared)
proxy_wstunnel_module (shared)
systemd_module (shared)
cgi_module (shared)
php5_module (shared)
Installation

Once verifying the Apache setup, you can install ModSecurity package from the CentOS base repo.


[root@server1 yum.repos.d]# yum install mod_security -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirror.metrocast.net
* extras: mirror.metrocast.net
* updates: mirror.metrocast.net
Resolving Dependencies
--> Running transaction check
---> Package mod_security.x86_64 0:2.7.3-5.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===============================================================================================================================================
Package Arch Version Repository Size
===============================================================================================================================================
Installing:
mod_security x86_64 2.7.3-5.el7 base 177 k

Transaction Summary
===============================================================================================================================================
Install 1 Package

This will install the mod_security on your server. Now we need to configure it on our server.
Check and confirm the integration of the module to Apache

Check for the configuration file generated with the default set of rules. The configuration file will be located inside the Apache custom modules folder "/etc/httpd/conf.d/".


[root@server1 conf.d]# pwd
/etc/httpd/conf.d
[root@server1 conf.d]# ll mod_security.conf
-rw-r--r-- 1 root root 2139 Jun 10 2014 mod_security.conf

[root@server1 conf.d]# httpd -M | grep security
security2_module (shared)

Now restart the Apache and verify whether the Mod_security module is loaded on restart in the Apache logs.


[root@server1 conf.d]# tail -f /etc/httpd/logs/error_log
Mon Apr 18 06:24:35.170359 2016] [suexec:notice] [pid 2819] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Mon Apr 18 06:24:35.170461 2016] [:notice] [pid 2819] ModSecurity for Apache/2.7.3 (http://www.modsecurity.org/) configured.
[Mon Apr 18 06:24:35.170469 2016] [:notice] [pid 2819] ModSecurity: APR compiled version="1.4.8"; loaded version="1.4.8"
[Mon Apr 18 06:24:35.170476 2016] [:notice] [pid 2819] ModSecurity: PCRE compiled version="8.32 "; loaded version="8.32 2012-11-30"
[Mon Apr 18 06:24:35.170483 2016] [:notice] [pid 2819] ModSecurity: LUA compiled version="Lua 5.1"
[Mon Apr 18 06:24:35.170488 2016] [:notice] [pid 2819] ModSecurity: LIBXML compiled version="2.9.1"
[Mon Apr 18 06:24:35.451568 2016] [auth_digest:notice] [pid 2819] AH01757: generating secret for digest authentication ...
[Mon Apr 18 06:24:35.452305 2016] [lbmethod_heartbeat:notice] [pid 2819] AH02282: No slotmem from mod_heartmonitor
[Mon Apr 18 06:24:35.501101 2016] [mpm_prefork:notice] [pid 2819] AH00163: Apache/2.4.6 (CentOS) PHP/5.4.16 configured -- resuming normal operations

From the logs, you can identify the ModSecurity version loaded and other details.
Identifying the Nature

We need to go through the ModSecurity configuration file to identify the include path for the custom rules which we can add for customization and also identify the log file path for further analysis.

We can add the custom rules inside this path according to the configuration.


# ModSecurity Core Rules Set configuration
IncludeOptional modsecurity.d/*.conf
IncludeOptional modsecurity.d/activated_rules/*.conf

[root@server1 modsecurity.d]# pwd
/etc/httpd/modsecurity.d
[root@server1 modsecurity.d]# ll
total 4
drwxr-xr-x 2 root root 4096 Jun 10 2014 activated_rules

And we can inspect the log file at /var/log/httpd/modsec_audit.log
Customizing ModSecurity with the Core rule sets

We can get the custom rule sets from the official repo. These rule sets are automatically symlinked to the activated rules and make it effective on install by default.


root@server1 conf.d]# yum -y install mod_security_crs
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirror.metrocast.net
* extras: mirror.metrocast.net
* updates: mirror.metrocast.net
Resolving Dependencies
--> Running transaction check
---> Package mod_security_crs.noarch 0:2.2.6-6.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===============================================================================================================================================
Package Arch Version Repository Size
===============================================================================================================================================
Installing:
mod_security_crs noarch 2.2.6-6.el7 base 90 k

These are the general core rule sets installed from the official repo file. We need to modify certain rules to prevent from blocking the legitimate server requests.


[root@server1 base_rules]# ll
total 332
-rw-r--r-- 1 root root 1980 Jun 9 2014 modsecurity_35_bad_robots.data
-rw-r--r-- 1 root root 386 Jun 9 2014 modsecurity_35_scanners.data
-rw-r--r-- 1 root root 3928 Jun 9 2014 modsecurity_40_generic_attacks.data
-rw-r--r-- 1 root root 2610 Jun 9 2014 modsecurity_41_sql_injection_attacks.data
-rw-r--r-- 1 root root 2224 Jun 9 2014 modsecurity_50_outbound.data
-rw-r--r-- 1 root root 56714 Jun 9 2014 modsecurity_50_outbound_malware.data
-rw-r--r-- 1 root root 22861 Jun 9 2014 modsecurity_crs_20_protocol_violations.conf
-rw-r--r-- 1 root root 6915 Jun 9 2014 modsecurity_crs_21_protocol_anomalies.conf
-rw-r--r-- 1 root root 3792 Jun 9 2014 modsecurity_crs_23_request_limits.conf
-rw-r--r-- 1 root root 6933 Jun 9 2014 modsecurity_crs_30_http_policy.conf
-rw-r--r-- 1 root root 5394 Jun 9 2014 modsecurity_crs_35_bad_robots.conf
-rw-r--r-- 1 root root 19157 Jun 9 2014 modsecurity_crs_40_generic_attacks.conf
-rw-r--r-- 1 root root 43961 Jun 9 2014 modsecurity_crs_41_sql_injection_attacks.conf
-rw-r--r-- 1 root root 87470 Jun 9 2014 modsecurity_crs_41_xss_attacks.conf
-rw-r--r-- 1 root root 1795 Jun 9 2014 modsecurity_crs_42_tight_security.conf
-rw-r--r-- 1 root root 3660 Jun 9 2014 modsecurity_crs_45_trojans.conf
-rw-r--r-- 1 root root 2253 Jun 9 2014 modsecurity_crs_47_common_exceptions.conf
-rw-r--r-- 1 root root 2787 Jun 9 2014 modsecurity_crs_48_local_exceptions.conf.example
-rw-r--r-- 1 root root 1835 Jun 9 2014 modsecurity_crs_49_inbound_blocking.conf
-rw-r--r-- 1 root root 22314 Jun 9 2014 modsecurity_crs_50_outbound.conf
-rw-r--r-- 1 root root 1448 Jun 9 2014 modsecurity_crs_59_outbound_blocking.conf
-rw-r--r-- 1 root root 2674 Jun 9 2014 modsecurity_crs_60_correlation.conf
[root@server1 base_rules]# pwd
/usr/lib/modsecurity.d/base_rules

These rules are automatically symlinked to the activated rule set to enable by default on installation.


[root@server1 activated_rules]# ls
modsecurity_35_bad_robots.data modsecurity_crs_23_request_limits.conf modsecurity_crs_47_common_exceptions.conf
modsecurity_35_scanners.data modsecurity_crs_30_http_policy.conf modsecurity_crs_48_local_exceptions.conf.example
modsecurity_40_generic_attacks.data modsecurity_crs_35_bad_robots.conf modsecurity_crs_49_inbound_blocking.conf
modsecurity_41_sql_injection_attacks.data modsecurity_crs_40_generic_attacks.conf modsecurity_crs_50_outbound.conf
modsecurity_50_outbound.data modsecurity_crs_41_sql_injection_attacks.conf modsecurity_crs_59_outbound_blocking.conf
modsecurity_50_outbound_malware.data modsecurity_crs_41_xss_attacks.conf modsecurity_crs_60_correlation.conf
modsecurity_crs_20_protocol_violations.conf modsecurity_crs_42_tight_security.conf
modsecurity_crs_21_protocol_anomalies.conf modsecurity_crs_45_trojans.conf
[root@server1 activated_rules]# pwd
/etc/httpd/modsecurity.d/activated_rules



We can even customize your ModSecurity by choosing the rule set from OWASP CRS.

OWASP ModSecurity CRS provides a set of generic attack detection rules to ensure baselevel protection for the Web Applications. We can make it more complex as per our security needs. OWASP CRS too provides protections in the following categories:

HTTP Protection
Real-time Blacklist Lookups
DDOS Attacks
Common Web Attacks Protection
Automation Detection - Detecting bots, crawlers, scanners and other surface malicious activity.
Detects Malicious File uploads via Web with AV Scanning
Tracking Sensitive Data - Tracks Credit Card usage and blocks leakages.
Trojan Protection
Identification of Application Defects
Error Detection and Hiding
You can refer this guide OWASP CRS directives to configure our own rule sets.

To install OWASP CRS rule set instead of the default generic rules from the official repo. You can download the OWASP CRS and copy the configuration file and rule sets to the /etc/httpd/modsecurity.d/ folder.

Before enabling OWASP Core Rule set, you can remove modsecurity_crs which is enabled from the repo.

Now go to the /usr/local/src folder and download the repo file from OWASP CRS download.


[root@server1 src]# wget https://github.com/SpiderLabs/owasp-modsecurity-crs/zipball/master
--2016-04-18 08:28:01-- https://github.com/SpiderLabs/owasp-modsecurity-crs/zipball/master
Resolving github.com (github.com)... 192.30.252.131
Connecting to github.com (github.com)|192.30.252.131|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/SpiderLabs/owasp-modsecurity-crs/legacy.zip/master [following]
--2016-04-18 08:28:01-- https://codeload.github.com/SpiderLabs/owasp-modsecurity-crs/legacy.zip/master
Resolving codeload.github.com (codeload.github.com)... 192.30.252.161
Connecting to codeload.github.com (codeload.github.com)|192.30.252.161|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘master’

[ <=> ] 3,43,983 --.-K/s in 0.04s

2016-04-18 08:28:02 (7.68 MB/s) - ‘master’ saved [343983]

Since the downloaded file is a zip file, extract the file for the contents.


[root@server1 src]# file master
master: Zip archive data, at least v1.0 to extract

root@server1 src]# unzip master

root@server1 src]# ls
master SpiderLabs-owasp-modsecurity-crs-f16e0b1

Once the files are downloaded, copy the crs configuration file and the base rule set to the location/etc/httpd/modsecurity.d/


[root@server1 modsecurity.d]# cp -rp /usr/local/src/SpiderLabs-owasp-modsecurity-crs-f16e0b1/modsecurity_crs_10_setup.conf.example .
[root@server1 modsecurity.d]# ls
activated_rules modsecurity_crs_10_setup.conf.example
[root@server1 modsecurity.d]# mv modsecurity_crs_10_setup.conf.example modsecurity_crs_10_setup.conf

Now change the directory to the activated_rules folder and copy the base rules from the installation to that.


[root@server1 modsecurity.d]# cd activated_rules/

[root@server1 activated_rules]# cp -rp /usr/local/src/SpiderLabs-owasp-modsecurity-crs-f16e0b1/base_rules/* .
[root@server1 activated_rules]# ll
total 344
-rw-r--r-- 1 root root 1969 Apr 14 08:49 modsecurity_35_bad_robots.data
-rw-r--r-- 1 root root 386 Apr 14 08:49 modsecurity_35_scanners.data
-rw-r--r-- 1 root root 3928 Apr 14 08:49 modsecurity_40_generic_attacks.data
-rw-r--r-- 1 root root 2224 Apr 14 08:49 modsecurity_50_outbound.data
-rw-r--r-- 1 root root 56714 Apr 14 08:49 modsecurity_50_outbound_malware.data
-rw-r--r-- 1 root root 23038 Apr 14 08:49 modsecurity_crs_20_protocol_violations.conf
-rw-r--r-- 1 root root 8107 Apr 14 08:49 modsecurity_crs_21_protocol_anomalies.conf
-rw-r--r-- 1 root root 3792 Apr 14 08:49 modsecurity_crs_23_request_limits.conf
-rw-r--r-- 1 root root 6907 Apr 14 08:49 modsecurity_crs_30_http_policy.conf
-rw-r--r-- 1 root root 5410 Apr 14 08:49 modsecurity_crs_35_bad_robots.conf
-rw-r--r-- 1 root root 20881 Apr 14 08:49 modsecurity_crs_40_generic_attacks.conf
-rw-r--r-- 1 root root 44677 Apr 14 08:49 modsecurity_crs_41_sql_injection_attacks.conf
-rw-r--r-- 1 root root 99654 Apr 14 08:49 modsecurity_crs_41_xss_attacks.conf
-rw-r--r-- 1 root root 1795 Apr 14 08:49 modsecurity_crs_42_tight_security.conf
-rw-r--r-- 1 root root 3660 Apr 14 08:49 modsecurity_crs_45_trojans.conf
-rw-r--r-- 1 root root 2247 Apr 14 08:49 modsecurity_crs_47_common_exceptions.conf
-rw-r--r-- 1 root root 2787 Apr 14 08:49 modsecurity_crs_48_local_exceptions.conf.example
-rw-r--r-- 1 root root 1838 Apr 14 08:49 modsecurity_crs_49_inbound_blocking.conf
-rw-r--r-- 1 root root 22328 Apr 14 08:49 modsecurity_crs_50_outbound.conf
-rw-r--r-- 1 root root 1448 Apr 14 08:49 modsecurity_crs_59_outbound_blocking.conf
-rw-r--r-- 1 root root 2674 Apr 14 08:49 modsecurity_crs_60_correlation.conf

Once the rules are copied, you can restart the Apache and confirm its status to make sure everything is configured correctly.


[root@server1 activated_rules]# systemctl status httpd
httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
Active: active (running) since Mon 2016-04-18 08:35:13 UTC; 16s ago
Docs: man:httpd(8)
man:apachectl(8)
Process: 3571 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=0/SUCCESS)
Main PID: 3576 (httpd)
Status: "Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec"
CGroup: /system.slice/httpd.service
├─3576 /usr/sbin/httpd -DFOREGROUND
├─3578 /usr/sbin/httpd -DFOREGROUND
├─3579 /usr/sbin/httpd -DFOREGROUND
├─3580 /usr/sbin/httpd -DFOREGROUND
├─3581 /usr/sbin/httpd -DFOREGROUND
└─3582 /usr/sbin/httpd -DFOREGROUND

Apr 18 08:35:12 server1.centos7-test.com systemd[1]: Starting The Apache HTTP Server...
Apr 18 08:35:13 server1.centos7-test.com systemd[1]: Started The Apache HTTP Server.
[root@server1 activated_rules]# tail -f /etc/httpd/logs/error_log
[Mon Apr 18 08:35:13.237779 2016] [suexec:notice] [pid 3576] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Mon Apr 18 08:35:13.237912 2016] [:notice] [pid 3576] ModSecurity for Apache/2.7.3 (http://www.modsecurity.org/) configured.
[Mon Apr 18 08:35:13.237921 2016] [:notice] [pid 3576] ModSecurity: APR compiled version="1.4.8"; loaded version="1.4.8"
[Mon Apr 18 08:35:13.237929 2016] [:notice] [pid 3576] ModSecurity: PCRE compiled version="8.32 "; loaded version="8.32 2012-11-30"
[Mon Apr 18 08:35:13.237936 2016] [:notice] [pid 3576] ModSecurity: LUA compiled version="Lua 5.1"
[Mon Apr 18 08:35:13.237941 2016] [:notice] [pid 3576] ModSecurity: LIBXML compiled version="2.9.1"
[Mon Apr 18 08:35:13.441258 2016] [auth_digest:notice] [pid 3576] AH01757: generating secret for digest authentication ...
[Mon Apr 18 08:35:13.442048 2016] [lbmethod_heartbeat:notice] [pid 3576] AH02282: No slotmem from mod_heartmonitor
[Mon Apr 18 08:35:13.476079 2016] [mpm_prefork:notice] [pid 3576] AH00163: Apache/2.4.6 (CentOS) configured -- resuming normal operations
[Mon Apr 18 08:35:13.476135 2016] [core:notice] [pid 3576] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
Ensuring the Server Security with ModSecurity

Now we can test the working of ModSecurity on our server. Just try to access any file from the server via browser. I just tried accessing the /etc/shadow file from the browser and it reported the forbidden error.




Inspecting the details on the server from the ModSecurity logs (/var/log/httpd/modsec_audit.log). This is what is reported on the server end.




--ffddb332-A--
[19/Apr/2016:05:40:50 +0000] VxXE4nawj6tDGNi3ESgy8gAAAAM 101.63.70.47 60553 45.33.76.60 80
--ffddb332-B--
GET /etc/shadow HTTP/1.1
Host: 45.33.76.60
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: Drupal.toolbar.collapsed=0; SESS1dba846f2abd54265ae8178776146216=cVBBus2vUq_iMWD3mvj-0rM8ca21X1D7UrcVRzsmIZ8
Connection: keep-alive

--ffddb332-F--
HTTP/1.1 403 Forbidden
Content-Length: 212
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

--ffddb332-E--

--ffddb332-H--
Message: Access denied with code 403 (phase 2). Pattern match "^[\\d.:]+$" at REQUEST_HEADERS:Host. [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_21_protocol_anomalies.conf"] [line "98"] [id "960017"] [rev "2"] [msg "Host header is a numeric IP address"] [data "45.33.76.60"] [severity "WARNING"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "9"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [tag "http://technet.microsoft.com/en-us/magazine/2005.01.hackerbasher.aspx"]
Action: Intercepted (phase 2)
Stopwatch: 1461044450304152 4953 (- - -)
Stopwatch2: 1461044450304152 4953; combined=735, p1=505, p2=135, p3=0, p4=0, p5=91, sr=158, sw=4, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.7.3 (http://www.modsecurity.org/); OWASP_CRS/2.2.9.
Server: Apache/2.4.6 (CentOS)
Engine-Mode: "ENABLED"

--ffddb332-Z--

This log clearly states the IP 101.63.70.47 details which was trying to download a file /etc/shadow from the server. And according to the logs, the HTTP reported forbidden error from the server. The details for this server response is also reported in the logs as it was denied as per the ModSecurity rule "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_21_protocol_anomalies.conf". The server identified this web request to be a violation of the Modsecurity rule specified and thus reported this error code.

Now you see how easy to install and configure the ModSecurity on CentOS 7. ModSecurity, when properly configured, harden an Apache web server against several threats including DDoS attacks, SQL injections, Malicious attacks and should be considered in deployments exposed on the Internet.

I hope you enjoyed reading this article. Thank you for reading this :) I would recommend your valuable suggestions and recommendations on this.
    Blogger Comment
    Facebook Comment