Showing posts with label Server. Show all posts
Showing posts with label Server. Show all posts

Tuesday, January 14, 2020

How TO **TROUBLESHOOT** A Network By Accident!





TP-Link (TL-SG1016D) Accidental Network Error Discovery!

The other day I saw a used GIGABIT switch for sale on Carousell, Hong Kong's local version of eBay + Amazon.  I bid on it and I won!  Yaay!

When the unit arrived, I did an unboxing video - but switches are pretty boring devices and there's not much material to do a "show and tell" with.  


So, at the suggestion of Mrs. Maker, I also did a "teardown" video where I took the switch apart in search of a moving part (like a fan) to check on, like with a 3COM switch I refurbished almost 10 years ago. 

No dice.  The TL-SG1016D is a passively cooled device, which means that it has heat sinks and uses airflow and convection to keep itself cool.  Maybe in a future video I'll install a miniature fan, but first I would need to determine that such hackery is needed by using a thermal imaging system (like a FLIR camera).

Anyways, I did my best to bulk up the content by taking the switch apart, putting rubber feet on it and so on...and then ran out of stuff to say...

So I went and put it into service, fully expecting a no-drama situation - only to have a "WTF!" moment when I realized that one of the ports on the switch (PORT 4) was not reporting a Gigabit connection when it should have!




After a little bit of investigation, I found out that the cable in question was not working properly.  The fix was pretty simple.  I swapped out the ethernet cable for a different one.

After that, the link came up at the correct speed:



So what had originally started off as a pretty banal video about a very simple device with no moving parts, no problems and practically zero user experience, I discovered a mis-behaving part of my network that was negatively affecting Mrs. Maker's enjoyment of her computing experience.  

Fixing this problem made me a hero to Mrs. Maker!   Mostly because I somehow magically improved the (perceived) speed of her computer...So...THANKS TP-LINK!


Help a Maker Out?


Did you see anything in this video you want for yourself? If the answer is yes, consider using one of the link(s) below to buy it directly from amazon.com. When you do, I get a small commission that keeps me going!

Bill of Materials


TP-Link 16-Port Gigabit Ethernet Unmanaged Switch | Plug and Play | Metal | Desktop/Rackmount | Fanless | Limited Lifetime (TL-SG1016D)








Saturday, December 21, 2019

named - How To Resolve DNS Server Abuse

CentOS 7 / named


How To Resolve DNS Server Abuse

One day, I noticed that my CentOS system log file (which is located at /var/log/messages) was filled with thousands of messages that looked like this:

16-Dec-2019 08:04:24.451 client: query (cache) '236.31.230.157.in-addr.arpa/PTR/IN' denied
16-Dec-2019 08:04:24.452 client: query (cache) '236.31.230.157.in-addr.arpa/PTR/IN' denied
16-Dec-2019 08:04:24.453 client: query (cache) '236.31.230.157.in-addr.arpa/PTR/IN' denied
16-Dec-2019 08:04:24.454 client: query (cache) '236.31.230.157.in-addr.arpa/PTR/IN' denied

After a little bit of research, I determined that this was a consequence of my Domain Name Server (DNS) server process, named, was being abused.  Anonymous clients around the internet were using my DNS server to resolve IP addresses for any domain, not just the ones that I was responsible for.  

This is a holdover from when the Internet was a kinder and gentler place.  In the old days, a client could connect to any DNS server they wanted to resolve a name to an IP address, because name servers were complicated and rare and bandwidth was relatively scarce.  But, for decades now, Google has maintained two very high-quality and well-publicized DNS servers at 8.8.8.8 and 8.8..4.4, so there's no need for anyone to ask little old me to be resolving a name beyond the domains for which I am responsible.  

In this more cynical and hard-edged Internet age, open DNS servers like mine are being abused to power various nefarious schemes, including spam and denial of service attacks.

So I decided to do something about this situation, and use the fail2ban package to monitor DNS  and block clients who made too many requests within a given period of time.



How To Set Up DNS for Abuse Prevention


The first system to make adjustments to is named, the DNS service offered by bind. 

Clearing Up Some Naming Convention Confustion

Unfortunately, DNS is a bit of a confusing situation with bunch of different names involved.  It's a long and old story, but the quick version is this:

DNS      - the name resolution standard defined in a document called an Request For Comment (RFC)
bind     - the software package that implemented the standard outlined in the RFC
named   - the name of the running service that offers the services outlined in the RFC


(re)Configuring named


The configuration file for named is located at /etc/named.conf.  It contains a lot of information, but for this exercise we are only going to look at a small amount of settings

1) Turn off named recursion

