Lab 7: Linux Network Security, Firewall, NAT Routing, and DHCP Server

Introduction

In this lab you will perform the following tasks:

  • View Open Ports on your Linux Server

  • Scan Other Systems for Open Ports

  • Configure a Host Based Firewall on your Linux Server

  • Enable Packet Forwarding and configure your Linux Server as a NAT Router

  • Configure your Linux Server as a DHCP Server

  • Install Linux Mint as a client behind your Linux Server NAT Router

  • Configure Port Forwarding on your Linux Server to Access a Client Behind the NAT Router

  • Secure SSH Using SSH Keys

  • Secure SSH Using 2FA

  • Enable Fail2Ban for SSH Log Monitoring

You will be introduced to the following commands:

  • ss

  • nmap

  • iptables

  • nftables

  • firewall-cmd

  • fail2ban

Preliminaries

  1. Open an SSH remote terminal session to your Linux server’s IP address

    1. Connect to ITCnet from the computer you will be using as your administrative PC. In most cases this means connecting to the ITC Student VPN (unless you are using the Netlab Windows Administrative PC).

    2. Run the PuTTY software on your computer (or the Windows Administrative PC) and enter in the IP address of your Linux server VM in the "Host Name" box and click the "Open" button.

      Remember that if you do not have a Windows computer to connect from you can either figure out how to SSH from your own computer over the VPN to your Linux server or you can use the Windows Administrative PC that is provided for you in Netlab.
  2. Login with your standard user’s username and password

Monitoring Connections and Open Ports

  1. One common activity you would want to do when evaluating the security of a system is to find out what ports the system is accepting connections on. For this reason most operating systems have some kind of utility to display active network connections and open ports, Linux is no exception. Traditionally the netstat utility, which stands for network statistics, has been used to show open ports, incoming and outgoing connections, routing tables, interface statistics, masquerade connections, and multicast memberships. However, the more modern ss utility, which is short for socket statistics, can provide much of the same information in a much faster way, especially when there are a large number of connections on a server. Both tools can be used to identify unauthorized connections or traffic that could indicate a security breach, performance issues, or undesired applications running on the server. They are crucial for system and network administrators to ensure the integrity and efficiency of server operations.

  2. Review the manual page for ss. Specifically, figure out what the -n -a -l -t -p and -u options do.

  3. Try the ss -ntup and ss -tup commands and figure out what is being shown on your screen and in the output below. Be sure to run the commands with administrative permissions in order to have full access to see all the sockets open on your system and their details.

    ben@2480-Z:~$ sudo ss -ntup
    Netid              State              Recv-Q              Send-Q                           Local Address:Port                           Peer Address:Port               Process
    tcp                ESTAB              0                   64                                172.17.50.36:22                             172.17.202.3:50358               users:(("sshd",pid=51036,fd=4),("sshd",pid=51020,fd=4))
    ben@2480-Z:~$ sudo ss -tup
    Netid              State              Recv-Q              Send-Q                           Local Address:Port                           Peer Address:Port               Process
    tcp                ESTAB              0                   64                                172.17.50.36:ssh                            172.17.202.3:50358               users:(("sshd",pid=51036,fd=4),("sshd",pid=51020,fd=4))
  4. Try the ss -nltup command and figure out what is being shown on your screen and in the output below:

    ben@2480-Z:~$ sudo ss -nltup
    Netid        State         Recv-Q        Send-Q                Local Address:Port                 Peer Address:Port        Process
    udp          UNCONN        0             0                        127.0.0.54:53                        0.0.0.0:*            users:(("systemd-resolve",pid=334,fd=20))
    udp          UNCONN        0             0                     127.0.0.53%lo:53                        0.0.0.0:*            users:(("systemd-resolve",pid=334,fd=18))
    udp          UNCONN        0             0                           0.0.0.0:5355                      0.0.0.0:*            users:(("systemd-resolve",pid=334,fd=11))
    udp          UNCONN        0             0                              [::]:5355                         [::]:*            users:(("systemd-resolve",pid=334,fd=13))
    tcp          LISTEN        0             80                        127.0.0.1:3306                      0.0.0.0:*            users:(("mariadbd",pid=29657,fd=18))
    tcp          LISTEN        0             4096                     127.0.0.54:53                        0.0.0.0:*            users:(("systemd-resolve",pid=334,fd=21))
    tcp          LISTEN        0             128                         0.0.0.0:22                        0.0.0.0:*            users:(("sshd",pid=508,fd=3))
    tcp          LISTEN        0             511                         0.0.0.0:80                        0.0.0.0:*            users:(("nginx",pid=48789,fd=5),("nginx",pid=48788,fd=5))
    tcp          LISTEN        0             4096                        0.0.0.0:5355                      0.0.0.0:*            users:(("systemd-resolve",pid=334,fd=12))
    tcp          LISTEN        0             4096                  127.0.0.53%lo:53                        0.0.0.0:*            users:(("systemd-resolve",pid=334,fd=19))
    tcp          LISTEN        0             128                            [::]:22                           [::]:*            users:(("sshd",pid=508,fd=4))
    tcp          LISTEN        0             511                            [::]:80                           [::]:*            users:(("nginx",pid=48789,fd=6),("nginx",pid=48788,fd=6))
    tcp          LISTEN        0             4096                           [::]:5355                         [::]:*            users:(("systemd-resolve",pid=334,fd=14))
  5. Notice that there are a number of ports open on your system. Some of these we have opened to provide a specific service such as SSH, Webserver, etc. but sometimes ports are open simply by default when some software has been installed. On older distributions of Linux there are even several ports open by default on fresh installs!

  6. Note that in the local address column there are some addresses (such as the one for mariadb) listed as 127.0.0.x. These are services open only to the localhost (other software running on the server itself) and not to remote connections over the network. This is generally a more secure option if you don’t need to access the service remotely.

  7. There are a number of different strategies you can use to secure your system including disabling a service, binding it to an internal-only IP address (such as a localhost address), or blocking access with a firewall rule. If your firewall is setup with an implicit (or explicit) reject any rule at the bottom of the input chain and you have not specifically opened a port it should not be accessible from other systems. We’ll explore the option of using a firewall to explicitly control access to ports on our system later in this lab.

  8. Try the ss -natup command and figure out what is being shown on your screen and in the output below and how it differs from the previous command:

    ben@2480-Z:~$ sudo ss -natup
    Netid        State         Recv-Q        Send-Q               Local Address:Port                 Peer Address:Port         Process
    udp          UNCONN        0             0                       127.0.0.54:53                        0.0.0.0:*             users:(("systemd-resolve",pid=334,fd=20))
    udp          UNCONN        0             0                    127.0.0.53%lo:53                        0.0.0.0:*             users:(("systemd-resolve",pid=334,fd=18))
    udp          UNCONN        0             0                          0.0.0.0:5355                      0.0.0.0:*             users:(("systemd-resolve",pid=334,fd=11))
    udp          UNCONN        0             0                             [::]:5355                         [::]:*             users:(("systemd-resolve",pid=334,fd=13))
    tcp          LISTEN        0             80                       127.0.0.1:3306                      0.0.0.0:*             users:(("mariadbd",pid=29657,fd=18))
    tcp          LISTEN        0             4096                    127.0.0.54:53                        0.0.0.0:*             users:(("systemd-resolve",pid=334,fd=21))
    tcp          LISTEN        0             128                        0.0.0.0:22                        0.0.0.0:*             users:(("sshd",pid=508,fd=3))
    tcp          LISTEN        0             511                        0.0.0.0:80                        0.0.0.0:*             users:(("nginx",pid=48789,fd=5),("nginx",pid=48788,fd=5))
    tcp          LISTEN        0             4096                       0.0.0.0:5355                      0.0.0.0:*             users:(("systemd-resolve",pid=334,fd=12))
    tcp          LISTEN        0             4096                 127.0.0.53%lo:53                        0.0.0.0:*             users:(("systemd-resolve",pid=334,fd=19))
    tcp          ESTAB         0             64                    172.17.50.36:22                   172.17.202.3:50358         users:(("sshd",pid=51036,fd=4),("sshd",pid=51020,fd=4))
    tcp          LISTEN        0             128                           [::]:22                           [::]:*             users:(("sshd",pid=508,fd=4))
    tcp          LISTEN        0             511                           [::]:80                           [::]:*             users:(("nginx",pid=48789,fd=6),("nginx",pid=48788,fd=6))
    tcp          LISTEN        0             4096                          [::]:5355                         [::]:*             users:(("systemd-resolve",pid=334,fd=14))
  9. Using the web browser on your administrative PC connect to your website at http://172.17.xx.xx/blog and then within a short period of time run the ss -natup and ss -ntup commands again. You should see something like this:

    ben@2480-Z:~$ sudo ss -ntup
    Netid        State        Recv-Q         Send-Q                 Local Address:Port                 Peer Address:Port         Process
    tcp          ESTAB        0              0                       172.17.50.36:80                   172.17.202.3:55738         users:(("nginx",pid=48789,fd=12))
    tcp          ESTAB        0              0                       172.17.50.36:80                   172.17.202.3:55737         users:(("nginx",pid=48789,fd=11))
    tcp          ESTAB        0              64                      172.17.50.36:22                   172.17.202.3:50358         users:(("sshd",pid=51036,fd=4),("sshd",pid=51020,fd=4))
    tcp          ESTAB        0              0                       172.17.50.36:80                   172.17.202.3:55733         users:(("nginx",pid=48789,fd=4))
  10. Notice how you can see now the open TCP connections between Nginx and the web browser on your administrative PC as well as the IP address of your administrative PC. This can be a useful tool for seeing what systems are connected to your server, on what port they are connected, and what software or process on the server they are connected to.

