Skip to main content

Resources

Generating self-signed certificates on CentOS

In this process, we will learn how to create self-signed Secure Sockets Layer (SSL) certificates using the OpenSSL toolkit. SSL is a technology used to encrypt messages between two ends of communication (for example, a server and client) so that a third-party cannot read the messages sent between them. Certificates are not used for encrypting the data, but they are very important in this communication process to ensure that the party you are communicating with is exactly the one you suppose it to be. Without them, impersonation attacks would be much more common.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice.

Note
Generally speaking, if you are intending to use an SSL Certificate on a production server, you will probably want to purchase a SSL Certificate from a trusted Certificate Authority. There are many options open to you regarding what certificate best suits your requirements and your budget, but for the purpose of this process, we will confine our discussion to a self-signed certificate that is more than adequate for any development server or internal network.

The Process

  1. To begin, log in as root and go to the following directory so that we can use the Makefile to generate our intended certificates and keyfiles:
    cd /etc/pki/tls/certs
  2. Now, to create a self-signed certificate with an embedded public key (both in the file, server.crt) along with its private key for the server (with the filename as server.key), type the following:
    make server.crt
  3. You will then be asked for a password and will receive a series of questions, to which you should respond with the appropriate values. Complete all the required details by paying special attention to the common name value, which should reflect the domain name of the server or IP address that you are going to use this certificate for. For example, you may type:
    mylocaldomainname.home
  4. To create a pem file that includes a self-signed certificate and a public and a private key in one file, and is valid for five years, type the following:
    make server.pem DAYS=1825
  5. Now, let’s create a key pair (a private key and self-signed certificate that includes the public key) for an Apache web server that we will need for enabling https, and which will be generated in /etc/pki/tls/private/localhost.key and /etc/pki/tls/certs/localhost.crt (use a secure password and repeat it in the second command):
    make testcert
  6. To create a Certificate Signing Request (CSR) file instead of a self-signed certificate, use this:
    make server.csr

How Does It Work?

Here in this process we introduced you to the SSL technology that uses public key cryptography (PKI) (where two forms of keys exist: public and private). On the server, we store the private key and our clients get a public key. Every message sent from one end to the other is encrypted by the key belonging to one side and can only be decrypted by the corresponding key from the other. For example, a message encrypted with the server’s private key can only be decrypted and read by the client’s public key and vice versa. The public key is sent to the client through a certificate file, where it is part of the file. As said before, the public key is encrypting and decrypting the data and the certificate is not responsible for this, but rather for identifying a server against a client and making sure that you are actually connected to the same server you are trying to connect. If you want to set up secure services using SSL encryption in protocols such as FTPS, HTTPS, POP3S, IMAPS, LDAPS, SMTPS, and so on, you need a signed server certificate to work with. If you want to use these services for your business, and you want them to be trusted by the people who are using and working with them, for example, on the public Internet, your certificate should be signed from an official certification authority (CA). Certificate prices are paid by subscription and can be very expensive. If you don’t plan to offer your certificate or SSL-enabled services to a public audience, or you want to offer them only within a company’s intranet or just want to test out things before buying, here you can also sign the certificate by yourselves (self-signed) with the OpenSSL toolkit.

Note
The only difference between a self-signed certificate and one coming from an official CA is that most programs using the certificate for communication will give you a warning that it does not know about the CA and that you should not trust it. After confirming the security risk, you can work with the service normally.

So, what did we learn from this experience?

We started this process by going to the standard location where all the system’s certificates can be found in CentOS 7: /etc/pki/tls/certs. Here, we can find a Makefile, which is a helper script for conveniently generating public/private key pairs, SSL CSRs, and self-signed SSL test certificates. It works by hiding away from you complicated command line parameters for the OpenSSL program. It is very easy to use and will automatically recognize your target through the file extension of your filename parameter. So, it was a simple process to generate an SSL key pair by providing an output filename with the .crt extension. As said before, you will be asked for a password and a list of questions regarding the ownership of the certificate, with the most important question being the common name. This should reflect the domain name of the server you are planning to use this certificate for, because most programs, such as web browsers or email clients, will check the domain names to see if they are valid. The result of running this command was the certificate with its embedded public key in file server.crt, as well as the corresponding private key for the server called server.key.

Next, we created a .pem file and provided a DAYS parameter to make the certificate valid for five years instead of the default one year when you are running without it. A pem file is a container file that contains both parts of the key pair: the private keys and the self-signed certificate (with its embedded public key). This file format is sometimes required by some programs, such as vsftpd, to enable SSL encryption instead of providing the key-pair in two separated files. Next, we ran the Makefile target testcert, which generates a private key as well as a public key, plus the certificate in the correct location, where the Apache web server is expecting them for setting up HTTPS. Please note that, if you need to repeat any Makefile run later, you need to delete the generated output files; for example, for Apache, you need to delete the following files before you can build the output files again:
rm /etc/pki/tls/certs/localhost.crt /etc/pki/tls/private/localhost.key make testcert

Finally, we showed you how to generate a CSR file, which will be needed if you plan to purchase an SSL certificate from a trusted certificate authority.

There's more…

We did not cover all the possibilities that the Makefile script has to offer to generate certificates. If you run the command, make, without giving any target parameter, the program will print out a usage help text with all possible options.

As we have learned, the public and private keys are generated in pairs and will encrypt and decrypt each partner’s messages. You can verify that your key pairs are valid and belong together by comparing the output of the following (which must be exactly the same):
openssl x509 -noout -modulus -in server.crt | openssl md5 openssl rsa -noout -modulus -in server.key | openssl md5

 

 

Using YUM to install packages on CentOS

In this process, we will investigate the role of YUM in installing new packages on your server. An important task for every server administrator is the installation of applications and services. There are several different ways to achieve this, but the most effective method involves the YUM package manager. YUM is able to search through any number of repositories, automatically resolve package dependencies, and specify the installation of one or more packages. YUM is a modern and definitive way to install your packages on your server, and it is the purpose of this process to show you how it is done.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet in order to facilitate the download of additional packages. It’s also good if you have already found some interesting packages to install, which can be learned by using the instructions from the Using YUM to search for packages process. 

The Process

This process will show you how to install one or more packages by invoking the YUM installation option. To do this, you will need to log in as the root user and complete the following process:

  1. To install a single package, replace the package_name value with the appropriate value and type the following:
    yum install package_name
  2. Your system will now provide a transaction report that will require your approval. So, when prompted, simply respond by using the Y or N key and press the Return key to either accept or decline the transaction, as shown as follows:
    Is this ok [y/d/N]: y
  3. If you have declined the transaction, then no further work is required and you will exit the package management routine. However, if you have confirmed the transaction, then watch the progress of your installation, and in the end, it will show you a Complete! Message.
  4. Congratulations! You now have successfully installed your package of choice.

How Does It Work?

All packages are stored in the RPM package file format, and it is the role of YUM to provide access to those files that are stored in various repositories on the Internet. YUM is the power behind the package management for CentOS and it really does make the installation process very easy, but what have we learned from this experience?

Having invoked the install command, YUM will conduct a search of the various repositories in order to find the relevant headers and metadata associated with the package in question. For example, if you wanted to install a package called wget, you would begin by issuing the install command like so: yum install wget. YUM will then locate the package and generate a transaction summary that will not only indicate the required disk size and expected installation size but will also indicate any necessary dependencies required by the requested package. YUM will then check several different repositories (base, extras, and updates) and, having resolved the need for any necessary
dependencies, YUM will be asking us to confirm the request before continuing with the installation process. So, as you can see, by using the Y key, we will be providing YUM with the permission to fulfill the request, which in turn will result in the download, verification, and installation of the package(s) concerned.

There’s More:

There are times when you may wish to install more than one package at a time. To do this, simply invoke the same install command, but instead of naming a single package, simply identify the full list of packages you may require in such a way that it forms a long shopping list:
yum install package_name1 package_name2 package_name3

The number of packages you can install in this way is unlimited, but always leave a single space between each package name and keep the command on a single line. For very long installation instructions, line-wrapping may occur.
You do not need to list the packages in any particular order and the request will be processed in exactly the same way as it was in the original process, and again after listing the transaction summary, it will remain pending until it is confirmed or declined. Again, use the Y key to confirm your request so that the process completes.

 

 

Using YUM to search for packages in CentOS

In this process, we will investigate the role of using YUM to find a package. YUM was developed to improve the installation of RPM software packages, and it is used to access a growing list of packages that provide a full range of services offered by your server. YUM is simple to use, but if you are not sure what a package is called, then your duties as the server administrator can become that much harder. To overcome this, YUM maintains an extensive range of discovery tools and it is the purpose of this process to show you how to use this functionality in order to search through the various repositories and find the package you need.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet.

The Process:

This process will show you how to find one or more packages by invoking YUM’s searching options. To do this, you will need to log in as the root user and complete the following process:

  1. To search for a single package, replace the keyword value with the appropriate phrase, string, or parameter, and type the following:
    yum search keyword
  2. Wait for a summary of the search results, and when a list is generated, you can query any package shown by simply replacing package_name with the appropriate value:
    yum info package_name
  3. If the preceding results prove satisfactory, and you want to view a list of dependencies associated with the package in question, type the following:
    yum deplist package_name

How Does It Work?

Searching for packages with YUM can be achieved in the same way as you would search for anything on the World Wide Web (WWW). The types of words you can search for can be as specific or as general as you like. They can even consist of full or partial words;
having found a package that you may be interested in, you will have noticed that this process has also served to show you how to discover additional information about the package in question.

So, what have we learned from this experience?

YUM maintains extensive search features and it allows you to query packages by keyword, package name, and pathname. For example, if you want to locate the correct package for compiling C, Objective-C, and C++ code, you can use the yum search compiler query. When using these search terms on the command line, there are a number
of related results, and each package carries a brief description that enables us to use a simple process of elimination in order to select the most obvious or the most relevant value. With this in mind, you can then query YUM using the info parameter to find out
more about certain packages. This option reveals the full package details together with a detailed description of what functionality the package is intended to provide. Generally speaking, you may not need to know any further details.

However, there may be circumstances in which you want to know how this package interacts with the server as a whole (especially if you are working with source installations or troubleshooting broken packages), so we can use YUM’s deplist parameter that can give quite a detailed report; if you do happen to have any broken packages, you could simply use this output to detail what dependencies you may or may not need to install in order to fix an underlying issue. This command is particularly useful when debugging dependencies or when working with source-based installations.

There’s More:

Sometimes, you may not want to search for a specific package, and instead, you may prefer to display the contents of your repositories in a catalog-style format. Again, this is easy to do and YUM provides for this functionality with the following commands. If you would like to simply list all the packages available to you from the current repositories used by your system, type yum list all. However, because this list may be quite exhaustive, you may prefer to page through the results by using yum list all | less. In a similar fashion, if you would simply like to list all the software currently installed on your system, type yum list installed | less. If you would like to determine which packages provide for a specific file or feature, simply run the following command at any time by substituting your_filename_here with something more relevant to your own needs: yum provides your_filename_here.

 

Setting your hostname and resolving the network on CentOS

The process of setting the hostname is typically associated with the installation process. If you ever need to change it or your server’s Domain Name System (DNS) resolver, this process will show you how.

To Start With: What Do You Need?

For completing this process, you will require a working installation of the CentOS 7 operating system with root privileges, and a console-based text editor of your choice.

The Process

To start this process, we shall start by accessing the system as root and opening the following file in order to name or rename your current server’s hostname:

  1. Log in as root and type in the following command to see the current hostname:
    hostnamectl status
  2. Now, change the hostname value to your preferred name. For example, if you want to call your server jimi, you would type (change appropriately):
    hostnamectl set-hostname jimi

    Note
    Static hostnames are case-sensitive and restricted to using an Internet-friendly alphanumeric string of text. The overall length should be no longer than 63 characters, but try to keep it much shorter.

  3. Next, we need the IP address of the server. Type in the following command to find it (you need to identify the correct network interface in the output):
    ip addr list
  4. Afterward, we will set the Fully Qualified Domain Name (FQDN), in order to do this, we will need to open and edit the host's file:
    vi /etc/hosts
  5. Here, you should add a new line appropriate to your needs. For example, if your server’s hostname was called jimi, (with an IP address of 192.168.1.100, and a domain name of henry.com) your final line to append will look like this:
    192.168.1.100          jimi.henry.com jimi

    Note
    For a server found on a local network only, it is advisable to use a non-Internet based top-level address. For example, you could use .local or .lan, or even .home, and by using these references you will avoid any confusion with the typical .com, .co.uk, or .net domain names.

  6. Next, we will open the resolv.conf file, which is responsible for configuring static DNS server addresses that the system will use:
    vi /etc/resolv.conf

  7. Replace the content of the file with the following:
    # use google for dns
    nameserver 8.8.8.8
    nameserver 8.8.4.4

  8. When complete, save and close your file before rebooting your server to allow the changes to take immediate effect. To do this, return to your console and type:
    reboot

  9. On a successful reboot, you can now check your new hostname and FQDN by typing the following commands and waiting for the response:
    hostname --fqdn

  10. To test if we can resolve domain names to IP addresses using our static DNS server addresses, use the following command:
    ping -c 10 google.com

 