2) Segregate named logging to a dedicated logfile

How To Turn off named recursion


Recursion in named is the settng that enables anonymous clients to resolve any name using your server.  These days, this is not an advisable setting to turn on, and it is easy to disable:

Here's what my named.conf looked like when I was done:

  /*

   - If your recursive DNS server has a public IP address, you MUST enable access
     control to limit queries to your legitimate users. Failing to do so will
     cause your server to become part of large scale DNS amplification
     attacks. Implementing BCP38 within your network would greatly
     reduce this attack surface

  */

  #
  #  GL    2018-02-02    Uncomment ONE of the following
  #
  recursion no;
# recursion yes;

How To Segregate named Logging To A Dedicated Logfile

The next thing to do is configure named so it logs its messages to a segregated logfile, which makes system monitoring easier in some ways, because the logfile isn't flooded with named related messaging.

Thankfully, there's some instructions embedded in the fail2ban package that help out with this task.  Here they are:

# Fail2Ban filter file for named (bind9).
#

# This filter blocks attacks against named (bind9) however it requires special
# configuration on bind.
#
# By default, logging is off with bind9 installation.
#
# You will need something like this in your named.conf to provide proper logging.
#
# logging {
#     channel security_file {
#         file "/var/log/named/security.log" versions 3 size 30m;
#         severity dynamic;
#         print-time yes;
#     };
#     category security {
#         security_file;
#     };
# };

Let's look at the existing named logging situation:

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

So, what's in the data/named.run file?

16-Dec-2019 08:04:24.451 client: query (cache) '236.31.230.157.in-addr.arpa/PTR/IN' denied
16-Dec-2019 08:04:24.452 client: query (cache) '236.31.230.157.in-addr.arpa/PTR/IN' denied
16-Dec-2019 08:04:24.453 client: query (cache) '236.31.230.157.in-addr.arpa/PTR/IN' denied
16-Dec-2019 08:04:24.454 client: query (cache) '236.31.230.157.in-addr.arpa/PTR/IN' denied

So it looks like this file also contains messages related to named.  Let's go ahead and implement the changes required by fail2ban.



Here's what my named.conf file looked like when I was done:

/* 

# 
#  GL  2019-12-16  commented out as an experiment
#
logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};
*/

logging {
  channel security_file {
    file "/var/log/named/security.log" versions 3 size 30m;
    severity dynamic;
    print-time yes;
  };
  category security {
  security_file;
  };
};

SELINUX / CentOS Peculiarities


Because SELINUX is a more stringent security setting than most Linux distributions, a couple of other things need to be done to get this solution working.

Who is DNS?

One of the things that needs to be determined is the security context of the DNS server.  This is established in a couple of places, but the easiest way I know is to scan the /etc/passwd file, which contains a list of all of the users in the system, including services.

And indeed, this line appeared in /etc/passwd:

named:x:25:25:Named:/var/named:/sbin/nologin

Now we know that there is a named user context on this machine.  Next thing is to check the user context of the running service.  This can be done with the ps command:

# ps ax | grep "named"
 5907 ?        Ssl    1:12 /usr/sbin/named -u named -c /etc/named.conf

This output confirms that the username named is being used by DNS service on this machine via the -u parameter (-u named).

Directory Work

OK, with our detective work done, we can go ahead and do the following:

- Create a named subdirectory in the /var/log directory.
- Assign ownership of the named subdirectory to the user context of the DNS server process (named).
- Change the security context of the named subdirectory to that of a named log
- Allow other processes (like fail2ban) permission to enter that directory

Here's how I did it:

# mkdir named
# chown named:named named
# chcon system_u:object_r:named_log_t:s0 named
# chmod 755 named

Here's the result of those actions:

drwxr-xr-x. named  named system_u:object_r:named_log_t:s0 named

Those commands created a directory called named owned (and therefore manipulatable) by the user named (the user context of the DNS server) in the security context of a named log, that may be read and entered into by other processes, like fail2ban.


File Work

Now that the named subdirectory has been prepared, a file needs to be created in it for the named service to write to, and for fail2ban to scan to determine who to ban.

Here's how I did it:

# cd named
# touch security.log
# chown named:named security.log
# chcon system_u:object_r:named_log_t:s0 security.log
# chmod 644 security.log

Here's the result of those actions:

-rw-r--r--. named named system_u:object_r:named_log_t:s0 security.log

Those commands created a file called security.log owned (and therefore manipulatable) by the user named (the user context of the DNS server) in the security context of a named log, that may also be read by other processes like fail2ban.

How To (re)Start The name Service


With all of the preliminary work done, it's time to restart the named service and see if everything was set up properly.