Scan Other Systems for Open Ports

  1. Sometimes we want to verify what ports are open on a system by checking from another computer. The nmap, or Network Mapper, utility is a very powerful security scanning utility available on Linux. While ss or netstat use information from the Linux kernel about what ports and connections are in use by what processes nmap actively probes and tests ports on your system or another system to determine whether the port is open or not as well as additional information about the port in some cases. nmap is a complex and powerful utility. Entire books and extensive documentation are available which you may want to reference but we’ll only be exploring some of the more basic features in this introductory lab activity.

    Before we begin this section of the lab it is important to remember that scanning a system is often seen as an attack against the system and should not be done unless you are the administrator of both the system that you are scanning from and the system you are scanning or have the explicit permission of the system administrator of those systems! In some areas people have been legally charged and prosecuted for scanning of systems which they are not authorized to do. You have been warned!
  2. nmap provides a system on the Internet which they allow you to scan for testing purposes so let’s try a verbose scan which gives additional diagnostic detail by running the nmap -v scanme.nmap.org command which will take a minute to run:

    ben@2480-Z:~$ nmap -v scanme.nmap.org
    Starting Nmap 7.93 ( https://nmap.org ) at 2024-06-25 12:03 CDT
    Initiating Ping Scan at 12:03
    Scanning scanme.nmap.org (45.33.32.156) [2 ports]
    Completed Ping Scan at 12:03, 0.05s elapsed (1 total hosts)
    Initiating Parallel DNS resolution of 1 host. at 12:03
    Completed Parallel DNS resolution of 1 host. at 12:04, 13.00s elapsed
    Initiating Connect Scan at 12:04
    Scanning scanme.nmap.org (45.33.32.156) [1000 ports]
    Discovered open port 80/tcp on 45.33.32.156
    Discovered open port 22/tcp on 45.33.32.156
    Discovered open port 31337/tcp on 45.33.32.156
    Discovered open port 9929/tcp on 45.33.32.156
    Completed Connect Scan at 12:04, 0.73s elapsed (1000 total ports)
    Nmap scan report for scanme.nmap.org (45.33.32.156)
    Host is up (0.048s latency).
    Other addresses for scanme.nmap.org (not scanned): 2600:3c01::f03c:91ff:fe18:bb2f
    Not shown: 996 closed tcp ports (conn-refused)
    PORT      STATE SERVICE
    22/tcp    open  ssh
    80/tcp    open  http
    9929/tcp  open  nping-echo
    31337/tcp open  Elite
    
    Read data files from: /usr/bin/../share/nmap
    Nmap done: 1 IP address (1 host up) scanned in 17.82 seconds
  3. You can see in the output above that nmap discovered four open ports on the scanme.nmap.org system at the time of this scan. Furthermore, nmap was able to determine the likely service running on each of those ports and show the name of the service.

  4. The -v option makes the output more verbose which means more detail is provided. Try again, but without the -v option this time to get just the standard output. Use the command nmap scanme.nmap.org and take note of what the difference is while the command is running.

  5. When scanning your own system there are a few different ways to go about it. You could either scan the localhost address 127.0.0.1 or the actual outside IP address of your system. You could also setup a separate system or VM and do the scanning from that system. In each case you might see somewhat different results, can you guess why?

  6. The answer is related to how you have firewall rules setup and what addresses you have services bound to. For example by default on Debian systems the MySQL/MariaDB server daemon only listens for connections on the localhost address (127.0.0.1) and not on outside interfaces.

  7. Try running the nmap 127.0.0.1 command and then compare output with the nmap <your outside 172.17.xx.xx ip address here> command. Do you see some network services listening only on the localhost address? These services are not accessible from outside your computer even though the ports are open and you would see them as open with ss.

  8. The most realistic use of nmap though is to scan like an attacker would using a system outside of the one you’re testing. In fact it’s even possible to scan a whole range of IP addresses at once. Use nmap to scan the entire Linux System Administration class subnet with the nmap 172.17.50.0/23 command. Note that this could take some time depending on how many systems respond to nmap.

    Remember that in our case these systems are secure from the outside world because we have an upstream firewall which you have bypassed by connecting to our VPN or using an administrative PC through Netlab and these systems are using unroutable private IPv4 addresses.
  9. Take a look at the nmap book or documentation and try running a few different types of nmap scans on one of the systems you found in the Linux System Administration class subnet.

  10. nmap also supports scanning IPv6 addresses but it needs to be done separately from IPv4. Note that a running service is not necessarily listening on both IPv4 and IPv6 addresses just because you have them both active on your operating system. Figure out how to scan IPv6 addresses with nmap and try scanning both an IPv4 and IPv6 address of your machine and compare the results. Use the same type of address (i.e. both IPv4 and IPv6 addresses should be the localhost addresses or should both be outside addresses) Are the same services open on both IPv4 and IPv6 on your system?

Configure a Host Based Firewall on your Linux Server

In this section of the lab you will be configuring a firewall on your Linux Server. You will be doing this while connected to your Linux Server’s IP address over SSH. This is obviously a bit risky because if you make a mistake during the firewall configuration you could block SSH access to your Linux Server. Thus, it is important to have a backup plan. Luckily, our servers are running as VMs through Netlab so we have access to the server console through Netlab which will continue to work. So, if you have an issue and are no longer able to access your server over SSH you will need to login to Netlab and access your server that way until you have fixed the firewall rule to allow SSH access.

  1. One of the important steps towards securing any system is to limit the attack surface. When we’re talking about a networked system one way that this is typically done is to make certain that only those ports we want to have open to the world are actually open. One of the most common ways of doing this is to use a host-based firewall running on the system. Like all modern network operating systems Linux has a built-in host-based firewall. Tradtionally the Linux firewall was based around iptables but starting in 2014 distributions began replacing that with the newer and more flexible nftables solution.

  2. While it was somewhat common to write your own firewall rules directly in the iptables era the additional flexibility provided by nftables has made writing rules more complex. Many ditributions, including Debian, still provide compatible versions of the iptables commands which actually create nftables rules under the hood but it’s also become increasingly more common to use a utility to manage the firewall rules instead of writing them directly yourself. One reason for this is to reduce the complexity of managing a firewall by automatically handling things like implementing the rules automatically each time the system boots.

  3. Two of the most common tools for managing firewall rules on Linux systems are firewalld and ufw. While ufw provides a basic host-based firewall it still relies on iptables or at least iptables compatible commands to implement it’s rules. On the other hand firewalld supports nftables natively and also supports defining zones and multiple complex rulesets such as those needed when multiple interfaces are connected to different networks. In this lab activity we’ll explore the use of firewalld to manage the nftables firewall on our server.

  4. Begin by installing the firewalld package on your system.

  5. Use the firewall-cmd --state command to check and see if the firewall is now up and running

    ben@2480-Z:~$ sudo firewall-cmd --state
    running
  6. Check to see what rules are currently applied in your firewall using the firewall-cmd --list-all command:

    ben@2480-Z:~$ sudo firewall-cmd --list-all
    public
      target: default
      icmp-block-inversion: no
      interfaces:
      sources:
      services: dhcpv6-client ssh
      ports:
      protocols:
      forward: yes
      masquerade: no
      forward-ports:
      source-ports:
      icmp-blocks:
      rich rules:
  7. By default all interfaces are in the public zone (this is set in the /etc/firewalld/firewalld.conf file). We can create custom zones or use pre-defined security zones which will speed up configuring the firewall. Take a minute to read more about the pre-defined zones in firewalld documentation.

  8. Before we start working on rules for our firewall we should assign (move) our outside network interface (ens192) to the external zone which is designed for NAT routing which we’ll be setting up shortly. Do this by running the firewall-cmd --zone=external --add-interface=ens192 command.

  9. Check to see what rules are enabled for the external zone. This time you will need to specify the zone name as it’s not the default public zone anymore. Use the firewall-cmd --zone=external --list-all command to do this.

  10. You can also check the rules on all zones with the firewall-cmd --list-all-zones command.

  11. If you were watching carefully you may have noted that the dhcpv6-client service was allowed in the public zone is not allowed by default on the external zone. This will prevent our server from being able to receive a DHCPv6 IP address on our ens192 interface anymore. Since we want to allow that run the firewall-cmd --zone=external --add-service="dhcpv6-client" command to allow the dhcpv6-client service on interfaces in the external zone.

  12. Try accessing your website again from your administrative PC by browsing to http://172.17.xx.xx/blog. You should notice that your site is no longer accessible because your firewall is blocking traffic on port 80 from getting to nginx!

  13. Run the firewall-cmd --get-services command on your system to see what services firewalld can create rules for.

    Just because firewalld doesn’t know about every service does not mean you can’t create a rule to allow the service. While the services are a convenient way to make services work (because they can open multiple ports with one rule if needed for the service) you can create manual rules that open a particular TCP or UDP port from a zone.

    An example of creating just such a rule would be the firewall-cmd --zone=external --add-port=31337/tcp command which would allow incoming TCP traffic on the non-standard port 31337 to the server from the external zone.

    It’s even possible to create your own custom services which can implement a variety of rules all at once when activated.

  14. Try creating a new rule on the external zone to allow access to the http service from that zone. If you have done this successfully your external zone rules should now look like the ones below and your site should be accessible again from the administrative PC browser.

    ben@2480-Z:~$ sudo firewall-cmd --zone=external --list-all
    external (active)
      target: default
      icmp-block-inversion: no
      interfaces: ens192
      sources:
      services: dhcpv6-client http ssh
      ports:
      protocols:
      forward: yes
      masquerade: yes
      forward-ports:
      source-ports:
      icmp-blocks:
      rich rules:
  15. There is one more very important thing to know about firewalld. By default, changes you make to the firewall are applied instantly. However, when the system is rebooted everything will go back to the same configuration that was in place the last time the system booted. This means if you make an error when configuring the firewall and lock yourself out of the system a reboot of the system will most likely get you back in. However, once you have tested and verified that your rules are working the way you want you need an extra command to save them permanently to be applied the next time the system boots. Run the firewall-cmd --runtime-to-permanent command now to save automatically apply your current firewall rules the next time the system boots.

Enable Packet Forwarding and configure your Linux Server as a NAT Router

  1. One of the things you may want to do with a Linux server is to use it as a router. To do this we’ll need to use a second network interface card attached to a second network. Our virtual lab environment is already setup with a second network interface card (ens224) in our Linux server which is attached to a small network with just one client computer. While it’s possible to install routing protocol software (such as OSPF or BGP) in Linux and use it as a regular enterprise router it’s probably more likely that you’ll want to use it as a SOHO NAT router. In fact, many of the commercial SOHO NAT routers use Linux themselves!

  2. The first thing we need to do is to configure that second NIC (ens224) with an IP address. Create a new /etc/systemd/network/20-internal.network file just like we did back in lab 5 for our primary network.

    1. Be sure to set the match interface to ens224

    2. Use 192.168.1.1/24 as the IP address and mask

    3. Do not configure a gateway, DNS, or IPv6 settings for the new interface

  3. Apply the changes to our network configuration run the systemctl restart systemd-networkd command as the admninistrative user.

  4. Check that the ip_forward permission is enabled on your Linux server by running sysctl net.ipv4.ip_forward as thge administrative user and making sure that the output shows a 1 for enabled.

    The ip_forward permission is used to determine if Linux will forward packets from one network to another. It is usually off by default but activating newer versions of firewalld will automatically enable it to allow traffic to flow between multiple interfaces in the same zone. If you run the firewall-cmd --zone=external --list-all command you’ll notice there is a forward: yes line by default in the external zone.

    If you are not using firewalld and need to activate the ip_forward permission in Debian Linux it is usually done by opening the /etc/sysctl.conf file and un-commenting (removing the # at the beginning of the line) the net.ipv4.ip_forward=1 line which will apply the next time the system is restarted. If you also want to apply the change immediately without rebooting you would use the sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward' command.

  5. Put the second NIC (ens224) into the internal zone of firewalld

  6. Modify the firewall to allow access to the ssh and http services on your Linux server from clients on the internal zone.

  7. Ensure that all devices on your internal zone will share one IP on your external zone. This is commonly called NAT but is really called port address translation (PAT) by some vendors such as Cisco and NAT masquerading by Linux. This is actually a setting on the external zone and not the internal zone. You should see a masquerade: yes line in the rules for the zone. If you don’t or need to enable it on a custom outside zone you can do so with a command like firewall-cmd --add-masquerade --zone=external.

  8. Add a policy to your firewall which allows traffic from the internal zone to the external zone

    1. Create a new policy named internal-external with the firewall-cmd --permanent --new-policy internal-external command

    2. Set the policy to apply to traffic originating from the internal zone with the firewall-cmd --permanent --policy internal-external --add-ingress-zone internal command.

    3. Set the policy to apply to traffic leaving the external zone with the firewall-cmd --permanent --policy internal-external --add-egress-zone external command.

    4. Set the policy to allow traffic matching this policy by default with the firewall-cmd --policy internal-external --set-target=ACCEPT --permanent command.

  9. Just as before once you are satisfied your firewall is running correctly you should use the firewall-cmd --runtime-to-permanent command to set these rules to automatically load each time the system is started.

  10. Reload the firewall with the firewall-cmd --reload command.

Configure your Linux Server as a DHCP Server

  1. We want our inside client network to receive IPv4 addresses automatically from a DHCP server so we’ll configure our Linux Server to also act as a DHCPv4 server using the ISC Kea DHCP server software.

  2. Begin by installing the kea-dhcp4-server package on your server.

  3. There are a lot of options that can be used for an advanced DHCP server. The configuration file for Kea is explained in the Kea Administrator Reference Manual but for our purposes of a very simple DHCP server we don’t need too much configuration. Let’s move the existing sample configuration file from /etc/kea/kea-dhcp4.conf to /etc/kea/kea-dhcp4.bak to keep it as a backup just in case we want to reference it.

  4. After moving the sample Kea configurtion file to a backup copy start nano as an adminsitrative user with a new blank /etc/kea/kea-dhcp4.conf file and put the following contents into it and save the file:

    {
        "Dhcp4": {
            "interfaces-config": {
                "interfaces": [
                    "ens224"
                ]
            },
            "lease-database": {
                "type": "memfile",
                "persist": true,
                "name": "/var/lib/kea/kea-leases4.csv",
                "lfc-interval": 3600
            },
            "valid-lifetime": 3600,
            "option-data": [
                {
                    "name": "domain-name-servers",
                    "data": "172.17.50.1"
                }
            ],
            "subnet4": [
                {
                    "id": 1,
    				"subnet": "192.168.1.0/24",
                    "pools": [
                        {
                            "pool": "192.168.1.100 - 192.168.1.254"
                        }
                    ],
                    "option-data": [
                        {
                            "name": "routers",
                            "data": "192.168.1.1"
                        }
                    ]
                }
            ]
        }
    }
  5. Kea uses JSON style configuration files. These (and the somewhat related YAML format) are becoming a popular style of modern software configuration file. In this case we have specified:

    1. The DHCP server should listen for address requests on the ens224 interface only

    2. The server should store it’s database of active leases in the /var/lib/kea/kea-leases4.csv file and should clean up old information in the file every 3600 seconds (one hour)

    3. Leases should be valid for 3600 seconds (one hour)

    4. Clients should get a DNS server address of 172.17.50.1 from the DHCP server

    5. The DHCP server will hand out addresses for the 192.168.1.0/24 network but addresses will only come from the range (pool) of 192.168.1.100-192.168.1.254 to hold some static addresses at the beginning of the subnet.

    6. Clients in the subnet will use 192.168.1.1 as their default gateway (router).

  6. Use the systemctl restart kea-dhcp4-server command to restart the server with the new configuration and systemctl status kea-dhcp4-server to make sure the DHCP server has restarted properly.

  7. Make sure to add a firewall rule allowing clients on the internal zone to access the dhcp service and to set the new rule to load automatically each time the system is started. Otherwise the firewall will block systems in the internal zone from contacting the DHCP server to get an address! We’ll need to add a new firewall rule like this (plus probably one for the external zone too) every time we add a new service to our server from this point on!

Install Linux Mint as a client behind your Linux Server NAT Router

  1. Because we are going to use a GUI installation of Linux to serve as an example client PC behind our Linux Server we’ll need to begin by installing a copy of Linux on that client PC system. We’ll use a differnt distribution of Linux, Linux Mint, for this system. Although it’s possible to install a GUI on Debian, Linux Mint has been created specifically as an easy to use client version on Linux. It’s still based on Debian so much of what we have learned so far will still apply as we’ll see.

  2. Because we want to use the local console of the virtual machine for the installation and use of Linux Mint we’ll need to log in to the ITC NetLab system and access a reservation for your pod.

    1. If you are not already signed in you’ll need to start by signing in to the ITC NetLab website.

    2. If you have a currently active reservation you will see a green "Enter Lab" button on your list of reservations. Click the green "Enter Lab" button. If not, you will need to make a reservation (you can review the instructions in Lab 1 if needed) and then click the "Enter Lab" button.

  3. Access your virtual machine console

    1. Once you are in your pod you can either click on the image of the "Linux Desktop" on the topology diagram or use the tabs across the top of your screen to access the console of your Linux Desktop VM.

    2. The console shows the display of your VM and allows you to type and interact with your VM just as if you were physically sitting down in front of a server with a monitor, keyboard, and mouse attached. Think of a virtual machine console window as a window to a seaparte computer that you are able to see in your web browser. You can see the "virtual monitor" and interact with a keyboard and mouse but just like a separate physical machine you will not be able to copy and paste text or drag and drop files in and out of this console window.

  4. Install Linux Mint using the graphical wizard

    1. Linux Mint uses a "Live CD" where the system boots and can operate off the CD image which is currently in the CD-ROM drive of the VM. This is designed to allow you to easily test out Linux on a system without actually installing it or making any modifications to the hard drive. However, because the system must run entirely from the CD image (or USB stick) and RAM there are several disadvantages including much slower performance so we want to actually install Linux Mint onto the hard drive of the virtual machine.

    2. If you see an icon on the desktop of the "Linux Desktop" VM with the title "Install Linux Mint" such as shown in the image below you know that your copy of Mint is running in the Live CD mode and is not booted from the hard drive. Double click the "Install Linux Mint" icon on the desktop to start the installation.

      Linux Mint Live CD Mode Desktop
    3. The graphical installer will start as shown in the screenshot below. You will be prompted for the following choices:

      Starting the installer
      1. Select English as the language, and English (US) as the keyboard layout.

      2. Check the box to install multimedia codecs

      3. Choose to "Erase the disk and install Linux Mint" and confirm writing the changes to disk

      4. Choose "Chicago" as the location

      5. Set your name

      6. Set the computer name to 2480 followed by a dash and then your pod ID letter followed by a dash and the word "desktop", like 2480-Z-desktop for LSA Pod Z. Look up at the top of your screen above the line with the "Topology" and "Linux Desktop" tabs and you should see a line with "LSA Pod" followed by a letter, that letter is your pod ID letter.

      7. Create a new user name. The system will automatically use your first name (all lowercase) as the username and then you should set the password to a password you will not forget. It is strongly suggested you write down your username and password somewhere you can refer back to for future labs. This will be the "standard user account" on your Linux Mint system.

        Setting the user name and computer name
        If you forget your password it is possible to recover them because we have local console access to the system but that is not something covered in this course so you are on your own if that happens. The official method to get back into your system as far as this course is concerned is to format and reset your virtual machine and start over with a fresh installation. If you want to avoid this major annoyance it is very important that you do not forget or loose your passwords.
      8. You will see a progress bar as files are copied to your system

        Installer copying files
  5. Complete the installation

    1. When the installation is complete you can select "Restart Now" to "eject" the virtual CD and reboot into the new install. Be sure the "Install Linux Mint" link is gone from the desktop when the system reboots so you know you booted from the hard drive installed copy. You will need to press "ENTER" when prompted to verify the installation media is removed to complete the reboot.

      Installation complete
    2. If the system does not reboot and you instead receive some errors on the screen try rebooting manually by powering off and back on the Linux Desktop VM (instructions for doing this are the same as those found for the Linux Server in Lab 1). If you contonue to have issues please contact your instructor for assistance.

  6. When your Linux Mint system reboots log in with the username and password established during the installation process.

  7. You should see a welcome screen the first time you log in. You can uncheck the "Show this dialog at startup" box in the lower right corner and then close the dialog with the "X" in the upper right corner.

    Linux Mint welcome screen
  8. Adjust your Linux Mint display resolution to be able to see more content on the screen.

    1. Right click on the desktop and select "Display Settings"

    2. Change the resolution to "1280 x 800 (16:10)" and scroll down in the dialog box either using the scroll bar on the right side of the dialog box or the wheel on your mouse so you can see and click the green "Apply" button. Be sure to also click to keep the settings change when prompted.

      Linux Mint Adjusting Screen Resolution
  9. Check the IP address and test network connectivity

    1. Open the terminal application by pressing the menu button in the lower left and typing the word "Terminal" and clicking on the Terminal application. This will give you the same type of command line terminal as you had with Debian Linux

    2. Check the IP address of the system with the ip address show command. Notice how the ens192 interface has a IP from the DHCP pool we created earlier on your server.

      Linux Mint Checking the IP address from the terminal
    3. Try pinging 172.17.50.1. Are you able to ping? If so, NAT is working properly on your network because the 172.17.50.0/23 network is outside of the LAN segment this machine is attached to (192.168.1.0/24).

    4. Try pinging google.com. If you are able to ping, this shows that not only is NAT working, but DNS is resolving as well and traffic can get all the way out to the Internet.

    5. Open a web browser on the system (you can use a graphical browser this time since you have a GUI) and test browsing to a few websites. Firefox is the browser installed by default on Linux Mint.

  10. Use the Linux Mint Software Manager to Install an SSH server on the Mint system

    1. Click the menu button in the lower left of the screen and atart typing "Software Manager" then click to open the Linux Mint Software manager. This is a graphical front-end to the APT package repositories used by Linux Mint.

    2. Use the search box in the upper left corner of the software manager to search for "openssh-server" and click on the "Openssh-server" package when you find it.

      The Openssh-server package in the Linux Mint software manager
    3. Click the green "Install" button and then the "Continue" button to confirm you want to install this software.

    4. You will be prompted to enter your password just like you would with "sudo" from the command line as installing software requires administrative permission on the system.

      Because Mint is based on Debian you could of course use the same apt command line utilities with Linux Mint as we used in Debian to manage software packages too.
    5. Close the software manager application with the "X" in the upper right corner once the installation is complete.

    6. You should be able to use the ssh program on the command line from your Debian Server to access your Mint system like ssh mintusername@192.168.1.x where you are using a valid username/password on the Mint system and the IP address of the Mint system. Type exit and press enter to return to your Debian server. Notice the command prompt changes to show which machine you are currently working on.

      ben@2480-Z:/home/ben$ ssh ben@192.168.1.100
      The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established.
      ED25519 key fingerprint is SHA256:/kqoPivMOdZ6rOeMt9Cpt5ESypL3pzXAnJBRAgJffK0.
      This key is not known by any other names.
      Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
      Warning: Permanently added '192.168.1.100' (ED25519) to the list of known hosts.
      ben@192.168.1.100's password:
      
      ben@2480-Z-desktop:~$ exit
      logout
      Connection to 192.168.1.100 closed.
      ben@2480-Z:/home/ben$
  11. Spend a few more minutes exploring the functionality of the Linux GUI and desktop with Linux Mint.

Configure Port Forwarding on your Linux Server to Access a Client Behind the NAT

  1. Now we are going to enable port forwarding through our Linux Server to the Linux Desktop VM. This will allow you to access the SSH server you setup on the Linux Mint system from the ITC network and VPN or Administrative PC without needing to SSH to the Linux Server first. Because we are already using port 22 on our Linux server’s outside interface to provide SSH access to our Linux server itself we need to use a different port to access the Linux Mint desktop system. Instead of changing the port number in the SSH server software on Linux Mint we can have our firewall do it at the same time the NAT masquerading is occurring.

  2. On your Linux server use the command firewall-cmd --add-forward-port=port=2222:proto=tcp:toport=22:toaddr=192.168.1.100 --zone=external where 192.168.1.100 is the IP address of your Linux Mint system to create a new rule which forwards port 2222 on the IP address of your Linux server through to port 22 on the IP address of your Linux Mint system.

    Normally you would only want to port forward to a computer with a static IP but here we are forwarding to the DHCP address of your Linux Mint system. This means the rule will be a little unstable because our Linux Mint server could get a different IP address from the DHCP server at some point which would break the rule by sending traffic somewhere other than to the Linux Mint system. This could be both a security vulnerability and would obviously not do what we wanted operationally. Therefore, if we wanted this as more than just a simple demonstration of setting up port forwarding, we would want to set up a static IP on any machines we were forwarding ports to.
  3. From a computer on the ITC network, such as one connected to the VPN or the Administrative PC, try to SSH to port 2222 on the outside (172.17.50.xx) IP address of your Linux server system. Use a username and password from your Linux Mint desktop system. Upon connection you should see that you are actually connected to the Linux Mint system via port forwarding.

  4. Once you are satisfied your firewall is running correctly use the correct firewall-cmd command to save the current runtime rules as permanent rules.

  5. When you are done testing this section of the lab please power off your new Linux Mint VM using the shutdown command in the Mint Menu as the desktop systems require far more RAM and CPU power to run than the Linux Server VMs.

Secure SSH Using SSH Keys

  1. If you have port 22 exposed to the Internet (remember, our lab servers are not directly exposed to public IP addresses and need to be accessed via VPN or Netlab) and watch your system logs you will see a steady stream of attackers trying to brute force their way into your Linux server by using automated tools to guess usernames and passwords. While using strong passwords can help there are some better tools at our disposal. One of these tools is the SSH Key system where the client uses a secret key file to authenticate to the SSH server instead of (or in addition to) a password. So long as the secret key file is not available to attackers they will not be able to log in to the system. For this reason some administrators enforce a rule that passwords cannot be used alone for remote SSH access and all remote SSH authentication must be by SSH key.

  2. SSH Keys are created by the client software and not by the server so the exact method used to create them depends on the client software you are using to connect. If you are using PuTTY as your SSH client on either your own system or on the Administrative PC follow the instructions below to implement SSH keys. If you are using a command line SSH client (for example you are connecting from a Mac or a Linux computer of your own) skip this sub-section and go to #3 where you’ll find instructions for that.

    1. Start the PuTTYgen program by finding it in your Windows Start Menu or by tapping the Windows key and typing "puttygen".

      PuTTY Key Generator
    2. Click the radio button in the Parameters section to select "ECDSA" as the type of key to generate then click the "Generate" button.

    3. You will need to follow the instructions to move your mouse back and forth randomly in the blank area to generate some randomness.

      PuTTY Key Generator - Generating randomness
    4. When the process is complete you will see a public key on the screen. This will need to be pasted into a configuration file on any servers you want to connect to. Highlight everything in the "Public key for pasting into OpenSSH authorized_keys file" box and copy it to your clipboard now. Be sure to leavr the PuTTY Key Generator software open and running on your system, we will need to come back to it in a minute and if you generate a new key it will be different.

      PuTTY Key Generator - Completed generating key
    5. Connect to your Linux server system by SSH using your usual username and password and go to your user’s home directory and then open the file ~/.ssh/authorized_keys in a text editor. The .ssh directory and/or authorized_keys file may exist or you may need to create one or both (be sure to note the period at the beginning of the .ssh directory indicating it is a hidden directory)

    6. Paste the contents of your public key into the authorized_keys file you just opened or created. Note that although PuTTY Key Generator may have shown the key as several lines it is actually just one very long line. Each line in the authorized_keys file is for a different key so you can create multiple keys which can login as your user and put them all into the same authorized_keys file on separate lines.

    7. Save and close the authorized_keys file, then close the PuTTY session to your Linux server.

    8. Return to the PuTTY Key Generator software on your client computer. You can enter in a "key passphrase" and the same again in the "confirm passphrase" box if you want to be required to enter in a password each time the secret key file is used to connect. Note this can be entirely different than your password on the Linux server. It is best practice to use a key passphrase just in case someone is able to obtain your secret key file.

    9. Click the "Save private key button". If you did not set a key passphrase you’ll get an extra warning encouraging you to set one. Save the PPK file somewhere on your administrative client system.

      If you want to see your public key again (possibly to install on other Linux servers you want to connect to using the same private key) you can do so. However, you can’t just use the "Save public key" button because the format PuTTY Key Generator uses when it saves the public key is not the same as what you enter into the authorized_keys files on Linux servers. To get the text to put into the authorized_keys files you will need to run the PuTTY Key Generator again and click the "Load" button to "Load an existing private key file". You’ll need to provide your private key file to PuTTY Key Generator which will then display the public key in the correct format to be put into an authorized_keys file on a Linux server.
    10. Close the PuTTY Key Generator software and open the regular PuTTY client software.

    11. Put the IP address of your Linux server into the "Host Name" box as normal but do not click the "Open" button yet.

    12. Under the "Connection" category on the left side of the screen press the "+" next to "SSH" and then again next to "Auth" and then click on the "Credentials" page.

    13. Click the "Browse" button next to "Private key file for authentication" and find the PPK file you saved previously from PuTTY Key Generator. It should look something like this:

      PuTTY - Setting a private key file to connect
    14. Now click the "Open" button and enter your username when prompted. If you did not set a key passphrase you should immediately be logged in as shown below, note they "Authenticating with public key" line towards the top of the screen:

      PuTTY - Connecting with an SSH Key and no passphrase
    15. If you did set a key passphrase you will be prompted to enter it before the connection is made as shown below. Note that this is your key passphrase you created in PuTTY Key Generator and which may be entirely unrelated to your Linux server account password, we are not using passwords to authenticate with this method.

      PuTTY - Connecting with an SSH Key and a passphrase
  3. SSH Keys are created by the client software and not by the server so the exact method used to create them depends on the client software you are using to connect. If you are using a command line OpenSSH client (for example you are connecting from a Mac or a Linux computer of your own) follow the instructions below to implement SSH keys. If you are using PuTTY as your SSH client on either your own system or on the Administrative PC you should have followed the instructions in the above sub-section #2 and skip this sub-section, pick up again at #4.

    1. At a terminal on your client system run the ssh-keygen command.

    2. You will be prompted to a location to save the key file. You can probably just accept the default location by pressing enter. See the example output below.

    3. You can optionally enter in a key "passphrase" if you want to be required to enter in a password each time the secret key file is used to connect or press enter to skip having a passphrase on this key. You will need to enter the same again to confirm. Note this passphrase can be entirely different than your password on the Linux server. It is best practice to use a key passphrase just in case someone is able to obtain your secret key file.

      ben@2480-Z:~$ ssh-keygen
      Generating public/private rsa key pair.
      Enter file in which to save the key (/home/ben/.ssh/id_rsa):
      Enter passphrase (empty for no passphrase):
      Enter same passphrase again:
      Your identification has been saved in /home/ben/.ssh/id_rsa
      Your public key has been saved in /home/ben/.ssh/id_rsa.pub
      The key fingerprint is:
      SHA256:eo/4uzW0+aRzZvNemgK6Hmx4gxE5/C6zww0g5/bduSM ben@2480-Z
      The key's randomart image is:
      +---[RSA 3072]----+
      |                 |
      |     . .         |
      |      =          |
      |  . o  +         |
      |   + .. S .      |
      |    o .B ..o     |
      |   . o*+Oo=o.   .|
      |      +OE*==*  + |
      |      o+B=+B.==  |
      +----[SHA256]-----+
      ben@2480-Z:~$
    4. Note the location for the private (/home/ben/.ssh/id_rsa in the above example) and public (/home/ben/.ssh/id_rsa.pub in the above example) key files which are given in the output when the keys are created.

    5. Use the cat command to view the public key file like:

      ben@2480-Z:~$ cat /home/ben/.ssh/id_rsa.pub
      ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCu2M+cyYOd/4jmxrDmETLjYIT/XiRfvJeRFgpUn42wrJZcH82eTztLyY+HmdbBUil20OuwtUrIdGgh4+O4ROS3jyU+WRztYm01icgspzJMuowGFh7iNazwvmdO2ICyCI+5Y0RXFrgQI/TD1aD0730f8gQZOsOH4rqgyMY7leIqYGGcQ/nyn4k3g4/85bQZZwL5+v/rjSrqp8oSNaU8gSgZSglU8lJDRWXaWlrZjGHlzUu4hikahFp4IQGUPoRqPQgBDdVpsoHjrZdVm5aFxg7PdvjcomKeUhtf4ZlM6lLjkmqzZV76kSrPwoDu/6s1xugpeUJv0TBqhSxB7DXgANVbnau2qSKgh7gXIDOGbmkvSEAMywgwfLncvK1r4EzoV+m7ph0U2e+nv6kph+PXcaqGL6qOBFvipe5U+CrrY5DA11nNQ4I/oCUYL6QPyJkXoXHMqSLpQkBTV1IoGrXIGTq9VpO/1+yix2Y4RjuErPjwdtxNfg1nax3U/6sB3D+rSD8= ben@2480-Z
      ben@2480-Z:~$
    6. You want to copy the actual public key to your clipboard. In the above example the actual public key is just:

      ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCu2M+cyYOd/4jmxrDmETLjYIT/XiRfvJeRFgpUn42wrJZcH82eTztLyY+HmdbBUil20OuwtUrIdGgh4+O4ROS3jyU+WRztYm01icgspzJMuowGFh7iNazwvmdO2ICyCI+5Y0RXFrgQI/TD1aD0730f8gQZOsOH4rqgyMY7leIqYGGcQ/nyn4k3g4/85bQZZwL5+v/rjSrqp8oSNaU8gSgZSglU8lJDRWXaWlrZjGHlzUu4hikahFp4IQGUPoRqPQgBDdVpsoHjrZdVm5aFxg7PdvjcomKeUhtf4ZlM6lLjkmqzZV76kSrPwoDu/6s1xugpeUJv0TBqhSxB7DXgANVbnau2qSKgh7gXIDOGbmkvSEAMywgwfLncvK1r4EzoV+m7ph0U2e+nv6kph+PXcaqGL6qOBFvipe5U+CrrY5DA11nNQ4I/oCUYL6QPyJkXoXHMqSLpQkBTV1IoGrXIGTq9VpO/1+yix2Y4RjuErPjwdtxNfg1nax3U/6sB3D+rSD8= ben@2480-Z
    7. Connect to your Linux server system by SSH using your usual username and password and go to your user’s home directory and then open the file ~/.ssh/authorized_keys in a text editor. The .ssh directory and/or authorized_keys file may exist or you may need to create one or both (be sure to note the period at the beginning of the .ssh directory indicating it is a hidden directory)

    8. Paste the contents of your public key into the authorized_keys file you just opened or created. Note that although cat may have shown the key as several lines it is actually just one very long line. Each line in the authorized_keys file is for a different key so you can create multiple keys which can login as your user and put them all into the same authorized_keys file on separate lines.

    9. Save and close the authorized_keys file, then close the SSH session to your Linux server.

    10. From your administrative client use the usual ssh username@remote_host command to connect to your Linux server again where username and remote_host are replaced by your Linux server username and IP address respectively.

    11. If you did not set a key passphrase you should immediately be logged in, if you did set a key passphrase you will be prompted to enter it before the connection is made. Note that this is your key passphrase you created on your client when you created the key and which may be entirely unrelated to your Linux server account password, we are not using passwords to authenticate with this method.

  4. Note that your Linux server is currently configured to allow you to log in using either a username and password or SSH key based authentication. If you wanted to require users use SSH key based authentication and not allow passwords (which prevents the types of brute force password attacks mentioned at the beginning of this section) you would need to edit the OpenSSH options on your Linux server in the /etc/ssh/sshd_config file to activate the PasswordAuthentication no line and then restart the ssh server. Do not do this on your Linux server for this class as we will be doing some more work with password based SSH authentication.

Secure SSH Using 2FA

  1. An alternative way to secure SSH from brute force password attacks is to use multi-factor authentication. In this section we’ll setup a time-based one time password (TOTP) second fadctor of authentication (2FA) which will require a changing numeric code be entered along with your password when logging in. You will need to install a TOTP app on your phone or other device to show you the correct code to enter. The lab is written using the "Google Authenticator" phone app but there are many other TOTP apps which are compatible as well including options you can install on your Windows PC or Mac if you don’t have or want to install a phone app. However, you’ll be on your own as to how to add the required key into those apps if you choose to use something other than Google Authenticator.

  2. Use apt to install the libpam-google-authenticator package on your Linux server system.

  3. Run the google-authenticator command to create a new secret key in your home directory.

    1. When you are asked "Do you want authentication tokens to be time-based?"" Answer "y".

    2. The command will create a secret key used to setup your TOTP application on your phone. This will include a QR code to scan with your phone app as well as a text key which could be entered manually. You may need to expand the size of your SSH window to see these. See the example below.

      Creating a TOTP key with libpam-google-authenticator
  4. Install the "Google Authenticator" app on your phone (or whatever other TOTP app you would prefer on your phone or PC/Mac) and open it.

  5. Add a code or enter the secret key in your TOTP authentication app. If you’re using Google Authenticator the easiest way to do this is tell it you want to scan a QR code and then point the camera on your phone at the QR code in the SSH window from your Linux server.

  6. When things are setup in your TOTP app you should see a changing six digit code on your TOTP app. You will need to enter in the code on your Linux server in the SSH window where it says "Enter code from app". This will confirm that your phone app and server are both in sync.

  7. Assuming the code entered was successful you should get a message "Code confirmed" as well as some emergency scratch codes you could save somewhere safe in case of an emergency which will each work one time to allow access.

  8. You will be promted to answer four more questions. Read through each question and answer "y" to the first three and "n" to the last one (we’ll deal with rate limiting separately in the next part of the lab).

    Do you want me to update your "/home/ben/.google_authenticator" file? (y/n) y
    
    Do you want to disallow multiple uses of the same authentication
    token? This restricts you to one login about every 30s, but it increases
    your chances to notice or even prevent man-in-the-middle attacks (y/n) y
    
    By default, a new token is generated every 30 seconds by the mobile app.
    In order to compensate for possible time-skew between the client and the server,
    we allow an extra token before and after the current time. This allows for a
    time skew of up to 30 seconds between authentication server and client. If you
    experience problems with poor time synchronization, you can increase the window
    from its default size of 3 permitted codes (one previous code, the current
    code, the next code) to 17 permitted codes (the 8 previous codes, the current
    code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
    between client and server.
    Do you want to do so? (y/n) y
    
    If the computer that you are logging into isn't hardened against brute-force
    login attempts, you can enable rate-limiting for the authentication module.
    By default, this limits attackers to no more than 3 login attempts every 30s.
    Do you want to enable rate-limiting? (y/n) n
  9. Use administrative permissions to open the the /etc/ssh/sshd_config file on your system with a text editor.

  10. Find the two settings below in the file and ensure both are set to yes then save the file and exist the editor.

    UsePAM yes
    ChallengeResponseAuthentication yes
    KbdInteractiveAuthentication yes
  11. Use administrative permissions to open the the /etc/pam.d/sshd file on your system with a text editor.

  12. Just below the @include common-auth line towards the top of the file add these two lines

    # two-factor authentication via Google Authenticator
    auth   required   pam_google_authenticator.so
  13. Use the systemctl restart ssh command to restart the SSH server.

  14. Try making a new SSH connection to the server. You should be prompted for a password and then a verification code when connecting. Get the current verification code from your TOTP app.

    Logging in via SSH with a TOTP verification code
  15. Make sure you cannot log in with an incorrect verification code or without a verification code.

    The way we currently have things setup you do not need a verification code if you are connecting with SSH keys. If you are using an SSH client other than PuTTY to connect it may automatically provide the SSH key we made above when connecting and you would not be prompted for a password or verification code. It is possible to require a verification code when connecting with an SSH key but it takes away some advantages of using SSH keys and is arguably not much more secure since an SSH key is another "something you have" factor just like the authentication codes.

    If your client is automatically providing an SSH key and so you are unable to test verification codes the easiest thing to do is either to delete your id_rsa file private key from your client or remove the public key from the authorized_keys file on your Linux server which will force password based authentication with the verification codes.

  16. You can leave verification codes enabled on your Linux server for the rest of the course if you would like but you may want to turn them back off. To do this just open the /etc/pam.d/sshd file on your system and put a # at the beginning of the auth required pam_google_authenticator.so line like:

    # two-factor authentication via Google Authenticator
    #auth   required   pam_google_authenticator.so
  17. Save and close the /etc/pam.d/sshd file and the verification codes should be turned off.

Enable Fail2Ban for SSH Log Monitoring

  1. Yet another way to resist brute force password attacks against your Linux server is to monitor failed login attempts and block IP addresses in the system firewall for some amount of time if they have attempted to gain access multiple times and failed. This type of monitoring and blocking can be automated with software, one of the most popular software packages to do this with on Linux is called Fail2Ban because it bans the ip addresses (usually for some amount of time) if they fail the login process too many times. While the most common us is probably to monitor SSH remote login attempts the Fail2Ban software can be adjusted to monitor many other programs which log failed login attempts as well. It is not a bad idea to implement monitoring and blocking software like this even if your system is protected by other measures such as SSH keysm, 2FA, or required VPN access.

  2. Use the apt utility to install the fail2ban package on your system.

  3. Use a text editor to open the /etc/fail2ban/jail.conf file and read through the commented notes in the file. This file contains many of the configuration settings for the fail2ban application. Note that the file instructs you not to modify /etc/fail2ban/jail.conf but instead to create a new /etc/fail2ban/jail.local file with any modifications. Doing it this way will allow apt to update the defaults in /etc/fail2ban/jail.conf as new versions are released while still allowing you to customize settings as needed. After you have reviewed the commented notes in the /etc/fail2ban/jail.conf file close the file.

  4. Use a text editor (with administrative permissions) to create and edit a new file /etc/fail2ban/jail.local where we’ll store our customizations. Copy and paste the customizations below into the file and save it. Note the comment lines below which also explain what each configuration line in the file is doing, the comments do not need to be copied but it should be OK to copy them too if you want.

    # Change some default settings which affect all applications
    # being monitored by the fail2ban application
    [DEFAULT]
    
    # Our Debian system is using the newer nftables for it's
    # underlying firewall instead of the older iptables so we
    # want to have fail2ban use native nftables commands for
    # banning IP addresses which misbehave. There are two
    # different banactions which need to know what backend
    # to use banaction and banaction_allports so we'll set
    # them both to use nftables.
    banaction = nftables-multiport
    banaction_allports = nftables-allports
    
    # Change settings specifically around monitoring of
    # SSH authentication attempts.
    [sshd]
    
    # Our version of Debian has switched to using systemd for
    # SSH logging so we need to let fail2ban know to use the
    # systemd backend or it won't be able to find an SSH log to
    # monitor for failed authentication attempts.
    backend=systemd
    
    # Tell fail2ban it should monitor SSH attempts
    enabled = true
    
    # Tell fail2ban that if someone tries to break in to SSH
    # they should be blocked from connecting to the server on
    # ANY port, be default they would still be able to access
    # ports other than the SSH port (22) such as our website.
    # This will block them from getting to anything on the system.
    port = 0:65535
    
    # Tell fail2ban to block attackers for 1 minute. Normally
    # you would probably want this to be longer, like 10 or 15
    # minutes. But because we're pretty secure behind our VPN
    # and we want to be able to do some testing we'll set it to
    # cancel the ban after 1 minute.
    bantime = 1m
    
    # Tell fail2ban to block people who give a wrong login/password
    # for SSH 3 times within 2 minutes.
    findtime = 2m
    maxretry = 3
  5. Now that we have changed the configuration we should restart fail2ban with the systemctl restart fail2ban command. Always check to make sure the service has restarted and is running with the systemctl status fail2ban command.

  6. Before testing out fail2ban for real you may want to simulate a ban on an IP address that is not being used just to see the firewall rules are being properly entered.

    1. Use the sudo fail2ban-client set sshd banip 192.168.1.7 command to simulate a user from the 192.168.1.7 IP address putting a wrong password in 3 times within 2 minutes and getting banned.

    2. Use the sudo fail2ban-client status to see a list of software which is being monitored by fail2ban. Each monitored software is called a "jail" by fail2ban.

    3. Check the list of IPs which have been blocked for a particular jail (ushc as sshd) with the command sudo fail2ban-client status sshd. 192.168.1.7 should be on that list (as long as it has been less than 1 minute since you banned it, remember our ban time is only 1 minute). If you check again after one minute the IP should be removed from the list.

      ben@2480-Z:~$ sudo fail2ban-client set sshd banip 192.168.1.7
      0
      ben@2480-Z:~$ sudo fail2ban-client status
      Status
      |- Number of jail:      1
      `- Jail list:   sshd
      ben@2480-Z:~$ sudo fail2ban-client status sshd
      Status for the jail: sshd
      |- Filter
      |  |- Currently failed: 0
      |  |- Total failed:     0
      |  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
      `- Actions
         |- Currently banned: 1
         |- Total banned:     1
         `- Banned IP list:   192.168.1.7
      ben@2480-Z:~$ sudo fail2ban-client status sshd
      Status for the jail: sshd
      |- Filter
      |  |- Currently failed: 0
      |  |- Total failed:     0
      |  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
      `- Actions
         |- Currently banned: 0
         |- Total banned:     1
         `- Banned IP list:
      ben@2480-Z:~$
    4. Ban the IP address 192.168.1.8 and then quickly run the sudo nft list table inet f2b-table command to view the actual firewall rules what fail2ban has implemented. Run the same command again a minute later to see that fail2ban has removed the ban.

      ben@2480-Z:~$ sudo fail2ban-client set sshd banip 192.168.1.8
      1
      ben@2480-Z:~$ sudo nft list table inet f2b-table
      table inet f2b-table {
              set addr-set-sshd {
                      type ipv4_addr
                      elements = { 192.168.1.8 }
              }
      
              chain f2b-chain {
                      type filter hook input priority filter - 1; policy accept;
                      tcp dport 0-65535 ip saddr @addr-set-sshd reject with icmp port-unreachable
              }
      }
      ben@2480-Z:~$ sudo nft list table inet f2b-table
      table inet f2b-table {
              set addr-set-sshd {
                      type ipv4_addr
              }
      
              chain f2b-chain {
                      type filter hook input priority filter - 1; policy accept;
                      tcp dport 0-65535 ip saddr @addr-set-sshd reject with icmp port-unreachable
              }
      }
      ben@2480-Z:~$
    5. Without going into too much details on nftables rules you can see in the above output that the f2b-chain is set to block tcp ports 0-65535 for all IP addresses in the IP address set addr-set-sshd by sending an icmp port-unreachable message. Fail2Ban adds the blocked IP address to the IP address set addr-set-sshd when the IP is banned and then removes it from the set when it is unbanned 1 minute later.

  7. Now let’s do an actual intrusion test to see fail2ban in action.

    1. Use Netlab to connect to your Linux Mint Desktop system again and open a terminal on Linux Mint.

    2. Use the ssh someuser@192.168.1.1 command on your Linux Mint system to try and connect to your Linux server. Make up a fake password to try and connect. Do this three times in less than two minutes.

    3. Now try to connect with your real username (in my case ssh ben@192.168.1.1) and you should see you are not even prompted for a password because you have been banned!

    4. Go to your Linux Server SSH connection and verify that the IP address of your Linux Mint desktop is banned using the fail2ban-client and/or the nft commands we used before. Remember you will be unbanned in one minute so if it takes you longer than one minute to check you’ll need to put in some more fake passwords from Mint to get banned again.

  8. Think about what you could do to access your Linux Server in case you accidentally got banned yourself? How could you get back in before the ban expired? If you got back in is there a command for fail2ban you can find which will let you remove the ban on a certain IP address?

Wrapping Up

  1. Properly shutdown your Linux Mint Desktop system either using the menu in the lower left of the GUI or using an SSH or terminal session to the desktop system and the shutdown -h now command with administrator permissions.

  2. Close the SSH session

    1. Type exit to close the connection while leaving your Linux server VM running.

  3. If you are using the Administrative PC in Netlab instead of your own computer as the administrative computer you should also shut down that system in the usual way each time you are done with the Netlab system and then end your Netlab Reservation. You should do these steps each time you finish using the adminsitrative PC in future labs as well.

  4. End your Netlab Reservation

    1. If you still have time left in your reservation in Netlab it’s polite to end the reservation so other users can work on the system, only a limited number of reservations can be made at one time. You can do this by logging into Netlab, opening your lab, and clicking the "Reservation" menu at the top of the screen and choose to "End Reservation Now" followed by confirming that you want to end the reservation.

You can keep your Linux Server running, you do not need to shut it down.

Document Build Time: 2024-10-30 23:55:41 UTC
Page Version: 2024.01
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License