How it works…

A hostname is a unique label created to identify a machine on a network. It is restricted to alphanumeric-based characters, and making a change to your server’s hostname can be achieved by using the hostnamectl command. A DNS server is used to translate domain names to IP addresses. There are several public DNS servers available; in a later process, we will build our own DNS service.

So, what have we learned from this experience?

In the first stage of the process, we changed the current hostname used by our server with the hostnamectl command. This command can set three different types of hostnames. Using the command with the set-hostname parameter will set the same name for all three hostnames: the high-level pretty hostname, which might include all kinds of special characters (for example, Lennart's Laptop), the static hostname which is used to initialize the kernel hostname at boot (for example lennarts-laptop), and the transient hostname, which is a default received from network configurations.

Following this, we set the FQDN of our server. A FQDN is a hostname along with a domain name after it. A domain name gets important when you are running a private DNS, or allowing external access to your server. Besides using a DNS server setting the FQDN can be achieved by updating the host's file found at /etc/hosts.

This file is used by CentOS to map hostnames to an IP address, and it is often found to be incorrect on a new, un-configured, or recently installed server. For this reason, we first had to find out the IP address of the server using ip addr list.

An FQDN should consist of a short hostname and the domain name. Based on the example shown in this process, we set the FQDN for a server named henry, whose IP address is 192.168.1.100 and domain name is henry.com.

Saving this file would arguably complete this process. However, because the kernel makes a record of the hostname during the boot process, there is no choice but to reboot your server before you can use the changed settings.

Next, we opened the system’s resolv.conf file, which keeps the IP addresses of the system’s DNS servers. If your server does not use or have any DNS records, your system is not able to use domain names for network destinations in any program at all. In our example, we entered the public Google DNS server IP addresses, but you are allowed to use any DNS server you want or have to use (often in a cooperate environment, behind a firewall, you have to use internal DNS server infrastructures). On a successful reboot, we confirmed your new settings by using the hostname command, which can print out the hostname or the FQDN based on the parameters given.

So, in conclusion, you can say that this process has not only served to show you how to rename your server and resolve the network but has also shown you the difference between a hostname and domain name:

As we have learned, a server is not only known by the use of a shorter, easier-to-remember, and quicker-to-type single-word-based hostname, it also consists of three values separated with a period (for example jimi.henry.com). The relationship between these values may have seemed strange at first, especially where many people would have seen them as a single value, but by completing this process you have discovered that the domain name remains distinct from the hostname by virtue of being determined by the resolver subsystem, and it is only by putting them together that your server will yield the FQDN of the system as a whole.

There's more…

The hosts file consists of a list of IP addresses and corresponding hostnames, and if your network contains computers whose IP addresses are not listed in an existing DNS record, then in order to speed up your network it is often recommended that you add them to this file.

This can be achieved on any operating system, but to do this on CentOS, simply open the host's file in your favorite text editor, as shown next:
vi /etc/hosts

Now, scroll down to the bottom of the file and add the following values by substituting the domain names and IP addresses shown here with something more appropriate to your own needs:

192.168.1.100 www.example1.lan

192.168.1.101 www.example2.lan

You can even use an external address such as:
83.166.169.228 www.packtpub.com

This method provides you with the chance to create mappings between domain names and IP addresses without the need to use a DNS, and it can be applied to any workstation or server. The list is not restricted by size, and you can even employ this method to block access to certain websites by simply re-pointing all requests to visit a known website to a different IP address. For example, if the real address of www.website.com is 192.168.1.200 and you want to restrict access to it, then simply make the following changes to the host's file on the computer that you want to block from access:
127.0.0.1 www.website.com

It isn’t failsafe, but in this instance, anyone trying to access www.website.com on this system will automatically be sent to 127.0.0.1, which is your local network address, so this will just block access.

When you have finished, remember to save and close your file in the usual way before proceeding to enjoy the benefits of faster and safer domain name resolution across any available network.

 

Installing, configuring, and testing PHP on CentOS

Hypertext Preprocessor (PHP) remains one of the most popular server-side scripting languages designed for web development. It already supports some nice features, such as connecting to relational databases like MariaDB out-of-the-box which can be used to implement modern web applications very fast. While a current trend can be seen for larger enterprises to move away from PHP in favor of some newer technologies such as Node.js (server-side JavaScript), it is still the superior scripting language on the consumer market. Every hosting company in the world provides some kind of LAMP stack (Linux, Apache, MySQL, PHP) to run the PHP code. Also, a lot of very popular web applications are written in PHP, such as WordPress, Joomla, and Drupal, so it’s fair enough to say that PHP represents a must-have feature for almost any Apache web server. Here in this process, we will show you how to get started with installing and running PHP in your Apache web server with the module mod_php.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice and an Internet connection. It is expected that your server will be using a static IP address and Apache is installed and currently running, and that your server supports one or more domains or subdomains.

The Process

We will begin this process by installing the PHP Hypertext Processor together with the Apache mod_php module, both not installed by default on CentOS 7 minimal.

  1. To begin, log in as root and type the following command:
    yum install mod_php
  2. Now let’s open the standard PHP configuration file after we have made a backup of the original file first:
    cp /etc/php.ini /etc/php.ini.bak && vi /etc/php.ini
  3. Find the line ; date.timezone = and replace it with your own timezone. A list of all the available PHP time zones can be found at http://php.net/manual/en/timezones.php. For example (be sure to remove the leading ; as this is disabling the interpretation of a command; this is called commenting out) to set the timezone to the city Berlin in Europe use:
    date.timezone = "Europe/Berlin"
  4. To make sure the new module and settings have been properly loaded, restart the Apache web server:
    systemctl restart httpd
  5. To be consistent with the CGI examples from the former recipe, here we will create our first dynamic PHP script which will print out the current local server time in the script vi /var/www/html/php-test.php, and run the popular PHP function phpinfo() that we can use to print out important PHP information:
    Server time via Mod PHP

    Time

    The time is

    phpinfo(); ?>

Populating the domain on CentOS

In this process, we will show you how you can quickly add new local domain record entries to your authoritative BIND server which are currently unknown to your nameserver.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system and a console-based text editor of your choice. It is expected that Unbound and BIND have both been installed and are already running and that you have read and applied the zone process and have prepared the required forward and reverse zone files for resolving hostnames of your private network.

The Process

If you want to add new domain names to the IP address mappings to your DNS server, for example for new or unknown hosts in your local network, you have two alternatives. Since we have already created zone files for our local network, we can simply add new A (and/or CNAME) and corresponding PTR entries for every new subdomain within our base domain name into our forward and reverse zone file configuration using our text editor of choice. Alternatively, we can use the nsupdate command-line tool to add those records interactively without the need to restart the DNS server. In this section, we will show you how to prepare and work with the nsupdate tool. In our example, we will add a new subdomain client4.centos7.home for a computer with the IP address 192.168.1.14 to our DNS server’s zone:

  1. Log in as root on the server running your BIND service. Now first we need to activate named to be allowed to write into its zone files by SELinux:
    setsebool -P named_write_master_zones 1
  2. Next, we need to fix some permission problems with the named configuration directory, otherwise nsupdate cannot update our zone files later:
    chown :named /var/named -R; chmod 775 /var/named -R
  3. Since our BIND server is running on port 8053, type the following command to start the interactive nsupdate session locally:
    nsupdate -p 8053 -d -l
  4. At the prompt (>), first connect to the local DNS server by typing the following (press Return to finish commands):
         local 127.0.0.1
  5. To add a new forward domain to IP mapping to your DNS server, type the following:
    update add client4.centos7.home. 115200 A 192.168.1.14
    send
  6. Now add the reverse relationship using the following command:
    update add 14.1.168.192.in-addr.arpa. 115200 PTR client4.centos7.home. send
    If both the update commands’ outputs contained the message NOERROR, press Ctrl+c key to exit the interactive nsupdate session.
  7. Finally, check if both the domain and IP resolution for the new zone entry work (this should also work remotely through the Unbound server):
    dig -p 8053 @127.0.0.1 client4.centos7.home.
    nslookup -port=8053 192.168.1.14 127.0.0.1

How Does It Work?

In this fairly easy process, we showed you how easily you can add new domain name resolution records with the nsupdate tool dynamically at runtime without needing to restart your BIND DNS server.

So what did we learn from this experience?

In this process, we introduced you to the nsupdate command-line tool which is a utility for making changes to a running BIND DNS database without the need to edit the zone files or restart the server. If you have already configured the zone files in your DNS server, then this is the preferred way to make changes to the DNS server. It has several options, for example, you can connect to the remote DNS servers but for simplicity and for security reasons we will only use and allow the most simple form and only connect nsupdate to our BIND server locally (to connect to a BIND server remotely using nsupdate, you need to do more configuration, such as generate secure key-pairs, open the firewall, and so on).

After allowing named to write into its own zone files, which otherwise is prohibited by SELinux, and fixing some permission problems on the default named configuration directory, we started the nsupdate program with -l for local connection, and -p 8053 to connect to our BIND DNS server on port 8053. -d gives us debug output which can be useful for resolving any problems. We then got prompted by an interactive shell where we could run BIND specific update commands. First we set local 127.0.0.1 which connects to our local server, than we used the commands update add to add a new forward A record to our running DNS server. The syntax is similar to defining records in the zone files. Here we used the line update add to add a new A record with a TTL of three days (115200 seconds) for the domain client4.centos7.home to resolve to the IP address 192.168.1.14. The next line was used to config some reverse resolution rules for our new domain and which adds the domain name as a PTR entry into our reverse zone. Here it is important to note that you need to define the domain part of the reverse update add rule the following way: ..in-addr.arpa. To finally execute our commands and make them permanent in our DNS server’s database, without the need to restart the server, we used the send command for both the reverse and forward commands separately since they target different zones. Finally, we tested if the new entries into the DNS server’s zone files were working by querying the BIND server.

 

Forging the CentOS firewall rules by example

In this process, we want to show you how to create your own firewalld service definitions or how to change existing ones, which any CentOS 7 system administrator should know if the predefined service files don’t fit your system’s need.

To Start With: What Do You Need?

To complete this process, you will require a minimal installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice. We will be changing the SSH service’s port number in firewalld, so make sure that you have configured the new port as shown in the process Locking down remote access and hardening SSH. Here, in our example, we have changed the port to 2223. Also, we will create a new firewalld service for a small Python-based web server that we will use to demonstrate the integration of new system service’s into firewalld. It’s advantageous to grasp the basics of firewalld by working through the Working with a firewall process before starting here.

The Process

Here in this process, we will show you how to change and how to create new firewalld service definitions. In this process, it is considered that we are in the default public zone.

To change an existing firewalld service (ssh)

  1. First, log in as root and copy the ssh service to the right place to edit it:
    cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services
  2. Next, open the ssh service definition file:
    vi /etc/firewalld/services/ssh.xml
  3. Change the port from 22 to 2223, then save the file and close it:

  4. Finally, reload the firewall:
    firewall-cmd --reload

To create your own new service
Perform the following steps to create your own new service:

  1. Open a new file:
    vi /etc/firewalld/services/python-webserver.xml
  2. Put in the following service definition:


       Python Webserver
       For pythons webservers
       
  3. Save and close the file, and then finally reload the firewall:
    firewall-cmd --reload
  4. Now, add this new service to our default zone:
    firewall-cmd --add-service=python-webserver
  5. Afterwards, run the following command to start a simple Python web server in the foreground on port 8000 (press the key combination Ctrl + C to stop it):
    python -m SimpleHTTPServer 8000
  6. Congratulations! Your new web server sitting at port 8000 can now be reached from other computers in your network:
    http://:8000/

How Does It Work?

Here in this process, we have shown how easy it is to customize or define new firewalld services if the predefined needs to be changed, or for new system services that are not defined at all. Service definition files are simple XML files where you define rules for a given system service or program. There are two distinct directories where our firewalld service files live: /usr/lib/firewalld/services for all predefined services available from the system installation, and /etc/firewalld/services for all custom and user-created services.

So, what did we learn from this experience?

We started this process by making a working copy of the SSH firewalld service file in the right place at /etc/firewalld/services. We could just copy the original file because all files in this directory will overload the default configuration files from /usr/lib/firewalld/services. In the next step, we then modified it by opening it and changing the default port from 22 to 2223. We have to do this every time we change a system’s service standard listening port to make the firewall aware that it should allow network traffic to flow through the changed port. As you can see when opening this file, service files are simple XML text files with some mandatory and some optional tags and attributes. They contain a list of one or more ports and protocols that defines exactly what firewalld should enable if the service is connected to a zone. There can be another important setting in the XML file: helper modules. For example, if you open the SAMBA service file at /usr/lib/firewalld/services/samba.xml, you will see the tag, . These are special kernel netfilter helper modules that can be dynamically loaded into the underlying kernel-based firewall, and which are needed for some system services, such as Samba or FTP, which create dynamic connections on temporary TCP or UDP ports instead of using static ports. After reloading the firewall configuration, we should now be able to test the connection from another computer in our network using the altered port.

In the second part of this process, we created a brand-new service file for a new system service, which is a simple Python web server listening on port 8000 displaying a simple directory content listing. Therefore, we created a simple XML service file for the Python web server including the right port 8000, restarted the firewall, and afterwards added this new service to our default public zone so that we can actually open connections through this service. You should now be able to browse to our web server’s start page using another computer in the same network. However, as we did not use the --permanent flag, if you restart the firewalld daemon, the python-webserver service will be gone from the public zone (or you can also use the parameter, --remove-service=python-webserver).

In summary, we can say that the recommended firewall choice in CentOS 7 is firewalld, as all important system services have already been set up to use it via predefined service rules. You should remember that Linux firewalls are a very complex topic that can easily fill up a whole book, and you can do a lot more with the firewall-cmd that cannot be covered here in this book.

There's more…

Often, you just want to quickly open a specific port to test out things before writing your own custom-made service definition. In order to do this, you can use the following command line, which will open port 2888 using the tcp protocol temporarily on the default zone:
firewall-cmd --add-port=2888/tcp

Once you have finished your tests, just reload the firewall configuration to remove and close the specific port again.

 

Using YUM to update the CentOS

In this process, we will investigate the role of the Yellowdog Updater, Modified (YUM) package manager with regard to running a system update. Every once in a while, you may become aware of an update or may simply wish to discover if one exists. Applying patches and updates is a regular task for every server administrator, and an up-to-date system can help increase or ensure the security of your server as software bugs and vulnerabilities are found all the time and must be fixed promptly. In this process, you will learn how to achieve this with the help of YUM.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet in order to facilitate the download of additional packages.

The Process: 

You can run this process, as often as required but it should be done frequently, based on a schedule of your own choosing in the full knowledge that on occasion, some updates may
require a full system reboot:

  1. Log in as root and check whether there are any updates for your installed packages. To do this, log in and type the following:
    yum check-update
  2. If no updates are available, then the update process will end and no further work will need to be done. However, if updates are available, YUM will now return a list of all package updates from the repositories known to your system. To complete the update process, type the following command:
    yum -y update
  3. By using the -y flag, the preceding command will now bypass the need to confirm the transaction summary, and your system will now undergo an immediate update process. When complete, you will be provided with a final report that identifies what dependencies have been installed and what packages have been updated.
  4. Generally speaking, no further work is required and you may resume typical operations. However, if a new kernel has been installed, or an important security update has taken place, it may be necessary to reboot the system for the new changes to take effect. To do this, type the following:
    reboot

Note

While there is much debate as to whether an update will require a full system restart in practice, this is only to be considered after a kernel update, which is an update to glibc and particular security-based features that are activated during the boot process.

How Does It Work?

YUM is the default package management system for CentOS and part of its role is to automatically calculate what packages may require updating, what dependencies are required, and to manage the entire process of updating your system in a very simple way.

So, what have we learned from this experience?

We started the process by checking to see if any updates were available to our system using the yum command with the check-update option. In this way, YUM will now check a central repository to confirm if an update is applicable to our system. A repository is a remote directory or website that contains prepared software packages and utilities. YUM will use this facility to automatically locate and obtain the correct Red Hat Package Manager (RPM) and dependencies, and if an update is available, then YUM will respond accordingly with a full summary of what packages and dependencies are available. For
this reason, YUM is a very useful tool, and without doubt its mechanism does serve to simplify the processes associated with package management, because it can talk to repositories and this saves us from having to find and install new applications or updates
manually. If there are updates available, the output will show us exactly which packages are affected, then we can proceed to update the system by using YUM’s update parameter.

In this instance, the preceding command includes the -y flag. This is done in order to circumvent the need to agree with the transaction summary given, and to confirm that we have already agreed to make these updates after running the previous check. Otherwise, you would simply confirm the requests by using the Y key.

There’s more:

You can also use the update parameter to update single packages instead of the whole system by providing the package name like so: yum update package_name. YUM will serve to ensure that all of the requirements for an application are met during installation, and it will automatically install the packages for any dependencies that are not already present on your system. However, and I am sure you will be pleased to hear this, if a new application has requirements that conflict with existing software, YUM will abort the process without making any changes to your system. If you want to automate the updating of your system using a specific time interval, you can install the yum-cron package, which can be highly customized but is outside the scope of this book. To start after installation, use man yum-cron.

 

Synchronizing the CentOS system clock with NTP and the chrony suite

In this process, we will learn how to synchronize the system clock with an external time server using the Network Time Protocol (NTP) and the chrony suite. From the need to time-stamp documents, e-mails, and log files, to securing, running, and debugging a network, or to simply interact with shared devices and services, everything on your server is dependent on maintaining an accurate system clock, and it is the purpose of this proces to show you how this can be achieved.

To Start With: What Do You Need?

For completion of this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet to facilitate downloading additional packages.

The Process

In this process, we will use the chrony service to manage our time synchronization. As chrony is not installed by default on CentOS minimal, we will start this process by installing it:

  1. To begin, log in as root and install the chrony service, then start it and verify that it is running:
    yum install -y chrony
    systemctl start chronyd
    systemctl status chronyd
  2. Also, if we want to use chrony permanently, we will have to enable it on server startup:
    systemctl enable chronyd
  3. Next, we need to check whether the system already uses NTP to synchronize our system clock over the network:
    timedatectl | grep "NTP synchronized"
  4. If the output from the last step showed No for NTP synchronized, we need to enable it using:
    timedatectl set-ntp yes
  5. If you run the command (from step 3) again, you should see that it is now synchronizing NTP.
  6. The default installation of chrony will use a public server that has access to the atomic clock, but in order to optimize the service, we will need to make a few simple changes to streamline and optimize at what time servers are used. To do this, open the main chrony configuration file with your favorite text editor, as shown here:
    vi /etc/chrony.conf
  7. In the file, scroll down and look for the lines containing the following:
    server 0.centos.pool.ntp.org iburst
    server 1.centos.pool.ntp.org iburst
    server 2.centos.pool.ntp.org iburst
    server 3.centos.pool.ntp.org iburst
  8. Replace the values shown with a list of preferred local time servers:
    server 0.uk.pool.ntp.org iburst
    server 1.uk.pool.ntp.org iburst
    server 2.uk.pool.ntp.org iburst
    server 3.uk.pool.ntp.org iburst

    Note
    Visit http://www.pool.ntp.org/ to obtain a list of local servers geographically near your current location. Remember, the use of three or more servers will have a tendency to increase the accuracy of the NTP service.
  9. When complete, save and close the file before synchronizing your server using the sytstemctl command:
    systemctl restart chronyd
  10. To check whether the modifications in the config file were successful, you can use the following command:
    systemctl status chronyd
  11. To check whether chrony is taking care of your system time synchronization, use the following:
    chronyc tracking
  12. To check the network sources chrony uses for synchronization, use the following:
    chronyc sources

How it works…

Our CentOS 7 operating system’s time is set on every boot based on the hardware clock, which is a small-battery driven clock located on the motherboard of your computer. Often, this clock is too inaccurate or has not been set right, therefore it’s better to get your system time from a reliable source over the Internet (that uses real atomic time). The chrony daemon, chronyd, sets and maintains system time through a process of synchronization with a remote server using the NTP protocol for communication.

So, what have we learned from this experience?

As a first step, we installed the chrony service, since it is not available by default on a CentOS 7 minimal installation. Afterward, we enabled the synchronization of our system time with NTP using the timedatectl set-ntp yes command.

After that, we opened the main chrony configuration file, /etc/chrony.conf, and showed how to change the external time servers used. This is particularly useful if your server is behind a corporate firewall and have your own NTP server infrastructure.

Having restarted the service, we then learned how to check and monitor our new configuration using the chronyc command. This is a useful command line tool (c stands for client) for interacting and controlling a chrony daemon (locally or remotely). We used the tracking parameter with chronyc, which showed us detailed information about the current NTP synchronization process with a specific server. Please refer to the man pages of the chronyc command if you need further help about the properties shown in the output (man chronyc).

We also used the sources parameter with the chronyc program, which showed us an overview of the used NTP time servers.

You can also use the older date command to validate correct time synchronization. It is important to realize that the process of synchronizing your server may not be instantaneous, and it can take a while for the process to complete. However, you can now relax in the full knowledge that you now know how to install, manage and synchronize your time using the NTP protocol.

There's more…

In this process, we set our system’s time using the chrony service and the NTP protocol. Usually, system time is set as Coordinated Universal Time (UTC) or world time, which means it is one standard time used across the whole world. From it, we need to calculate our local time using time zones. To find the right time zone, use the following command 

timedatectl list-timezones
If you have found the right time zone, write it down and use it in the next command; for example, if you are located in Germany and are near the city of Berlin, use the following command:

timedatectl set-timezone Europe/Berlin
Use timedatectl again to check if your local time is correct now:

timedatectl | grep "Local time"
Finally, if it is correct, you can synchronize your hardware clock with your system time to make it more precise:
hwclock --systohc

 

Implementing CGI with Perl and Ruby on CentOS

In the previous processes in this segment, our Apache service only served static content, which means that everything requested by a web-browser already existed in a constant state on the server, for example as plain HTML text files that don’t change. Apache simply sends the content of a specific file from the web server to the browser as a response where it then gets interpreted and rendered. If there were no way to change the contents sent to the client, the Internet would be really boring and not the huge success it is today. Not even the simplest example of dynamic content, such as showing a web page with the web server’s current local time would be possible.

Therefore, early in the 1990’s, some smart people started inventing mechanisms to make communication possible between a web server and some executable programs installed on the server to generate web pages dynamically. This means that the content of the HTML sent to the user can change in response to different contexts and conditions. Such programs are often written in scripting languages such as Perl or Ruby but can be written in any other computer language as well, such as Python, Java, or PHP (see later). Because Apache is written in pure C and C++, it cannot execute or interpret any other programming language such as Perl directly. Therefore, a bridge between the server and the program is needed to define how some external programs can interact with the server. One of these methods is called the Common Gateway Interface (CGI) which is a very old way to serve dynamic content. Most Apache web servers use some form of CGI applications and in this process, we will show you how to install and configure CGI for use with Perl and Ruby to generate our first dynamic content.

Note
There also exist some special Apache web server modules such as mod_perl, mod_python, mod_ruby, and so on which should be generally preferred as they directly embed the interpreter of the language into the web server process and therefore are a lot faster in comparison to any interface technology such as CGI.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet in order to facilitate the download of additional packages.

It is expected that your server will be using a static IP address, Apache is installed and currently running, and that your server supports one or more domains or subdomains.

The Process

As both scripting languages Perl as well as Ruby are not installed by default on CentOS 7 Minimal, we will start this process by installing all required packages using YUM.

  1. To begin, log in as root and type the following command:
    yum install perl perl-CGI ruby
  2. Next, restart the Apache web server:
    systemctl restart httpd
  3. Next, we need to configure SELinux appropriately for the use of CGI scripts:
    setsebool -P httpd_enable_cgi 1
  4. Then we need to change the correct security context for our cgi-bin directory for SELinux to work:
    semanage fcontext -a -t httpd_sys_script_exec_t /var/www/cgi-bin restorecon -Rv /var/www/cgi-bin

Creating your first Perl CGI script

  1. Now create the following Perl CGI script file by opening the new file vi /var/www/cgi-bin/perl-test.cgi and putting in the following content:
    #!/usr/bin/perl
    use strict;
    use warnings;
    use CGI qw(:standard);
    print header;
    my $now = localtime;
    print start_html(-title=>'Server time via Perl CGI'),
    h1('Time'), p("The time is $now"),
    end_html;
  2. Next, change the file’s permission to 755, so our apache user can execute it:
    chmod 755 /var/www/cgi-bin/perl-test.cgi
  3. Next, to test and actually see what HTML is being generated from the preceding script, you can execute the perl script directly on the command line; just type:
    /var/www/cgi-bin/perl-test.cgi
  4. Now open a browser on a computer in your network and run your first Perl CGI script, which will print the local time by using the URL:
    http:///cgi-bin/perl-test.cgi
  5. If the script is not working, have a look at the log file /var/log/httpd/error_log.

Creating your first Ruby CGI script

  1. Create the new Ruby CGI script file vi /var/www/cgi-bin/ruby-test.cgi and put in the following content:
    #!/usr/bin/ruby
    require "cgi"
    cgi = CGI.new("html4")
    cgi.out{
         cgi.html{
         cgi.head{ cgi.title{"Server time via Ruby CGI"} } +
         cgi.body{
              cgi.h1 { "Time" } +
              cgi.p { Time.now}
          }
       }
    }
  2. Now change the file’s permission to 755 so our apache user can execute it:
    chmod 755 /var/www/cgi-bin/ruby-test.cgi
  3. To actually see what HTML is being generated from the preceding script, you can execute the Ruby script directly on the command line; just type /var/www/cgibin/ruby-test.cgi. When the line offline mode: enter name=value pairs on standard input is shown, press Ctrl+D to see the actual HTML output.
  4. Now open a browser on a computer in your network and run your first Ruby CGI script which will print the local time by using the following URL:
    http:///cgi-bin/ruby-test.cgi
  5. If it is not working, have a look at the log file /var/log/httpd/error.log.

How Does It Work?

Here in this process, we showed you how easy it is to create some dynamic web sites using CGI. When a CGI resource is accessed, the Apache server executes that program on the server and sends its output back to the browser. The main advantage of this system is that CGI is not restricted to any programming language but works as long as a program is executable on the Linux command line and generates some form of text output. The big disadvantage of CGI technology is that it is a very old and outdated technology: every user request to a CGI resource starts a new process of the program. For example, every request to a Perl CGI script will start and load a new interpreter instance into memory, which will produce a lot of overhead, therefore making CGI only usable for smaller websites or lower parallel user request numbers. As said before, there are other technologies to deal with this issue, for example FastCGI or Apache modules such as mod_perl.

So what did we learn from this experience?

We began this process by logging in as root and installing the perl interpreter and the CGI.pm module for it as it is not included in the Perl standard library (we will use it in our script), as well as by installing the ruby interpreter for the Ruby programming language. Afterwards, to make sure our Apache web server takes notice of our new programming languages installed on the system, we restarted the Apache process.

Next, we made sure that SELinux is enabled to work with CGI scripts and then we provided the standard Apache cgi-bin directory /var/www/cgi-bin with the proper SELinux context type to allow system-wide execution. To learn more about SELinux, read, Working with SELinux. In this directory we then put our Perl and Ruby CGI scripts and made them executable afterwards for the Apache user. In the main Apache configuration file, the /var/www/cgi-bin directory has been defined as the standard CGI directory by default, which means that every executable file you put into this directory, with proper access and execution permissions and the .cgi extension, is automatically defined as a CGI script and can be accessed and executed from your web browser, no matter which programming or scripting language it has been written in. To test our scripts, we then opened a web browser and went to the URL http:///cgi-bin/ with the name of the .cgi script to follow.

There's more…

If you would like to allow execution of CGI scripts in other web directories as well, you need to add the following two lines (Options and AddHandler) to any virtual host or existing Directive directive, or create a new one in the following way (remember that you then also have to set the SELinux httpd_sys_script_exec_t label on the new CGI location as well):

Options +ExecCGI
AddHandler cgi-script .cgi

 

 

Creating an integrated CentOS nameserver solution

So far in this chapter division, we used Unbound as a caching-only DNS server solution because it is very secure and fast, and BIND as our authoritative-only DNS server because its zone management is highly configurable and customizable. BIND has been around for a long time and is the most used DNS software ever. However, a number of critical bugs have been found (and luckily fixed) in the past. Here in this process, we will combine Unbound with BIND to get the best of both worlds: Only the very secure Unbound service will be directly exposed to your private network and can take and serve DNS queries from your clients. The BIND service stays bound to localhost only as it was configured in a former process and is only allowed to resolve internal hostnames and does not have direct access to the Internet or your clients. If a client connects to your Unbound service and requests to resolve an internal hostname from your private network, Unbound will query the BIND server locally for the DNS resolution and cache the response. On the other hand, if a client requests to resolve an external domain name, Unbound itself will recursively query or forward other remote DNS servers and cache the response. The integration of both DNS server systems makes it the perfect all-round DNS server solution.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system and a console-based text editor of your choice. It is expected that a caching-only Unbound server (port 53) and an authoritative-only BIND server (port 8053) have been installed and are already running using process found in this chapter division.

The Process

In this process, we will show you how to configure Unbound so it will be able to query our locally running authoritative-only BIND service whenever a client requests an internal hostname. Any other request should go out as a recursive DNS request to a remote root server to construct an answer:

  1. Log in as root on our server running the Unbound and BIND service and open Unbound’s main configuration file:
    vi /etc/unbound/unbound.conf
  2. First put the following line somewhere in the server: clause:
    local-zone: "168.192.in-addr.arpa." nodefault
  3. Next, we will have to allow Unbound to connect to localhost which is disabled by default, search for the line that reads: # do-not-query-localhost: yes, then activate and set it to no:
    do-not-query-localhost: no
  4. Next, since our BIND server is not configured using DNSSEC, we need to tell Unbound to use it anyway (Unbound by default refuses to connect to DNS servers not using DNSSEC). Search for the line that starts with # domain-insecure: "example.com", then activate it and change it so it reads as follows:
    domain-insecure: "centos7.home."
    domain-insecure: "168.192.in-addr.arpa."
  5. Next, we need to tell Unbound to forward all the requests for our internal domain centos7.home. to the locally running BIND server (on port 8053). Append the following at the file’s end:
    stub-zone:
             name: "centos7.home."
             stub-addr: 127.0.0.1@8053
  6. Also, we need to tell Unbound to do the same for any reverse lookup to our internal domain using BIND:
    stub-zone:
            name: "1.168.192.in-addr.arpa."
            stub-addr: 127.0.0.1@8053
  7. Save and close the file, and then restart the Unbound service:
    unbound-checkconf && systemctl restart unbound

How Does It Work?

Congratulations! You now have a full authoritative and very secure DNS server solution using an integrated approach combining all the good parts from Unbound and BIND. In this process, we have shown you how to configure the Unbound service using stub-zones to connect to an internally running BIND service for both forward and reverse requests. A stub-zone is a special Unbound feature to configure authoritative data to be used that cannot be accessed using the public Internet servers. Its name field defines the zone name for which Unbound will forward any incoming DNS requests and the stub-addr field configures the location (IP address and a port) of the DNS server to access; in our example, this is the locally running BIND server on port 8053. For Unbound to be able to connect to the localhost, we first had to allow this using the do-not-query-localhost: no directive, had to mark our forward and reverse domain as being insecure, and also had to define a new local-zone, which is necessary that Unbound knows that clients can send queries to a stub-zone authoritative server.

There's more…

In order to test our new Unbound/BIND DNS cluster, make one public and one internal hostname DNS request to the Unbound service from another computer in the same network (you can also run similar tests locally on the DNS server itself). If our Unbound/BIND DNS cluster has the IP 192.168.1.7, you should be able to get correct answers for both dig @192.168.1.7 www.packtpub.com and dig @192.168.1.7 client1.centos7.home from any other computer in your network.

If you have to troubleshoot service problems or need to monitor the DNS queries of your new Unbound/BIND DNS server, you can configure logging parameters. For BIND, in the main configuration file named.conf you can set the verbosity of the logging output (or log level). This parameter is called severity and can be found within the logging directive. It is already set to dynamic; which gives the highest amount of logging messages possible. You can then read your current log using tail -f /var/named/data/named.run. For Unbound, you can set the level of verbosity in its main configuration file unbound.conf using the verbosity directive which is set to the lowest level of 1 but can be increased to 5. To learn more about the different levels, use man unbound.conf. Use journald to read the Unbound logging information using the command journalctl -f -u unbound.service (press Ctrl+c key to exit the command).

We can not only log the system and service information but can also enable query logs. For Unbound just use a verbosity of 3 or above to record query information. For BIND, in order to activate the query log (query output will go to the log file named.run), use the command rndc querylog on (to turn it off, use rndc querylog off). Remember to turn off any excessive logging information, such as the query log, when configuring your DNS server on a productive system as it can decrease your service’s performance. You can also install other third-party tools such as dnstop (from the EPEL repository) to monitor your DNS activity.

 

 

CentOS firewall

A firewall is a program that monitors and controls your system’s network interfaces’ incoming and outgoing network traffic and can restrict the transmission to only useful and non-harmful data into and out of a computer system or network. By default, CentOS is made available with an extremely powerful firewall, built right into the kernel, called netfilter. While, in older versions of CentOS, we used the famous iptables application to control it, in version 7, the new standard netfilter management program has changed to a service called firewalld, which is already installed and enabled on every CentOS 7 server by default.

It is a very powerful service to take full control over your server’s firewall security and is much easier to work with than iptables. Its main advantages are that it features a better structured and more logical approach to managing and configuring every aspect of a modern firewall solution. Therefore, it will be the foundation of your server’s security, and for this reason, it is the purpose of this process to get you started on the fundamentals of firewalld quickly.

To Start With: What Do You Need?

To complete this process, you will require a minimal installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice.

The Process

As the firewalld service is running on every CentOS 7 server by default, we can start directly working with the service by logging in to your server using the root user.

  1. Type the following commands to query zone-related information:
    firewall-cmd --get-zones | tr " " "\n"
    firewall-cmd --list-all-zones
    firewall-cmd --get-default-zone
    firewall-cmd --list-all
  2. We can switch to a different firewall default zone by using the following line:
    firewall-cmd --set-default-zone=internal
  3. Add a network interface to a zone temporarily:
    firewall-cmd --zone=work --add-interface=enp0s8
  4. Now, add a service to a zone temporarily:
    firewall-cmd --zone=work --add-service=ftp
  5. Test if adding the interface and service has been successful:
    firewall-cmd --zone=work --list-all
  6. Now, add the service permanently:
    firewall-cmd --permanent --zone=work --add-service=ftp
    firewall-cmd --reload
    firewall-cmd --zone=work --list-all
  7. Finally, let’s create a new firewall zone by opening the following file:
    vi /etc/firewalld/zones/seccon.xml
  8. Now put in the following content:

     
    security-congress For use at the security congress.  

  9. Save and close, then reload the firewall config so that we can see the new zone:
    firewall-cmd --reload
  10. Finally, check that the new zone is available:
    firewall-cmd --get-zones

How Does It Work?

In comparison to iptables, the new firewalld system hides away the creation of sophisticated networking rules and has a very easy syntax that is less error-prone. It can dynamically reload netfilter settings at runtime without having to restart the complete service and we can have more than one firewall configuration set per system, which makes it great for working in changing network environments, such as for mobile devices like laptops. In this process, we have given you an introduction to the two fundamental building blocks of firewalld: the zone and the service.

So, what did we learn from this experience?

We started this process using firewall-cmd to get information about available firewall zones on the system. Firewalld introduces the new concept of network or firewall zones, which assigns different levels of trust to your server’s network interfaces and their associated connections. In CentOS 7, there already exist a number of predefined firewalld zones, and all of these (for example, private, home, public, and so on, with the exception of the trusted zone) will block any form of incoming network connection to the server unless they are explicitly allowed using special rules attached to the zone (these rules are called firewalld services, which we will see later). We queried zone information using firewall-cmd with --get-zones or (more detailed) with the --list-all-zones parameter. Each of these zones acts as a complete and full firewall that you can use, depending on your system’s environment and location. For example, as the name implies, the home zone is for use if your computer is located in home areas. If this is selected, you mostly trust all other computers and services on the networks to not harm your computer, whereas the public zone is more for use in public areas such as public access points and so on. Here, you do not trust the other computers and services on the network to not harm you. On CentOS 7, the standard default zone configuration set after installation is the public zone, which we displayed using the command’s --get-default-zone parameter, and in more detail using --list-all.

Note
Simply put, firewalld zones are all about controlling incoming connections to the server. Limiting outgoing connections with firewalld is also possible but is outside the scope of this book.

Also, to get more technical information about all currently available zones, we used the firewall client’s --list-all-zones parameter. In the command’s output, you will notice that a zone can have some associated networking interfaces and a list of services belonging to it, which are special firewall rules applied to incoming network connections. You may also notice that, while listing details of all zones and their associated services by default, all firewalld zones are very restrictive and barely allow anything to connect to the server at all. Also, another very important concept can be seen in the command’s output from the above. Our public zone is marked as default and active. While the active zone is the one that is directly associated with a network interface, the default zone can really get important if you have multiple network adapters available. Here, it acts as a standard minimum firewall protection and fallback strategy, in case you missed to assign some active zone for every interface. For systems with only one network interface setting, the default zone will set the active zone automatically as well. To set a default zone, we used the --set-default-zone parameter and, to mark a zone as active for an interface, we used --add-interface. Please note that, if you don’t specify the --zone parameter, most firewall-cmd commands will use the default zone to apply settings. Firewalld is listening on every network interface in your system and waiting for new network packets to arrive. In summary we can say that if there is a new packet coming into a specific interface, the next thing firewalld has to do is find out which zone is the correct one associated with our network interface (using its active or if not available its default configuration); after finding it, it will apply all the service rules against the network packets belonging to it.

Next, we showed you how to work with firewalld services. Simply put, firewalld services are rules that open and allow a certain connection within our firewall to our server. Using such service file definitions allows the reusability of the containing rules because they can be added or removed to any zone. Also, using the predefined firewalld services already available in your system, as opposed to manually finding out and opening protocols, ports, or port ranges using a complicated iptables syntax for your system services of interest, can make your administrative life much easier. We added the ftp service to the work zone by invoking --add-service. Afterward, we printed out details of the work zone using -list-all. Firewalld is designed to have a separated runtime and permanent configuration. While any change to the runtime configuration has an immediate effect but will be gone, the permanent configuration will survive to reload or restart of the firewalld service. Some commands such as switching the default zone are writing the changes into both configurations which mean they are immediately applied at runtime and are persistent over service restart. Other configuration settings such as adding a service to a zone are only writing to the runtime configuration. If you restart firewalld, reload its configuration, or reboot your computer, these temporary changes will be lost. To make those temporary changes permanent, we can use the --permanent flag with the firewall-cmd program call to write it to the permanent configuration file as well.

Other than with the runtime options, here the changes are not effective immediately, but only after a service restart/reload or system reboot. Therefore, the most common approach to apply permanent settings for such runtime-only commands is to first apply the setting with the --permanent parameter, and afterward reload the firewall’s configuration file to actually activate them.

Finally, we showed you how to create your own zone, which is just a XML file you have to create in the /etc/firewalld/zones/ directory, and where we specified a name, description, and all the services that you want to activate. If you change something in any firewall configuration file, don’t forget to reload the firewall config afterward.

To finish this process, we will revert our permanent changes made to the work zone and reload firewalld to reset all the non-permanent changes we applied in this process:
firewall-cmd --permanent --zone=work --remove-service=ftp
firewall-cmd --reload

There's more…

To troubleshoot blocking services, instead of turning off the firewall completely, you should just switch zone to trusted, which will open all the incoming ports to the firewall:
firewall-cmd --set-default-zone=trusted

Once you have finished your tests, just switch back to the zone that you were in before, for example:
firewall-cmd --set-default-zone=public

 

 

Taking control in CentOS with GIT and Subversion

Document revision control systems or version control systems, as they are sometimes called, are used for the management of changes to documents. These systems get more and more important these days as modern work often connects people from around the globe to collaborate and work together on all kinds of documents (for example, software source code) making it important to manage the file changes by different people using revisions. In this process, we will show you how to use modern version control systems such as GIT and Subversion to manage the versioning of config files.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, and a connection to the Internet in order to facilitate the download of additional packages.

The Process:

Here in this process, we will put the complete main Linux configuration directory, /etc/, under version control of a Git repository to keep track of all our changes to configuration files:

  1. To begin, log in as root, install Git, and configure it by providing an email address and username (please substitute your_username and your_email_address with real names):
    yum install git
    git config --global user.email "your_email_address"
    git config --global user.name "your_username"
  2. Now, let’s create a new repository in the /etc directory:
    cd /etc/
    git init
  3. Now, after we have our new repository, let’s add all the files in the /etc/ directory under version control:
    git add *
  4. To commit the files to the repository creating your first revision, type the following:
    git commit -a -m "inital commit of the full /etc/ directory"
  5. Now, let’s change a file:
    echo "FILE HAS CHANGED" >> yum.conf
  6. Next, show the changes to your repository:
    git status
  7. Next, we will commit these changes and create a new revision of it:
    git commit -a -m "changing yum.conf files"
  8. Next, show all the commits so far:
    git log --pretty=oneline --abbrev-commit
  9. This will output the following commits on my system (the number hashes will be different on yours):
    8069c4a changing yum.conf
    5f0d50a inital commit of the full /etc directory
  10. Based on the output from the earlier step, we will now show all the differences between the two revision numbers (change the number hashes on your system based on the output from the earlier step):
    git diff 8069c4a 5f0d50a
  11. To complete this process, we will revert our changes to the original file revision (the initial commit):
    git checkout 5f0d50a

How Does It Work?

Here, in this process, we showed you how to use Git to manage changes to system config files in the /etc directory. This can be important, for example, if you are testing things out, so a lot of changes will be made to some configuration files and you will want to keep track of your changes, which is nice because you don’t need to memorize every single step you have taken if you later have to revert the changes or go back to a specific revision or  compare different file versions.

So, what did we learn from this experience?

We started by installing Git and added a username and an e-mail address to its configuration, which is essential for using it later in the process. Then, we changed to the /etc directory and initialized (using the init parameter) a new empty Git project there, which is called repository and keeps track of all the files associated to it. This command will add a hidden .git directory to it, which will contain the complete file changes and revision information. Next, we added all the files (using the wildcard * operator) from this directory, including all sub-directories to the next revision. A revision is like a state the files are in at a given time point and is identified by a unique hash ID such as 8069c4a.

Then, we actually created a new revision using the commit parameter and supplied a meaningful message using the -m parameter. After we set up the Git repository and added all the files to it, every change to the files gets watched in the /etc directory. Next, we changed the main YUM configuration file in our repository by adding a random string to

the end of it using the echo >> command. If we now use git’s status parameter again, we see in the output that the Git system has notified that this file has been changed. We can now create a new revision with the changed file by using git’s commit parameter again, using another meaningful message here stating that yum.conf has been changed. We then used the git log command. This will show us all the committed revisions with their unique md5 hash string IDs. With this ID, we can fuel the git diff command to see all the file changes between two revisions. To learn more about the output format, use man gitdiff- files and read its section COMBINED DIFF FORMAT. In our last step, we used the checkout command to go to a specific file revision; here we reverted all our changes and went back to the original file state.

Git is a very powerful version management tool, and in this process, we just scratched the surface of what can be done with it. To learn more about Git’s wonderful techniques, such as branching, merging, pull requests, and so on, start with the Git tutorial pages by typing in man gittutorial.

There’s More:

You can also use the program Subversion to bring your /etc directory under version control. Subversion is another common document revision control system whose main difference from Git is that it uses a centralized server to keep track of the file changes. Git is distributed, meaning that everybody working on a Git project will have the complete repository locally on their computer. Here, we will show you the exact steps necessary to use Subversion instead of Git for this purpose:

  1. First, install Subversion and configure a new server directory for our /etc repository:
    yum install subversion
    mkdir -p /var/local/svn/etc-repos
    svnadmin create --fs-type fsfs /var/local/svn/etc-repos
  2. Now, make an in-place import of the /etc filesystem to our new repository:
    svn mkdir file:///var/local/svn/etc-repos/etc
    -m "Make a directory in the repository to correspond to /etc"
  3. Now, switch to the /etc directory and add all the files to a new revision:
    cd /etc
    svn checkout file:///var/local/svn/etc-repos/etc ./
    svn add *
  4. Now, create your first commit:
    svn commit -m "inital commit of the full /etc/ directory"
  5. Next, change the yum.conf file:
    echo "FILE HAS CHANGED" >> yum.conf
  6. Commit your changes to a new file revision:
    svn commit -m "changing yum.conf files"
  7. Now, show the change log:
    svn log -r 1:HEAD
  8. Show the file differences between our two commits (the first commit was the /etc import):
    svn diff -r 2:3
  9. Finally, revert to the first revision of our yum.conf file:
    svn update -r 2 yum.conf

 

 

 

Speaking the right language in CentOS

In this process, we will show you how to change the language settings of your CentOS 7 installation for the whole system and for single users. The need to change this is rare but can be important, for example, if we accidentally chose the wrong language during installation.

To Start With: What Do You Need?

For the successful implementation of this process, you will require a working installation of the CentOS 7 operating system with root privileges, and a console-based text editor of your choice. You should have read the Navigating text files with less process because some commands in this process will use less for printing output.

The Process

There are two categories of settings that you have to adjust if you want to change the system-wide language settings of your CentOS 7 system. We begin by changing the system locale information and then the keyboard settings:

  1. To begin, log in as root and type the following command to show the current locale settings for the console, graphical window managers (X11 layout), and also the current keyboard layout:
    localectl status
  2. Next, to change these settings, we first need to know all the available locale and keyboard settings on this system (both commands use less navigation):
    localectl list-locales localectl list-keymaps
  3. If you have picked the right locale from the output above in our example, de_DE.utf8 and keymap de-mac (change to your own appropriate needs), you can change your locale and keyboard settings using:
    localectl set-locale LANG=de_DE.utf8 localectl set-keymap de-mac
  4. Now, verify the persistence of your changes using the same command again:
    localectl status

How it works…

As we have seen, the localectl command is a very convenient tool that can take care of managing all important language settings in a CentOS 7 system.

So what have we learned from this experience?

We started by logging in to our command line with the root user. Then, we ran the localectl command with the parameter status, which gave us an overview of the current language settings in the system. The output of this command showed us that language properties in a CentOS 7 system can be separated into locale (system locale) and keymap (VC keymap and all X11 layout properties) settings.

Locales on Linux are used to set the system’s language as well as other language-specific properties. This can include texts from error messages, log output, user interfaces, and if you are using a window manager such as Gnome, even Graphical User Interfaces (GUI). Locale settings can also define region-specific formatting such as paper sizes, numbers, and their natural sorting, currency information, and so on. They also define character encoding, which can be important if you choose a language that has characters that cannot be found in the standard ASCII encoding.

Keymap settings, on the other hand, define the exact layout of each key on your keyboard.

Next, to change these settings, we first issued the localectl command with the list-locales parameter to retrieve a full list of all locales on the system, and list-keymaps to show a list of all keyboard settings available in the system. Locales as outputted from the list-locales parameter use a very compact annotation for defining a language:
Language[_Region][.Encoding][@Modificator]

Only the Language part is mandatory, all the rest is optional. Examples for language and region are: en_US for English and region the United States or American English, es_CU would be language Spanish and Region Cuba or Cuban Spanish.

Encodings are important for special characters such as German umlaut or accents in the French language. The memory representation of these special characters can be interpreted differently depending on the used encoding type. In general, UTF-8 should be used as it is capable of encoding almost any character in every language.

Modificators are used to change settings defined by the locale. For example, sr_RS.utf8@latin is used if you want to have Latin settings for serbian Serbia, which normally uses Cyrillic definitions. This will change to western settings such as sorting, currency information, and so on.

To change the actual locale, we used the set-locale LANG=de_DE.utf8 parameter. Here, the encoding was selected to display proper German umlauts. Please note that we used the LANG option to set the same locale value (for example, de_DE.utf8) for all available locale options. If you don’t want to have the same locale value for all available options, you can use a more fine-grained control over single locale options. Please refer to the locale description using the man page, man 7 locale (on minimal installation; you need to install all Linux documentation man pages before using the yum install man-pages command). You can set these additional options using a similar syntax, for example, to set the time locale use:
localectl set-locale LC_TIME="de_DE.utf8"

Next, we showed all available keymap codes using the list-keymaps parameter. As we have seen from running localectl status, the keymaps can be separated in non-graphical (VC keymap) and graphical (X11 layout) settings, which allows the flexible configuration of different keyboard layouts when using a window manager such as Gnome and for the console. Running localectl with the parameter, set-keymap de-mac, sets the current keymap to a German Apple Macintosh keyboard model. This command applies the given keyboard type to both the normal VC and the X11 keyboard mappings. If you want different mappings for X11 than for the console, use localectl --no-convert set-x11keymap cz-querty, where we use cz-querty for the keymap code to a Czech querty keyboard model (change this accordingly).

There's more…

Sometimes, single system users need different language settings than the system’s locale (which can only be set by the root user), according to their regional keyboard differences and for interacting with the system in their preferred human language. System-wide locales get inherited by every user as long as they are not overwritten by local environment variables.

Note

Changing system-wide locales does not necessarily have an effect on your user’s locales if they have already defined something else for themselves.

To print all the current locale environment variables for any system user, we can use the command, locale. To set single environment variables with the appropriate variable name; for example, to set the time locale to US time we would use the following line:
export LC_TIME="en_US.UTF-8"

But, most likely we would want to change all the locales to the same value; this can be done by setting LANG. For example, to set all the locales to American English, use the following line:
export LANG="en_US.UTF-8"

To test the effect of locale changes, we can now produce an error message that will be shown in the language set by the locale command. Here is the different language output for changing the locale from English to German:
export LANG="en_US.UTF-8"
ls !

The following output will be printed:
ls: cannot access !: No such file or directory

Now, change to German locale settings:
export LANG="de_DE.UTF-8"
ls !

The following output will be printed:
ls: Zugriff auf ! nicht möglich: Datei oder Verzeichnis nicht gefunden

Setting a locale in an active console using the export command will not survive closing the window or opening a new terminal session. If you want to make those changes permanent, you can set any locale environment variables, such as the LANG variable, in a file called .bashrc in your home directory, which will be read every time a shell is opened. To change the locale settings permanently to de_DE.UTF-8 in our example (change this to your own needs) use the following line:
echo "export LANG='de_DE.UTF-8'" >> ~/.bashrc

 

Implementing name-based hosting on CentOS

Normally, if you install Apache as shown in the previous process, you can host exactly one website that is accessible as the server’s IP address or the domain name Apache is running on, for example, http://192.168.1.100 or http://www.centos7.home. Such a system is very wasteful for your server resources as you would need individual servers with Apache installed for every single domain you want to host. Name-based or virtual hosting is used to host multiple domains on the same Apache web server. If a number of different domain names have already been assigned to your Apache web server’s IP address using a DNS server or through a local /etc/hosts file, virtual hosts can be configured for every available domain name to direct the user to a specific directory on the Apache server containing the site’s information. Any modern webspace provider uses this kind of virtual hosting to divide one web server’s space into multiple sites. There is no limit to this system and to the number of sites to create from it as long as your web server can handle its traffic. In this process, we will learn how to configure name-based virtual hosting on the Apache web server.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice. It is expected that your server will be using a static IP address and Apache is installed and currently running, and that you have enabled system users publishing directories in an earlier process. Virtual host names cannot work without previously setting up one or more domains or subdomains outside Apache.

For testing, you could set up your /etc/hosts (see the Setting your hostname and resolving the network process in segment Chapter 2, Configuring the System) or configure some A or CNAMES in your BIND DNS server (refer to Chapter 9 , Working with Domains) to use different domain names or subdomains, such as www.centos7.home, all pointing to your Apache web server’s IP address.

Note
A common misconception is that Apache can create domain names for your Apache web server on its own. This is not true. The different domain names you want to wire to different directories using virtual hosts need to be set up in a DNS server or /etc/hosts file to point to your Apache server’s IP address before you can use them with virtual hosts.

The Process

For the purpose of this process we will be building some local virtual hosts with the following Apache example subdomain names: www.centos7.home, web1.centos7.home, web2.centos7.home and .centos7.home for the corresponding web publishing folders /var/www/html, /var/www/web1, /var/www/web2, and /home//public_html for the domain’s network name centos7.home. These names are interchangeable and it is expected that you will want to customize this process based on something more appropriate to your own needs and circumstances.

  1. To begin, log in as root on your Apache server and create a new configuration file that will hold all our virtual host definitions:
    vi /etc/httpd/conf.d/vhost.conf
  2. Now put in the following content, customizing the centos7.home value and the username to fit your own needs:

           ServerName centos7.home
           ServerAlias www.centos7.home
           DocumentRoot /var/www/html/


             ServerName web1.centos7.home
             DocumentRoot /var/www/web1/public_html/


             ServerName web2.centos7.home
             DocumentRoot /var/www/web2/public_html/


             ServerName .centos7.home
             DocumentRoot /home//public_html/
  3. Now save and close the file in the usual way before proceeding to create the directories for both virtual hosts that are currently missing:
    mkdir -p /var/www/web1/public_html /var/www/web2/public_html
  4. Having done this, we can now create default index pages for the missing subdomains web1 and web2 by using our favorite text editor, as follows:
    echo "

    Welcome to Web1

    " >
    /var/www/web1/public_html/index.html
    echo "

    Welcome to Web2

    " >
    /var/www/web2/public_html/index.html
  5. Now reload the Apache web server:
    apachectl configtest && systemctl reload httpd
  6. Now, for simple testing purposes, we will just configure all our new Apache web server’s subdomains in the hosts file of the client computer that wants to access these virtual hosts, but remember that you can also configure these subdomains in a BIND DNS server. Login to this client computer (it needs to be in the same network as our Apache server) as root and add the following lines to the /etc/hosts file, assuming our Apache server has the IP address 192.168.1.100:
    192.168.1.100 www.centos7.home
    192.168.1.100 centos7.home
    192.168.1.100 web1.centos7.home
    192.168.1.100 web2.centos7.home
    192.168.1.100 john.centos7.home
  7. Now on this computer, open a browser and test things out by typing the following addresses into the address line (replace with the username you defined for the virtual host): 
    http://www.centos7.home, http://web1.centos7.home, http://web2.centos7.home and http://.centos7.home.

How Does It Work?

The purpose of this process was to show you how easy it is to implement name-based virtual hosting. This technique will boost your productivity and using this approach will give you unlimited opportunities to domain-based web hosting.

So what did we learn from this experience?

We began by creating a new Apache configuration file to hold all our virtual host configuration. Remember, all files ending with the .conf extension in the /etc/httpd/conf.d/ directory will be loaded automatically when Apache is started. Following this, we then proceeded to put in the relevant directive blocks, starting with our default server root centos7.home and the alias www.centos7.home. The most important option in any virtual host block is the ServerName directive, which maps an existing domain name for our web server’s IP address to a specific directory on the filesystem. Of course, there are many more settings you can include, but the previous solution provides the basic building blocks that will enable you to use it as the perfect starting point. The next step was to then create individual entries for our centos7.home subdomains web1, web2, and . Remember, each virtual host supports the typical Apache directives and can be customized to suit your needs. Refer to the official Apache manual (install the YUM package httpd-manual, then go to the location /usr/share/httpd/manual/vhosts/) to learn more. After we created our virtual host blocks for every subdomain we wanted, we then proceeded to create the directories to hold the actual content and created a basic index.html in each directory. In this example, our web1 and web2 content directories were added to /var/www. This is not to imply that you cannot create these new folders in another place. In fact most production servers generally place these new directories in the home folder, as shown with our /home//public_html example. However, if you do intend to take this approach, remember to modify the permissions and ownership, as well as SELinux labels (outside/var/www you need to label Apache directories as httpd_sys_content_t) of these new directories so that they can be used as they were intended. Finally, we reloaded the Apache web service so that our new settings would take immediate effect. We could then directly use the subdomain names in our browser to browse to our virtual hosts when correctly set up in /etc/hosts on the client or on a BIND DNS server.

 

Setting up an authoritative-only DNS server on CentOS

In this process, we will learn how to create an authoritative-only DNS server, which can give answers to queries about domains under their control themselves instead of redirecting the query to other DNS servers (such as our caching-only DNS server from the previous process). We will create a DNS server to resolve all our own hostnames and services in our own private local network.
 
As said before, while Unbound should be your first choice when needing a caching-only DNS server as it is the most secure DNS server solution available, it has only limited authoritative capabilities which often is not enough for professional DNS server usage. Here, instead of name lookup of our local servers, we will use the popular authoritative BIND DNS server package and configure a new DNS zone to provide highly customizable name resolution. Technically speaking, we will be writing both a forward and reverse zone file for our domain. Zone files are text files that contain the actual domain name to IP address mappings or the other way around, that is, IP address mappings to domain name mappings. While most queries to any DNS server will be the translation of names to IP addresses, the reverse part is also important to set up if you need the correct domain name for any given IP address. We will configure BIND to be authoritative-only, which means that the server will only answer queries it is authoritative for (has the matching records in its zones), so if the DNS server cannot resolve a requested domain, it will stop the request and not contact other DNS servers using recursive requests to fetch and construct the correct answer.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a static IP address, and a console-based text editor of your choice. An Internet connection will be required to download additional packages. In this example, our DNS server runs in the private network with the network address 192.168.1.0/24. Our DNS server should manage a local private domain we decide to be centos7.home (in the form domain.toplevel-domain). The IP address of the new DNS server will be 192.168.1.7 and should get the hostname ns1, leading to the Fully Qualified Domain Name (FQDN) ns1.centos7.home. (Refer to the Setting your hostname and resolving the network process in Chapter division 2 , Configuring the System to learn more about FQDNs). Our configured zone will have an administrative e-mail address with the name admin@centos7.home, and for simplicity, all the other computers in this network will get hostnames such as client1, client2, client3, and so on. We will also have some mail, web, and FTP servers in our own network, each running on separate dedicated servers. We will be using the port 8053 for our BIND service as we already have Unbound running on the same server using the default DNS port 53.

The Process

For security reasons, we will allow BIND to resolve internal LAN names only (authoritative-only) and only allow localhost to make DNS queries; no other clients in our network can connect to it:
  1. To begin with, log in as root on your Unbound DNS server and install the required BIND package and enable the DNS server on boot:
    yum install bind && systemctl enable named
  2. The actual name of the DNS server in the BIND package is called named, so let’s open its main configuration file to make some adjustments after creating a backup copy of it first:
    cp /etc/named.conf /etc/named.conf.BAK; vi /etc/named.conf
  3. First, find the line listen-on port 53 { 127.0.0.1; }; and then change the port number to the custom port 8053, so it reads as follows:
    listen-on port 8053 { 127.0.0.1; };
  4. Next, find the line listen-on-v6 port 53 { ::1; } and change it to:
    listen-on-v6 port 8053 { none; };
  5. Next, since we are configuring an authoritative-only server, we will disable contacting other remote DNS servers, find the line that reads recursion yes; and change it to:
    recursion no;
  6. Save and close the file, and then validate the syntax of our config changes (no output means no errors!):
    named-checkconf
  7. Now tell SELinux about the changed named DNS port (this needs package policycoreutils-python):
    semanage port -a -t dns_port_t -p tcp 8053
  8. Now type the following command in order to create your forward zone file. Name the file after the domain whose resource records it will contain:
    vi /var/named/..db
  9. In our example, for our centos7.home domain, this will be:
    vi /var/named/centos7.home.db
  10. Now simply add the following lines (be careful not to forget typing the tailing dots in the domain names). We will start with the Start of Authority (SOA) block:
    $TTL 3h
    @ IN SOA ns1.centos7.home. admin.centos7.home.(
    2015082400 ; Serial yyyymmddnn
    3h ; Refresh After 3 hours
    1h ; Retry Retry after 1 hour
    1w ; Expire after 1 week
    1h) ; Minimum negative caching
  11. Afterwards, add the rest of the file’s content:
    ; add your name servers here for your domain
              IN            NS           ns1.centos7.home.
    ; add your mail server here for the domain
              IN            MX     10    mailhost.centos7.home.
    ; now follows the actual domain name to IP
    ; address mappings:

    ; first add all referenced hostnames from above
    ns1              IN             A             192.168.1.7
    mailhost         IN             A             192.168.1.8
    ;  add all accessible domain to ip mappings here
    router          IN              A              192.168.1.0
    www             IN              A              192.168.1.9
    ftp             IN              A              192.168.1.10
    ;  add all the private clients on the Lan here
    client1         IN              A              192.168.1.11
    client2         IN              A              192.168.1.12
    client3         IN              A              192.168.1.13
    ;   finally we can define some aliases for
    ;   existing domain name mappings
    webserver IN CNAME www
    johnny IN CNAME client2

  12. When you have finished, simply save and close the file before proceeding to create the reverse zone file for our private subnetwork used by our domain (the C-Class are the first three numbers (octets) which are separated by dots: XXX.XXX.XXX. For example, for the 192.168.1.0/24 subnet the C-Class is 192.168.1:
    vi /var/named/db.
  13. In our example, a reverse zone file resolving our centos7.home's 192.168.1 C-Class subnet will be:
    vi /var/named/db.1.168.192
  14. First put in the exact same SOA as in step 10, and then append the following content to the end of the file:
    ;    add your name servers for your domain
                           IN          NS          ns1.centos7.home.
    ; here add the actual IP octet to
    ; subdomain mappings:
    7           IN          PTR       ns1.centos7.home.
    8           IN          PTR       mailhost.centos7.home.
    9           IN          PTR       www.centos7.home.
    10          IN          PTR       ftp.centos7.home.
    11          IN          PTR       client1.centos7.home.
    12          IN          PTR       client2.centos7.home.
    13          IN          PTR       client3.centos7.home.
  15. Save and close the file, and then add our new zone pair to the named configuration. To do this, open named.conf again:
    vi /etc/named.conf
  16. Now locate the line including "/etc/named.rfc1912.zones";. Immediately following this line, create a space for your work and add the appropriate zone statement to enable your reverse zone, as follows (substitute XXX.XXX.XXX with the reversed C-Class of your reverse zone file name, in our example 1.168.192):
    zone "XXX.XXX.XXX.in-addr.arpa." IN {
    type master;
    file "/var/named/db.XXX.XXX.XXX";
    update-policy local;
    };
  17.  Having done this, you can now proceed to add a zone statement for your forward zone right afterwards, as follows (replacing ..db with your forward zone file name, in our example centos7.home):

    zone ".." IN {
    type master;
    file "/var/named/..db";
    update-policy local;
    };

  18. When you have finished, simply save and close the file, and then restart the bind service using:
    named-checkconf && systemctl restart named

How Does It Work?

All DNS servers are configured to perform caching functions, but where a caching-only server is restricted in its ability to answer queries from remote DNS servers only, an authoritative nameserver is a DNS server that maintains the master zone for a particular record.
 
So what have we learned from this experience?
 
The purpose of this process was to setup an authoritative-only BIND DNS server and provide a new zone for it. A DNS zone defines all the available resources (hostnames and services) under a single domain. Any DNS zone should always consist of both a forward and reverse zone file. To understand zone configurations, we need to discuss DNS hierarchy first. For example, take a DNS domain from the example in this process client1.centos7.home. Every computer in our private network has a hostname (for example, client1 or www) and is a member of a domain. A domain consists of the Second-level Domain (SLD) (for example, centos7) and a Top-level Domain name (TLD) (for example, home, org, com, and so on). On top of that TLD is the root domain (written . dot) which often is neglected when working with other programs or configurations. However, when working or defining FQDN in zone configurations, it is very important to never forget to add this dot . after the TLD. For example, a DNS domain for our client1 computer would be client1.centos7.home., whereas an FQDN for the /etc/hosts file is often written in the format client1.centos7.home (technically this is incorrect but most of the time sufficient). The root domain is very important because it contains the root DNS servers which will be queried first if an authoritative DNS server cannot find an existing entry for a requested domain in its own records (zones) or cache. But we have DNS servers in all the other domain hierarchies as well and this is how a DNS server makes its recursive requests. A root DNS server, as any other DNS server, resolves all its subdomains (defined in its zone files) which are the TLDs. These TLDs themselves can resolve all the SLDs (also defined in their zone files). The second-level domains resolve all their hostnames (which are special subdomains as they refer to individual computer or services on your network). So any DNS request traverses through the different DNS server hierarchies from the root DNS over the TLD DNS to the SLD DNS server. The root and the TLD DNS servers cannot fully resolve full domain DNS queries such as www.centos7.home and instead will resolve the correct address of the next DNS hierarchy. This system ensures that the root DNS will always find the correct TLD DNS server address and the TLD DNS server will always send the request to the right SLD DNS which has the correct zone file and is finally able to answer the requested DNS query.
 
So what did we learn from this experience?
 
As we have learned, a zone file is a simple text file that consists of directives and resource records and can look quite complicated as it contains a lot of two-letter abbreviations. Remember, you need to set up a zone file pair (forward and reverse) on a base domain level (for example, centos7.home) for all the hostnames and services running under it (for example, www, host1, api, and so on). After installing the named DNS server (which is part of the Berkeley Internet Name Domain (BIND) package), we made a copy of the original main configuration file and changed the default listening port from 53 to 8053 (as unbound is already listening on port 53) but kept it listening to localhost only, and disabled IPv6 to keep compatibility with the other major DNS servers (as IPv6 support is still limited on the Internet). Also, here we disabled recursion because our BIND DNS server had to be authoritative-only, which means that it is not allowed to forward DNS requests to other remote DNS servers when it could not resolve the query from its own zone records.
 
Then we began creating and customizing our own forward DNS zone file with the filename convention /var/named/..db. This file is opened with the $TTL control statement, which stands for Time to Live and which provides other nameservers with a time value that determines how long they can cache the records from this zone. This directive, as many others, is defined using seconds as the default time unit, but you can also use other units using BIND specific short forms to indicate minutes (m), hours (h), days (d), and weeks (w), as we did in our example (3h). Following this, we then provided a Start of Authority (SOA) record. This record contains specific information about the zone as a whole. This begins with the zone name (@), a specification of the zone class (IN), the FQDN of this nameserver in the format hostname.domain.TLD., and an e-mail address of the zone administrator. This latter value is typically in the form hostmaster.hostname.domain.TLD. and it is formed by replacing the typical @ symbol with a dot (.). Having done this, it was then a matter of opening the brackets to assign the zone’s serial number, refresh value, retry value, expire value, and negative caching timeto-live value. These directives can be summarized as follows:
  • The serial-number value is a numeric value, typically taking the form of the date in reverse (YYYYMMDD) with an additional value (VV), which is incremented every time the zone file is modified or updated, in order to indicate that it is time for the named service to reload the zone. The value VV typically starts at 00, and the next time you modify this file, simply increment it to 01, 02, 03, and so on.
  • The time-to-refresh value determines how frequently the secondary or slave nameservers will ask the primary nameserver if any changes have been made to the zone.
  • The time-to-retry value determines how frequently the secondary or slave nameservers should check the primary server after the serial number has failed. If a failure has occurred during the time frame specified by the time-to-expire value elapses, the secondary nameservers will stop responding as an authority for requests.
  • The minimum-TTL value determines how long the other nameservers can cache negative responses.
Having completed this section and having closed the corresponding bracket, we then proceeded to add the authoritative nameserver information (NS) with the IN NS definition. Typically speaking, you will have at least two, if not three, nameservers (put each nameserver’s FQDN in a new IN NS line). However, it is possible to set only one nameserver, which is particularly useful if you are running the server in an office or a home environment and would like to enjoy the benefit of local name resolution, such as .home, .lan, or .dev. The next stage then required us to include a reference for the Mail eXchanger (MX) records in order for us to specify a mail server for the zone. The format is IN MX
. The priority becomes important if you define more than one mail server (each in its separate IN MX line)—the lower the number, the higher the priority. In this respect, a secondary mail server should have a higher value.
 
Note
In the SOA, NS and MX lines we already referenced hostnames which aren’t defined as an IP mapping yet (A record). We could do this because the zone file is not processed sequentially. But do not forget to create corresponding A lines for each hostname later.
 
Depending on your needs, you may also intend to use your name server as your mail server (then you would write instead MX 10 ns1.centos7.home.), although you may have another server dedicated to that role as shown in the example.
 
Following this, it was then a matter of creating the appropriate A records (A for address) and assigning the appropriate IP address to the values shown. This is the heart of any domain name resolution requests to the server. An A record is used for linking an FQDN to an IP address, but much of the preceding settings will be based on your exact needs. Here you can define all the local host names you want to map in your network. As we have already used and referenced some domain names before in the zone file such as the nameserver or mailserver we would begin with these. Afterwards, we defined all the hostnames to IP address mappings for all public available and afterwards our internal clients. Remember that when using the A records you can have multiple mappings of the same IP address to different hostnames. For example, if you do not have dedicated servers for every service in your network but rather one server running all your DNS, mail, web, and ftp services, you can write the following lines instead:
 
ns1             IN A 192.168.1.7
mailhost    IN A 192.168.1.7
www IN A 192.168.1.7
ftp             IN A 192.168.1.7
 
You can also use a canonical name (CNAME) record for this task, which is used to assign an alias to an existing A record. Arguably, the CNAME value makes your DNS data easier to manage by pointing back to an A record. So if you ever consider the need to change the IP address of the A record, all your CNAME records pointed to that record automatically. However, and as this process has tried to show, the alternative solution is to have multiple A records, which implies the need for multiple updates in order to change the IP address.
 
At this stage of the process, we then turned our attention towards the reverse DNS zone. As with the forward zone file, the reverse zone files also have a special naming convention /var/named/db.. Naming your reverse zone file like db.1.168.192 can look strange first but makes sense when you look at how reverse lookup works. It starts from the highest node (in our example 192, which corresponds to the root domain in the forward zone file) and traverses its way down from it. As you see, the content we put in this file has some similarities between the directives and the resources used in the forward zone file. However, it is important to remember that reverse DNS is wholly separate and distinct from forward DNS.
 
The reverse DNS zone is designed to assist in the conversion of an IP address to a domain name. This can be done by using the Pointer Resource Record (PTR) which assigns unique IP addresses to one or more host names. For this reason, you must ensure that a unique PTR record exists for every A record. Every reverse zone file collects IP to hostname translations for a complete Class C address range (the first three dotted numbers, for example, 192.168.1). The last octets of such an IP range are all the hostnames which can be defined within such a file. Remember, the IP address value for the first column in a PTR record should only show this last octet. For example, the line 9 IN PTR www.centos7.home. in the reverse zone file db.1.168.192 will be able to resolve any reverse IP address requests of 192.168.1.9 to the domain value www.centos7.home.
 
Having created our forward and reverse zone files in this process, we then completed the configuration of the named service by adding our new zones to our BIND server in order to start our own domain name service resolving local domain names of our network. In these new appended forward and reverse zone definition blocks, we defined that we are the master zone holder and also specified update-policy local; because this is needed if we want to use the nsupdate command to update our zones dynamically from the localhost (see later). You may add unlimited zone pairs, but remember that each forward or reverse zone definition must be given a single zone entry in curly brackets.
 
In summary, we can say that forward and reverse zone files are defined on a single base domain name basis, one base domain gets one forward zone file. For reverse zone files, it’s a bit different because we are working with IP addresses. We create one zone file based on the Class C address range of the network address of our domain and here the last octet is called the hostname, for which we define our mappings in such a specific file.
 
BIND is a big subject and there is a lot more to learn as this process has only served to introduce you to the subject. In most cases, you may even find that your initial learning period will become known as a process of trial and error, but it will improve. Remember, practice makes perfect and if you do create additional forward zones, always reference them in the reverse zone file.
 

There's more…

 
Having created and added your zones to your BIND server, you are now able to test your configuration. To do this, you can use the host, dig or nslookup command to resolve internal hostnames from localhost only. For example, for testing forward DNS resolution we can use the dig command by specifying that our DNS server is running on localhost with port 8053: dig -p 8053 @127.0.0.1 client2.centos7.home. This should finish DNS lookup successfully and return the following line (output is truncated):
;; ANSWER SECTION:
client2.centos7.home. 10800 IN A 192.168.1.12

 
For reverse lookup, you will use an IP address instead (in this instance, the IP address used should correspond to a domain for which you have configured reverse DNS): nslookup port=8053 192.168.1.12 127.0.0.1. As we have configured BIND as an authoritative-only DNS server, any DNS request which is outside the local records of our zone should not be able to get fully resolved. To test this use dig -p 8053 @127.0.0.1 www.google.com which should return the status REFUSED and WARNING: recursion requested but not available message.
 
For security reasons, we restricted our BIND server to localhost only and did not allow it to connect to other DNS servers. Therefore you cannot use it as your only DNS solution for your private network. Instead, in the next process, we will learn how to combine Unbound with BIND to create an integrated and very secure all-in-one DNS server solution. But if you don’t want to do this and use BIND as your single and full authoritative DNS server solution (which is not recommended on CentOS 7 anymore), you can do this by disabling or uninstalling Unbound, restoring the original named.conf.BAK configuration file, and enabling the following directives in the BIND configuration file: allow-query {localhost;192.168.1.0/24;}; (which enables the complete 192.168.1.0/24 network to make DNS requests), listen-on port 53 {any;}; (listen for requests on any network), listen-on-v6 port 8053 { none; }; (for disabling IPv6). If you want BIND to be forwarding everything, which it is not authoritative for, instead of using recursion to find out the answer, add the following directives as well (in this example we use the official Google DNS servers for any forwarding requests, but you can change this to fit your needs): forwarders { 8.8.8.8;};forward only;. Then restart the bind service.
 

Installing and configuring fail2ban in CentOS

In this process, we will learn how to implement additional security measures for protecting the SSH server with a package called fail2ban. This is a tool that serves to protect a variety of services including SSH, FTP, SMTP, Apache, and many more against unwanted visitors. It works by reading log files for patterns based on failed login attempts and deals with the offending IP addresses accordingly. Of course, you may have already hardened your SSH server or another service on a direct application level, but it is the purpose of this process to show that, when faced with the possibility of Brute Force Attacks, an added layer of protection is always useful.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet in order to download additional packages. In addition to this, it will be assumed that YUM is already configured to download packages from the EPEL repository.

The Process

Fail2ban is not installed by default, and for this reason, we will need to invoke the YUM package manager and download the necessary packages:

  1. To begin this process, log in as root and type the following command:
    yum install fail2ban-firewalld fail2ban-systemd
  2. Create a new configuration file in your favorite text editor, like so
    vi /etc/fail2ban/jail.local
  3. Put in the following content:
    [DEFAULT]
    findtime = 900
    [sshd]
    enabled = true
  4. Now, append the following line that defines the ban period. It is calculated in seconds, so adjust the time period to reflect a more suitable value. In this case, we have chosen this to be one hour:
    bantime = 3600
  5. Then, append the maximum number of login attempts:
    maxretry = 5
  6. If you are running SSH over a custom port other than 22, you need to tell this to fail2ban as well (replace XXXX with your port number of choice) otherwise skip this step:
    port=XXXX
  7. Now, save and close the file in the usual way before proceeding to enable the fail2ban service at boot. To do this, type the following command:
    systemctl enable fail2ban
  8. To complete this process, you should now start the service by typing:
    systemctl start fail2ban

How Does It Work?

fail2ban is designed to monitor users who repeatedly fail to log in correctly on your server, and its main purpose is to mitigate attacks designed to crack passwords and steal user credentials. It works by continuously reading your system’s log files, and if this contains a pattern indicating a number of failed attempts, then it will proceed to act against the offending IP address. We all know that servers do not exist in isolation, and by using this tool, within a few minutes, the server will be running with an additional blanket of protection.

So, what did we learn from this experience?

fail2ban is not available from the standard CentOS repositories, and for this reason your server will need to have access to the EPEL repository. The installation of the fail2ban packages was very simple; besides the main fail2ban package, we installed two other packages to integrate it into CentOS 7’s new systemd and firewalld server technologies. Next, for our local customization, we created a new jail. local file. We started specifying the findtime parameter for all targets (specified within the [DEFAULT] section), which is the amount of time a user has when attempting to log in. This value is measured in seconds and implies that, if a user fails to log in within the maximum number of attempts during the designated period, then they are banned. Next, we enabled fail2ban for the sshd daemon by adding a [sshd] section. In this section, we introduced the bantime value, which represents the total number of seconds that a host will be blocked from accessing the server if they are found to be in violation of the rules. Based on this, you were then asked to determine the maximum number of login attempts before blocking. Also, if you have changed your service’s standard listening port, you have to define the custom port using the port directive. To test your settings, try to authenticate a user using SSH and provide a wrong password five times. On the sixth occasion, you should not be able to get back to the login prompt for one hour!

Protecting the sshd service from Brute Force Attacks is just the first step to get you started, and there is much more to learn with failban. To troubleshoot the service, please look at its log file at /var/log/fail2ban.log. To get some ideas about what can be done with it, open the following example failban config file: less /etc/fail2ban/jail.conf.

 

Monitoring CentOS important server infrastructure

In this process, we will use a small script that will monitor the available filesystem’s disk space periodically using cron, and if it exceeds a certain percentage threshold the script will send out a mail with a warning message.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice. You should have read the Scheduling tasks with cron process to have a basic understanding of the principles behind the cron system.

The Process

  1. To begin this process, log in as root and create the following file that will contain our monitoring script:
    vi /etc/cron.daily/monitor_disk_space.sh
  2. Now, put in the following content:
    #!/bin/bash
    EMAIL="root@localhost"
    THRESHOLD=70
    df -H | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $6 }'
    | while read output;
    do
      usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1 )
      partition=$(echo $output | awk '{ print $2 }' )
      if [ $usep -ge $THRESHOLD ]; then
      (echo "Subject: Alert: Free space low on `hostname -s`, $usep % used
    on $partition"; echo)|
      sendmail -t $EMAIL
      fi
    done
  3. Now, save the file and make it executable:
    chmod +x /etc/cron.daily/monitor_disk_space.sh

How it works…

We made this script executable and put it in the /etc/cron.daily directory, which is all we need to do to run this script automatically every day via the crond service.

This simple script showed us how easy it is to build monitoring scripts, and this can be a real alternative to installing and configuring big monitoring suites such as Nagios. You can use the shown script as a starting point to expand on, adding further resources that are important to monitor, such as CPU load, available RAM, and so on.

We used a script that executes the Linux command df, which is a tool to report file system disk space usage. From this command’s output, the script then parsed the USE% column (with the Unix tools awk and cut), which gives us the total disk percentage used. This number will then be compared to a threshold the user can set by editing the script and changing the environment variable, THRESHOLD. If the extracted percentage number is higher than our threshold, there will be an email sent to the email address defined with the environment variable, EMAIL (change appropriately if needed).

 

Introduction to Vim on CentOS

Here in this process, we will give you a very brief introduction to the text editor, Vim, which is used as the standard text editor everywhere. You can also use any other text editor you prefer, such as nano or emacs, instead.

To Start With: What Do You Need?

For implementing this process, you will require a working installation of the CentOS 7 operating system with root privileges.

The Process

We will start this process by installing the vim-enhanced package, as it contains a tutorial you can use to learn to work with Vim:

  1. To begin, log in as root and install the following package:
    yum install vim-enhanced
  2. Afterward, type the following command to start the Vim tutorial
    vimtutor
  3. This will open the Vim tutorial in the Vim editor. To navigate, press the up and down key to scroll up and down single-line wise. To exit the tutorial, press the Esc key, then type :q!, followed by the Return key to exit.
  4. You should now read through the file and go through the lessons to get a basic understanding of Vim, to learn how to edit your text documents.

How it works..

The tutorial shown should be seen as a starting point from which we should start learning the basics for working with one of the most powerful and effective text editors available for Linux. Vim has a very steep learning curve, but after dedicating about half an hour to the vimtutor guide, you should be able to do all the common text editing tasks without any problem, such as opening, editing, and saving text files.

 

Monitoring important remote system metrics

The Nagios plugin check_multi is a convenient tool to execute multiple checks within a single check command that generates an overall returned state and output from it. Here in this process, we will show you how to set it up and use it to quickly monitor a list of important system metrics on your clients.

To Start With: What Do You Need?

It is assumed that you’ve gone through this segment division process by process, therefore by now, you should have a Nagios server running and another client computer that you want to monitor, which can already be accessed via its NRPE service externally by our Nagios server. This client computer that you want to monitor needs an installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice installed on it, as well as a connection to the Internet in order to facilitate the download of additional packages. The client computer will have the IP address 192.168.1.8.

The Process

The check_multi Nagios plugin is available from Github, so we will begin this process to install the git program by downloading it:
  1. Log in as root on your client computer and install Git if not done already:
    yum install git
  2. Now, download and install the check_multi plugin by compiling it from the source:
    cd /tmp;git clone git://github.com/flackem/check_multi;cd
    /tmp/check_multi
    ./configure --with-nagios-name=nagios --with-nagios-user=nagios --withnagios-
    group=nagios --with-plugin-path=/usr/lib64/nagios/plugins --
    libexecdir=/usr/lib64/nagios/plugins/
    make all;make install;make install-config
  3. Next, we install another very useful plugin called check_mem, which is not available in the CentOS 7 Nagios plugin rpms:
    cd /tmp;git clone https://github.com/justintime/nagios-plugins.git
    cp /tmp/nagios-plugins/check_mem/check_mem.pl
    /usr/lib64/nagios/plugins/
  4. Next, let’s create a check_multi command file that will contain all your desired client checks that you want to combine in a single run; open the following file:
    vi /usr/local/nagios/etc/check_multi/check_multi.cmd
  5. Put in the following content:
    command[ sys_load::check_load ] = check_load -w 5,4,3 -c 10,8,6
    command[ sys_mem::check_mem ] = check_mem.pl -w 10 -c 5 -f -C
    command[ sys_users::check_users ] = check_users -w 5 -c 10
    command[ sys_disks::check_disk ] = check_disk -w 5% -c 2% -X nfs
    command[ sys_procs::check_procs ] = check_procs
  6. Next, test out the command file that we just created in the last step using the following commandline:
    /usr/lib64/nagios/plugins/check_multi -f
    /usr/local/nagios/etc/check_multi/check_multi.cmd
  7. If everything is correct, it should print out the results of your five plugin checks and an overall result, for example, OK -5 plugins checked. Next, we will install this new command in the NRPE service on our client so that the Nagios server is able to execute it remotely by calling its name. Open the NRPE configuration file:
    vi /etc/nagios/nrpe.cfg
  8. Add the following line to the end of the file right below the last # command line to expose a new command called check_multicmd to our Nagios server:
    command[check_multicmd]=/usr/lib64/nagios/plugins/check_multi -f
    /usr/local/nagios/etc/check_multi/check_multi.cmd
  9. Finally, let’s reload NRPE:
    systemctl restart nrpe
  10. Now, let’s check whether we can execute our new check_multicmd command that we defined in the last step from our Nagios server. Log in as root and type the following command (change the IP address of your client, 192.168.1.8, appropriately):
    /usr/lib64/nagios/plugins/check_nrpe -H 192.168.1.8 -c "check_multicmd"
  11. If the output is the same as running it locally on the client itself (take a look at the former step), we can successfully execute remote NRPE commands on our client through our server, so let’s define the command on our Nagios server system for real so that we can start using it within the Nagios system. Open the following file:
    vi /etc/nagios/objects/commands.cfg
  12. Put in the following content at the end of the file to define a new command called check_nrpe_multi, which we can use in any service definition:
    define command {
    command_name check_nrpe_multi
    command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c "check_multicmd"
    }
  13. Next, we will define a new server definition for the client that we want to monitor on our Nagios server (give the config file an appropriate name, for example, its domain name or IP address):
    vi /etc/nagios/servers/192.168.1.8.cfg
  14. Put in the following content, which will define a new host with its service, using our new Nagios command that we just created:
    define host {
             use                      linux-server
             host_name          host1
             address               192.168.1.22
             contact_groups     unix-admins
    }
    define service {
                    use generic-service
                    host_name host1
                    check_command check_nrpe_multi
                    normal_check_interval 15
                    service_description check_nrpe_multi service
    }
  15. Finally, we need to configure all persons who should get notification e-mails for our new service in case of errors. Open the following file:
    vi /etc/nagios/objects/contacts.cfg
  16. Put in the following content at the end of the file:
    define contactgroup{
                  contactgroup_name           unix-admins
                   alias                      Unix Administrators
    }
    define contact {
               contact_name                       pelz
                use                               generic-contact
                alias                             Oliver Pelz
                contactgroups                     unix-admins
                email                             oliverpelz@mymailhost.com
    }
  17. Now, restart the Nagios service:
    systemctl restart nagios

How Does It Work?

We started this process by installing the check_multi and check_mem plugins from their author’s Github repositories; they are plain command-line tools. Nagios performs checks by running such external commands, and it uses the return code along with output from the command as information on whether the check was successful or not. Nagios has a very flexible architecture that can be easily extended using plugins, add-ons, and extensions. A central place to search for all kinds of extensions is at https://exchange.nagios.org/ . Next, we added a new command file for check_multi, where we put five different system check_ commands in. These checks act as a starting point for customizing your monitoring needs and will check system load, memory consumption, system users, free space, and processes. All available check_ commands can be found at /usr/lib64/nagios/plugins/check_*. As you can see in our command file, the parameters of those check_ commands can be very different, and explaining them all is out of the scope of this process. Most of them are used to set threshold values to reach a certain state, for example, the CRITICAL state. To get more information about a specific command, use the --help parameter with the command. For example, to find out what all the parameters in the check_load -w 5,4,3 -c 10,8,6 command are doing, use run /usr/lib64/nagios/plugins/check_load --help. You can easily add any number of new check commands to our command file from existing plugins, or you can download and install any new commands, if you like. There are also a number of command file examples shipped with the check_multi plugin, which are very useful for learning, so please have a look at the directory: /usr/local/nagios/etc/check_multi/*.cmd.
 
Afterwards, we checked the correctness of our new command file that we just created by dry-running it as an -f parameter from the check_multi command locally on the client. In its output, you will find all the single outputs as if you would have run these five commands individually. If one single check fails, the complete check_multi will do. Next, we defined a new NRPE command in the NRPE config file called check_multicmd that can then be executed from the Nagios server, which we tested in the next step from our Nagios server. For a test to be successful, we expect the same results as we got when calling the command from the client itself. Afterwards, we defined this command in our commands.cfg on the Nagios server so that we can reuse it as much as we like in any service definition by referencing the command’s name, check_nrpe_multi. Next, we created a new server file named as the IP address (you can name it anything you like as long it has the .cfg extension in the directory) of the client we want to monitor: 192.168.1.8.cfg. It contains exactly one host definition and one or multiple service definitions, which are linked by the value of host_name of the host with the host_name value in your service definitions.
 
In the host definition, we defined a contact_groups contact that links to the contacts.cfg file’s contact group and contact entry. These will be used to send notification e-mails if the checked service has any errors. The most important value in the service definition is the check_command check_nrpe_multi line, which executes the command that we created before as our one and only check. Also, the normal_check_interval is important as it defines how often the service will be checked under normal conditions. Here, it gets checked every 15 minutes. You can add as many service definitions to a host as you like.
 
Now, go to your Nagios web frontend to inspect your new host and service. Here, go to the Hosts tab, where you will see the new host, host1, that you defined in this process, and it should give you information about its status. If you click on the Services tab, you will see the check_nrpe_multi service. It should show the Status as Pending, OK, or CRITICAL, depending on the success of the single checks. If you click on its check_nrpe_multi link, you will see details about the checks.
 
 We could only show you the very basics of Nagios, and there is always more to learn, so please read the official Nagios Core documentation at https://www.nagios.org , or check out the book Learning Nagios 4, Packt Publishing, by Wojciech Kocjan.