Here's what you will see if there's a configuration problem:

# service named restart
Redirecting to /bin/systemctl restart named.service

Job for named.service failed because the control process exited with error code. See "systemctl status named.service" and "journalctl -xe" for details.

Here's what you will see if everything is OK:

# service named restart
Redirecting to /bin/systemctl restart named.service

#

How To Check The named Server Is Running


Checking to make sure that the named server is running is pretty easy with the service <service_name> status command:

# service named status
Redirecting to /bin/systemctl status named.service
● named.service - Berkeley Internet Name Domain (DNS)
   Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-12-16 09:43:19 HKT; 5min ago
  Process: 10192 ExecStop=/bin/sh -c /usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID (code=exited, status=0/SUCCESS)
  Process: 10208 ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} $OPTIONS (code=exited, status=0/SUCCESS)
  Process: 10204 ExecStartPre=/bin/bash -c if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi (code=exited, status=0/SUCCESS)
 Main PID: 10209 (named)
   CGroup: /system.slice/named.service
           └─10209 /usr/sbin/named -u named -c /etc/named.conf


How To Configure fail2ban To Prevent DNS Server Abuse


Now that we have named running correctly and its messaging related to DNS abusers segregated into a dedicated logfile (/var/log/named/security.log), we can configure fail2ban to scan that logfile and start banning DNS abusers!

The first place to visit is /etc/fail2ban/jail.local, which is where local fail2ban policies reside.  Here's what I found:

# !!! WARNING !!!
# Since UDP is a connection-less protocol, spoofing of IP and imitation of illegal
# actions is way too simple.  Thus enabling of this filter might provide an easy 
# way to implementing a DoS against a chosen victim. 
#
# See:  http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html

#
# Please DO NOT USE this jail unless you know what you are doing.
#
# IMPORTANT: see filter.d/named-refused for instructions to enable logging
#
# This jail blocks UDP traffic for DNS requests.
#
# [named-refused-udp]
# enabled  = true
# filter   = named-refused
# port     = domain,953
# protocol = udp
# logpath  = /var/log/named/security.log

# IMPORTANT: see filter.d/named-refused for instructions to enable logging
# This jail blocks TCP traffic for DNS requests.

#
# GL  2019-12-15  Enabled the following
#
[named-refused]
enabled  = true
port     = domain,953
logpath  = /var/log/named/security.log

#
# GL  2019-12-15  Enabled the following
#
[named-refused-udp]
enabled  = true

#
# GL  2019-12-15  Enabled the following
#
[named-refused-tcp]

enabled  = true




How To Resolve fail2ban SELINUX Issues





Dec 16 10:02:17 vm setroubleshoot: SELinux is preventing /usr/bin/python2.7 from read access on the file disable. For complete SELinux messages run: sealert -l 4f0b9ddb-62c0-4568-a19a-ada24825e993

# sealert -l 4f0b9ddb-62c0-4568-a19a-ada24825e993
SELinux is preventing /usr/bin/python2.7 from read access on the file disable.

*****  Plugin catchall (100. confidence) suggests   **************************

If you believe that python2.7 should be allowed read access on the disable file by default.
Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do allow this access for now by executing:
# ausearch -c 'fail2ban-server' --raw | audit2allow -M my-fail2banserver
# semodule -i my-fail2banserver.pp

Additional Information:
Source Context                system_u:system_r:fail2ban_t:s0
Target Context                system_u:object_r:sysfs_t:s0
Target Objects                disable [ file ]
Source                        fail2ban-server
Source Path                   /usr/bin/python2.7
Port                          <Unknown>
Host                          vm.yougrow.net
Source RPM Packages           python-2.7.5-86.el7.x86_64
Target RPM Packages
Policy RPM                    selinux-policy-3.13.1-252.el7_7.6.noarch
Selinux Enabled               True
Policy Type                   targeted
Enforcing Mode                Enforcing
Host Name                     vm.yougrow.net
Platform                      Linux vm.yougrow.net 3.10.0-1062.9.1.el7.x86_64 #1
                              SMP Fri Dec 6 15:49:49 UTC 2019 x86_64 x86_64
Alert Count                   33
First Seen                    2019-12-15 10:24:17 HKT
Last Seen                     2019-12-16 10:02:14 HKT
Local ID                      4f0b9ddb-62c0-4568-a19a-ada24825e993

Raw Audit Messages
type=AVC msg=audit(1576461734.872:303365): avc:  denied  { read } for  pid=12096 comm="fail2ban-server" name="disable" dev="sysfs" ino=2085 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:sysfs_t:s0 tclass=file permissive=0

type=SYSCALL msg=audit(1576461734.872:303365): arch=x86_64 syscall=open success=no exit=EACCES a0=7fcb234bf110 a1=80000 a2=1b6 a3=24 items=0 ppid=1 pid=12096 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm=fail2ban-server exe=/usr/bin/python2.7 subj=system_u:system_r:fail2ban_t:s0 key=(null)


Hash: fail2ban-server,fail2ban_t,sysfs_t,file,read



Implementing the policies:

# ausearch -c 'fail2ban-server' --raw | audit2allow -M my-fail2banserver
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i my-fail2banserver.pp

# semodule -i my-fail2banserver.pp

#

Behind the scenes,  this was going in in /var/log/messages:

Dec 16 10:04:57 vm systemd: Got automount request for /proc/sys/fs/binfmt_misc, triggered by 12436 (find)
Dec 16 10:04:57 vm systemd: Mounting Arbitrary Executable File Formats File System...
Dec 16 10:04:57 vm systemd: Mounted Arbitrary Executable File Formats File System.
Dec 16 10:37:54 vm kernel: SELinux:  Converting 2406 SID table entries...

Dec 16 10:37:57 vm dbus[953]: [system] Reloaded configuration


Checking fail2ban again now..

DID NOT RESOLVE ISSUE



Rotating The New named Security Log




How To List The Contents Of fail2ban Jails
#!/bin/bash

###########################################################################################
#
# fail2ban-jails.bash
#
# This program lists all of the active jails in the FAIL2BAN system.
#
# GL    2019-12-04      fail2ban-jails.bash
#
###########################################################################################

JAILS=`fail2ban-client status | grep "Jail list" | sed -E 's/^[^:]+:[ \t]+//' | sed 's/,//g'`
for JAIL in $JAILS
do
  fail2ban-client status $JAIL

done

REFERENCES




Wednesday, December 18, 2019

CentOS - How To Optimize An Apache2 Web Server For Speed

CentOS 7 / memcached



How To Optmize An Apache2 Web Server For Speed


In an effort to serve our eCommerce customers better, I thought that providing them with a super fast website would be a good thing, so I used a bunch of tricks that I have learned over the years to speed things up a little bit once our site had been migrated for a while and the inevitable snags had been worked out.


First, Some Benchmarking


To investigate the raw speed of our un-optimized CentOS web server, I thought that I would install a range of test websites at my personal site so I could have some calibration information with which to evaluate the speed of our eCommerce website.

Here's the test URLs I prepared:


A) www.graham-leach.com/Apache2/HelloWorld - Loads a static text file that says "Hello World'.

B) www.graham-leach.com/Apache2/PHPHelloWorld - Executes a dynamic PHP script that says "Hello World!".

C) www.graham-leach.com/Apache2/GIFHelloWorld - Loads a static 1Mb animated GIF file that says "Hello World!"

D) www.holisticpethelp.com - Loads our eCommerce website featuring static text and images and also dynamic PHP and MySQL commands.


Initial Benchmarks - No memcached,  USA Client


www.graham-leach.com/Apache2/HelloWorld: 2.260 seconds

www.graham-leach.com/Apache2/PHPHelloWorld: 2.177 seconds

www.graham-leach.com/Apache2/GIFHelloWorld: 7.139 seconds

www.holisticpethelp.com: 13.191 seconds


Initial Benchmarks - No memcached,  Asia Client


www.graham-leach.com/Apache2/HelloWorld:

www.graham-leach.com/Apache2/PHPHelloWorld: 

www.graham-leach.com/Apache2/GIFHelloWorld: 

www.holisticpethelp.com:


Benchmark Analysis


What do the above numbers tell me?  Well, it looks like the fastest page load I can expect with this configuration is in the 2 second range, which is pretty great!  Unfortunately, the amount of utility offered by the web pages in that speed range are very limited.

Once the web server is forced to start pulling information off a hard disk, it dramatically slows down.  If the file is a single 1Mb image, the web server starts to drag and performs only in the 7 second range, which is not that great.

But when complex web pages start to be delivered, as with the Drupal CMS, which may feature dozens of images and hundreds of SQL queries, performance drops off dramatically and pages start to load in the 11 second range, whch is terrible!


Target Benchmark


If 2 seconds is great (but useless) and 10 seconds is terrible (but useful), what time are we targeting for our eCommerce website, you may ask?  

Well, according to www.webpagetest.org, the average load time target for websites in 2020 is about 5 seconds.



So it looks like we need to figure out a way to double our website speed so we can deliver web pages in about half the time.  Hey, it looks like we have our work cut out for us...so let's begin!


Ways To Make A Website Faster


Here's some easy ways to make a web server feel faster:

A) Keep as much of the website content as possible in memory (fast) via some kind of caching strategy, so the web server doesn't have to pull the files off the disk (slow) when they are required.

B) Reduce the impact of images by compressing them when uploading to the website, so they are as small as possible in transmission from the web server to the web client.

C) Reducing the size of text files (like Cascading Style Sheet, or .css files) as much as possible, so they are as small as possible in transmission from the web server to the web client.

D) Reducing the amount of database lookups as much as possible


How To Speed Up Apache2 Using memcache



Introducing memcached

Due to an unfortunate naming convention, there's a great deal of confusion between memcached, which is a server technology, and memcache, which is a plug-in or client Application Programming Interface (API) that enables applications to avails of the memcache server technology.

How To Install The memcached Server


# yum install memcached
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirror.qoxy.com
 * centos-sclo-rh: mirror.qoxy.com
 * centos-sclo-sclo: mirror.qoxy.com
 * epel: my.fedora.ipserverone.com
 * extras: mirror.qoxy.com
 * remi-php54: mirrors.thzhost.com
 * remi-php55: mirrors.thzhost.com
 * remi-php56: mirrors.thzhost.com
 * remi-php71: mirrors.thzhost.com
 * remi-safe: mirrors.thzhost.com
 * updates: mirror.qoxy.com
Resolving Dependencies
--> Running transaction check
---> Package memcached.x86_64 0:1.4.15-10.el7_3.1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

============================================================================================================================================================================================================
 Package                                          Arch                                          Version                                                   Repository                                   Size
============================================================================================================================================================================================================
Installing:
 memcached                                        x86_64                                        1.4.15-10.el7_3.1                                         base                                         85 k

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

Total download size: 85 k
Installed size: 176 k
Is this ok [y/d/N]: y
Downloading packages:
memcached-1.4.15-10.el7_3.1.x86_64.rpm                                                                                                                                               |  85 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : memcached-1.4.15-10.el7_3.1.x86_64                                                                                                                                                       1/1
  Verifying  : memcached-1.4.15-10.el7_3.1.x86_64                                                                                                                                                       1/1

Installed:
  memcached.x86_64 0:1.4.15-10.el7_3.1

Complete!

#

How To Configure The memcached Server


The memcached configuration file is located at /etc/sysconfig/memcached.  

Here's what mine looked like:

PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""

From long experience, I knew that the CACHESIZE="64" parameter was likely going to prove too small, so I changed it to a more generous value:

CACHESIZE="512"

and then saved the changes.


How To Turn On The memcached Server

The memcached server can be started using the service <servicename> start command:

# service memcached start
Redirecting to /bin/systemctl start memcached.service

How To Check That The memcached Server Is Running


The service start commands don't always tell you a lot about the status of the service they refer to, so it's always a good idea to check to make sure that the memcached service has started properly, and is happy, using the service <servicename> status command:

# service memcached status
Redirecting to /bin/systemctl status memcached.service
● memcached.service - Memcached
   Loaded: loaded (/usr/lib/systemd/system/memcached.service; disabled; vendor preset: disabled)
   Active: active (running) since Sun 2019-12-15 17:17:36 HKT; 5s ago
 Main PID: 15370 (memcached)
   CGroup: /system.slice/memcached.service
           └─15370 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024
Dec 15 17:17:36 vm.yougrow.net systemd[1]: Started Memcached.
#

It's Smart To Periodically Restart memcached


Many years of experience tells us that memcached can get confused.  When it does, it bogs down to the point where it fails to respond to incoming web page requests.  In the past this has led to stressful hours where we could not identify the source of the problem, and customers could not log into our eCommerce website, which was a real problem.  So, out of an abundance of caution, it makes sense to us to restart the memcached server every day at 6am.  This is done by editing the system crontab:

# crontab -e

# GL  2019-12-15  memcached bogs Apache2 down if it is not restarted frequently
#                 Every day at 06h00

00 06 * * * /bin/systemctl restart memcached.service

How To Enable memcached Load At System Startup


Seeing as memcached is so useful and critical to the web server responding quickly to customers, it would be great to have it be automatically loaded whenever the system boots.  

This can easily be done using the systemctl enable command:

# systemctl enable memcached.service
Created symlink from /etc/systemd/system/multi-user.target.wants/memcached.service to /usr/lib/systemd/system/memcached.service.
[root@vm ~]# service memcached status
Redirecting to /bin/systemctl status memcached.service
● memcached.service - Memcached
   Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2019-12-15 19:34:17 HKT; 2min 14s ago
 Main PID: 24146 (memcached)
   CGroup: /system.slice/memcached.service
           └─24146 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024

Dec 15 19:34:17 vm.yougrow.net systemd[1]: Started Memcached.

The memcached service will now start automatically at system boot.


How To Get memcached Statistics


Now that memcached is installed and enabled we can ask it to report on itself:

# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stats                         <- you need to type this in
STAT pid 24146
STAT uptime 844
STAT time 1576410499
STAT version 1.4.15
STAT libevent 2.0.21-stable
STAT pointer_size 64          <- this setting is a concern
STAT rusage_user 0.010459
STAT rusage_system 0.065922
STAT curr_connections 10
STAT total_connections 11
STAT connection_structures 11
STAT reserved_fds 20
STAT cmd_get 0
STAT cmd_set 0
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 0
STAT get_misses 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 7
STAT bytes_written 0
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT bytes 0
STAT curr_items 0
STAT total_items 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT evictions 0
STAT reclaimed 0

END                          <- you need to type this in
quit
Connection closed by foreign host.

#

How To Configure Apache2 To UseThe memcached Server 


For Apache2 to take advantage of the memcached server, it must be configured to load the memcache module.

How To Use phpinfo To Check If Apache2 Has Loaded The memcache Module



# httpd -M | grep "memcache"
 socache_memcache_module (shared)

How To Check That Apache2 Is Using memcached


Unfortunately, there's no really easy way to see if Apache2 is using the memcache module, even if it may have the module loaded.  It can only be checked programmatically.  Happily, I found this this code on www.stackoverflow.com that performs just such a check:


<?php
if (class_exists('Memcache')) {
    $server = 'localhost';
    if (!empty($_REQUEST['server'])) {
        $server = $_REQUEST['server'];
    }
    $memcache = new Memcache;
    $isMemcacheAvailable = @$memcache->connect($server);

    if ($isMemcacheAvailable) {
        $aData = $memcache->get('data');
        echo '<pre>';
        if ($aData) {
            echo '<h2>Data from Cache:</h2>';
            print_r($aData);
        } else {
            $aData = array(
                'me' => 'you',
                'us' => 'them',
            );
            echo '<h2>Fresh Data:</h2>';
            print_r($aData);
            $memcache->set('data', $aData, 0, 300);
        }
        $aData = $memcache->get('data');
        if ($aData) {
            echo '<h3>Memcache seems to be working fine!</h3>';
        } else {
            echo '<h3>Memcache DOES NOT seem to be working!</h3>';
        }
        echo '</pre>';
    }
}
if (!$isMemcacheAvailable) {
    echo 'Memcache not available';
}

?>

On  my system, even with the memcached server installed, the code produced this result:

Hmmm...did I remember to turn the memcached server on?



Another test of the web server now produced this result:





Optimized Benchmarks (USA)

Seeing as the USA is on the other side of the planet, these can be considered "worst case" performance figures for our eCommerce website:

www.graham-leach.com/Apache2/HelloWorld: 

www.graham-leach.com/Apache2/PHPHelloWorld: 

www.graham-leach.com/Apache2/GIFHelloWorld: 


www.holisticpethelp.com:  8.803 seconds

Optimized Benchmarks (Asia)

But testing closer to home, and thereby eliminating network latency, got me these figures, which can be considered "best base" performance figures:

www.graham-leach.com/Apache2/HelloWorld: 0.569 seconds

www.graham-leach.com/Apache2/PHPHelloWorld: 0.474 seconds

www.graham-leach.com/Apache2/GIFHelloWorld: 2.764

www.holisticpethelp.com:  7.380 seconds

Properly Sizing memcached


Out of the box, memcached is sized a little small for our eCommerce website.  We know this from running memcached on our old CentOS 5 server.  Experience tells us that the correct cache size is at least 256Mb, perhaps even as much as 512Mb.  Well, in this case it is best to err on the side of caution and give memcached a lot of room to do its thing, so we are going to set the cache to be 512Mb.

The configuration file for memcached is in /etc/sysconfig/memcached, and I made mine look like this:

PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="512"

OPTIONS=""

After making the changes, I restarted memcached and then checked its configuration with telnet once again:

# service memcached restart
Redirecting to /bin/systemctl restart memcached.service

# service memcached status
Redirecting to /bin/systemctl status memcached.service
● memcached.service - Memcached
   Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2019-12-15 19:56:48 HKT; 7s ago
 Main PID: 25404 (memcached)
   CGroup: /system.slice/memcached.service
           └─25404 /usr/bin/memcached -u memcached -p 11211 -m 512 -c 1024

Dec 15 19:56:48 vm.yougrow.net systemd[1]: Started Memcached.

# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stats
STAT pid 25404
STAT uptime 24
STAT time 1576411030
STAT version 1.4.15
STAT libevent 2.0.21-stable
STAT pointer_size 64
STAT rusage_user 0.003262
STAT rusage_system 0.014138
STAT curr_connections 10
STAT total_connections 11
STAT connection_structures 11
STAT reserved_fds 20
STAT cmd_get 0
STAT cmd_set 0
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 0
STAT get_misses 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 7
STAT bytes_written 0
STAT limit_maxbytes 536870912
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT bytes 0
STAT curr_items 0
STAT total_items 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT evictions 0
STAT reclaimed 0
END
quit
Connection closed by foreign host.

#

How To Install & Configure PHPMemcachedAdmin



Installation:


As of the writing of this document, version 1.3 of PHPMemcachedAdmin can be downloaded from:

https://github.com/elijaa/phpmemcachedadmin/archive/master.zip

Installation was very straightforward.  I went to the root of my web server and executed the following commands:

# wget https://github.com/elijaa/phpmemcachedadmin/archive/master.zip
--2019-12-15 20:32:51--  https://github.com/elijaa/phpmemcachedadmin/archive/master.zip
Resolving github.com (github.com)... 13.229.188.59
Connecting to github.com (github.com)|13.229.188.59|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/elijaa/phpmemcachedadmin/zip/master [following]
--2019-12-15 20:32:51--  https://codeload.github.com/elijaa/phpmemcachedadmin/zip/master
Resolving codeload.github.com (codeload.github.com)... 13.250.162.133
Connecting to codeload.github.com (codeload.github.com)|13.250.162.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘master.zip’

    [ <=>                                                                                                                                               ] 130,301     --.-K/s   in 0.03s

2019-12-15 20:32:52 (4.12 MB/s) - ‘master.zip’ saved [130301]


#

I then unzipped the master-zip file:

# unzip master.zip
Archive:  master.zip
f5b59eb46aa6e299ad24a03c8ab2fe041d38e16d
   creating: phpmemcachedadmin-master/
 extracting: phpmemcachedadmin-master/.gitignore
   creating: phpmemcachedadmin-master/Config/
  inflating: phpmemcachedadmin-master/Config/Memcache.sample.php
  inflating: phpmemcachedadmin-master/LICENSE
   creating: phpmemcachedadmin-master/Library/
  inflating: phpmemcachedadmin-master/Library/Bootstrap.php
   creating: phpmemcachedadmin-master/Library/Command/
  inflating: phpmemcachedadmin-master/Library/Command/Factory.php
  inflating: phpmemcachedadmin-master/Library/Command/Interface.php
  inflating: phpmemcachedadmin-master/Library/Command/Memcache.php
  inflating: phpmemcachedadmin-master/Library/Command/Memcached.php
  inflating: phpmemcachedadmin-master/Library/Command/Server.php
   creating: phpmemcachedadmin-master/Library/Configuration/
  inflating: phpmemcachedadmin-master/Library/Configuration/Loader.php
   creating: phpmemcachedadmin-master/Library/Data/
  inflating: phpmemcachedadmin-master/Library/Data/Analysis.php
  inflating: phpmemcachedadmin-master/Library/Data/Error.php
  inflating: phpmemcachedadmin-master/Library/Data/Version.php
   creating: phpmemcachedadmin-master/Library/HTML/
  inflating: phpmemcachedadmin-master/Library/HTML/Components.php
   creating: phpmemcachedadmin-master/Public/
   creating: phpmemcachedadmin-master/Public/Scripts/
   creating: phpmemcachedadmin-master/Public/Scripts/Highcharts/
  inflating: phpmemcachedadmin-master/Public/Scripts/Highcharts/highcharts.js
  inflating: phpmemcachedadmin-master/Public/Scripts/Highcharts/standalone-framework.js
  inflating: phpmemcachedadmin-master/Public/Scripts/script.js
   creating: phpmemcachedadmin-master/Public/Styles/
  inflating: phpmemcachedadmin-master/Public/Styles/Style.css
  inflating: phpmemcachedadmin-master/README.md
   creating: phpmemcachedadmin-master/Temp/
 extracting: phpmemcachedadmin-master/Temp/.version
   creating: phpmemcachedadmin-master/View/
   creating: phpmemcachedadmin-master/View/Commands/
  inflating: phpmemcachedadmin-master/View/Commands/Commands.phtml
   creating: phpmemcachedadmin-master/View/Configure/
  inflating: phpmemcachedadmin-master/View/Configure/Configure.phtml
  inflating: phpmemcachedadmin-master/View/Footer.phtml
  inflating: phpmemcachedadmin-master/View/Header.phtml
   creating: phpmemcachedadmin-master/View/LiveStats/
  inflating: phpmemcachedadmin-master/View/LiveStats/Frame.phtml
  inflating: phpmemcachedadmin-master/View/LiveStats/Stats.phtml
   creating: phpmemcachedadmin-master/View/Stats/
  inflating: phpmemcachedadmin-master/View/Stats/Error.phtml
  inflating: phpmemcachedadmin-master/View/Stats/Items.phtml
  inflating: phpmemcachedadmin-master/View/Stats/Slabs.phtml
  inflating: phpmemcachedadmin-master/View/Stats/Stats.phtml
  inflating: phpmemcachedadmin-master/commands.php
  inflating: phpmemcachedadmin-master/composer.json
  inflating: phpmemcachedadmin-master/configure.php
   creating: phpmemcachedadmin-master/docker/
  inflating: phpmemcachedadmin-master/docker/Memcache.docker.php
  inflating: phpmemcachedadmin-master/docker/README.md
  inflating: phpmemcachedadmin-master/docker/docker-compose.yml
   creating: phpmemcachedadmin-master/docker/phpmemcachedadmin/
  inflating: phpmemcachedadmin-master/docker/phpmemcachedadmin/Dockerfile
  inflating: phpmemcachedadmin-master/docker/phpmemcachedadmin/build.sh
 extracting: phpmemcachedadmin-master/docker/phpmemcachedadmin/start.sh
  inflating: phpmemcachedadmin-master/index.php
  inflating: phpmemcachedadmin-master/spam.php
  inflating: phpmemcachedadmin-master/stats.php

#

I then renamed the folder to memcached, and entered it:

# mv phpmemcachedadmin-master memcached
# cd memcached

Everything looked ok, so I had a peek at it using the web interface:



Hmmmm......seems there's a couple of things to look into before we are done


How To Fix The PHPMemcachedAdmin Temp Directory Problem

To resolve this error:

Warning : Temporary directory 'Temp/' is not writable, please fix this error and try again.

The Temp folder needs to be:

- Owned by apache:apache.  

This is accomplished using the following command(s):

# chown apache:apache Temp


How To Fix the PHPMemcachedAdmin Configuration File Problem

To resolve this error:

Error : Configuration file or folder is missing, please fix this error and try again.

Error : Configuration file or folder is missing, please fix this error and try again.

The Memcache.php.sample file in the Config directory needs to be:

- Copied to Memcached.php
- Owned by apache:apache 
- Set to SELINUX Read/Write mode

This is accomplished using the following command(s):

# cd Config
# cp Memcached.sample.php Memcached.php
# chown apache:apache Memcached.php
# chcon unconfined_u:object_r:httpd_sys_rw_content_t:s0 Memcache.php

Once these operations are completed, the PHPMemcachedAdmin dashboard comes up error-free:



As you can see, the size of the memory pool is 512Mb.


BUT THERE'S A PROBLEM

The statistics all read 0, meaning that our Drupal eCommerce website isn't taking advantage of the memcached server at all!

How To Integrate memcached with Drupal



Install PECL memcache



Install Drupal memcache module


https://ftp.drupal.org/files/projects/memcache-7.x-1.6.tar.gz




Change settings.php




Turn the Drupal memcache Module on:



After a little while, see what PHPMemcachedAdmin reports:



Conclusion


Getting Drupal to use memcached was fun, but it's hardly the end of the optimization journey...not by a long shot!  

I found more optimization tips can be found at analyze.websiteoptimization.com/wso, which I might look into very soon!



P.S.  After watching the server for a couple of days, I reduced the cache size to 128Mb


P.P.S.  After watching the server for a week, I reduced the cache size to 80Mb

P.P.P.S  After ten days, I increased the cache size to 96Mb



REFERENCES:

https://tecadmin.net/install-memcached-with-pecl-memcache-on-centos-rhel/

https://unix.stackexchange.com/questions/50639/httpd-cant-write-to-folder-file-because-of-selinux

https://devops.ionos.com/tutorials/install-and-configure-memcached-on-centos-7/

https://tecadmin.net/install-memcached-with-php-on-ubuntu/

https://stackoverflow.com/questions/1463670/how-to-check-if-memcache-or-memcached-is-installed-for-php

https://serverpilot.io/docs/how-to-install-the-php-memcache-extension 


http://analyze.websiteoptimization.com/wso