Top 2020 Hacker Prevention Tips for VM’s

The internet is a giant engine of collaboration and communication that anyone with access can contribute to.  While this has lead to many awesome developments such as organized knowledge at the tips of our fingers and better connection with other users, not all developments born from the internet are positive.  Bad actors can cause issues directly via hacking, or indirectly via malware and other malicious software.  

Having a strategy to prevent as much of this potential harm as possible is highly recommended.  This guide serves as a starting point for some basic security measures you can take to start safeguarding your environment.  It is important to stress this isn’t a comprehensive guide nor will it guarantee that nothing malicious occurs.  Security in a shared computing environment is much like security for your home, it is extremely difficult to make a home break-in proof, but it is easy to make a home much harder to steal from.

With that in mind please treat these suggestions as a starting point.  There is much more that can be done to improve security beyond the scope of this guide.  You will need to determine if additional measures are required for any laws or regulations regarding your business, as well as any additional measures desired for peace of mind.  Any links from here forth will bring you to a guide to help with a described suggestion.

Choose a strong password, or better yet, don’t use password authentication

Passwords used should be strongly crafted.  Utilize a variety of character types and a decent length, at least 8 characters.  The more variety to a password the longer it takes for a hacker to be able to guess or brute force it.

However, an even more secure option is to simply forego using a password for remote authentication.  By setting up SSH keys for your Linux devices, you can not only authenticate to your server in a more secure manner, but also forego having to utilize a password.

Change your access port

By default, Linux utilizes port 22 for SSH and Windows utilizes port 3389 for RDP.  This is common knowledge that hackers regularly use to attempt to exploit.  While most attempts will be thwarted by a strong method of authentication, it is recommended to change SSH or RDP to run on a different port.  This simple change can cause a lot of automated malicious agents to simply pass over the server altogether, or cause a bad actor from caring enough to continue, reducing the chances of something or someone breaking in.  Security through obscurity is very effective on a computing environment.

Lock down your firewall

Firewalls are your first line of defense against many malicious attacks.  The mentality taken when setting up your firewall should be to only allow traffic through the firewall that the server requires for its functions.  As an example, for a web server, you would likely only leave ports 80 and 443 open, and deny traffic on all other ports with the possible exception of an SSH or RPD port.  The server should only accept traffic it needs to perform its desired functions.

Utilize fail2ban or similar

One of the most common methods that malicious actors use to attempt to access a server is brute force. This simply means throwing hundreds or thousands of possibilities at the server in order to attempt to guess a password.  Utilize fail2ban for Linux systems or wail2ban for Windows systems to thwart such attempts.  These services watch attempts to authenticate to your server and block repeated attempts at a firewall level.  This not only eliminates these actors from being able to continue to attempt to access the server, but also improves performance by not allowing these requests to even be processed by the server.  They are simply discarded.

Keep items up to date

The unfortunate nature of software development is that it is inevitable that mistakes happen.  These are often harmless, or at least harmless from a security standpoint and manifest as bugs. However, some bugs affect the security of a server and thus become a vulnerability. Developers will often patch such issues as soon as possible so it is advantageous to ensure your OS and installed programs and packages are up-to-date.  This will save you from any issues the developer has already solved.

Set up users and permissions

Set up custom users for administration and access to your environment and devices.  Lock those users down so they can only access what is necessary for that user’s function.  You can think of this like compartmentalizing.  If a particular user gets compromised only specific items are at risk instead of the entire server.

Disable Root access

Set up all access to the server via custom users.  If root access is needed grant sudo permission to a specific user.  Root login access should be disabled entirely.  This prevents malicious actors from gaining access to the root user and significantly reduces the risk of a bad actor gaining higher level permissions.  

Disable unnecessary services

This links back to the firewall recommendations.  For the same reason, namely minimizing the profile of available attacks, you should disable any unnecessary services on your servers.  This means that there are less items active on the server and thus less potential weak points for a malicious user to exploit.  Security is much like a chain, it is only as strong as the weakest link.  Minimizing the number of links means less effort reinforcing the remaining required links.

Have a plan for the worst

As mentioned at the beginning of the article, these are all preventative measures.  One should also have a plan for if such preparations fail.  Backups, images, and redundancy are your best tools here, but these all need to be prepared ahead of time to be effective.  Read on here in our primer for disaster recovery for more ideas and guides on setting up for the worst cases.

How to Encrypt a Block Storage volume with LUKS on Ubuntu 18.04

Encrypting your Block Storage volume adds an extra layer of security to your most sensitive data and can help protect it even in the event of server or account level compromise. We’ll be using the standard LUKS (Linux Unified Key Setup) encryption specification in this article.

Install cryptsetup

Cryptsetup is the tool we will use to setup LUKS encryption. The package should already be installed, but if it’s missing, this command will install it. 

$ sudo apt install cryptsetup

Prepare your volume

This will destroy any data on the volume, so make sure you are using a fesh one or have backups you can restore from. 

Find the volume name

$ lsblk
NAME     MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda     202:0    0   20G  0 disk
├─xvda1  202:1    0 19.9G  0 part /
├─xvda14 202:14   0    4M  0 part
└─xvda15 202:15   0  106M  0 part
xvdb     202:16   0   75G  0 disk 

My Block Storage volume was assigned the name xvdb, which I’ll be using throughout this article. Make sure you use the correct name to avoid formatting the wrong volume.

Create a new GPT partition table

We are using gdisk to format the volume. This can seem intimidating, but it’s actually a very easy utility to use. Just make sure to use the help command “?” if you aren’t sure what to do next. 

$ sudo gdisk /dev/xvdb
GPT fdisk (gdisk) version 1.0.3

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): o
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): y

Create a new partition

Still in gdisk, we are creating a single partition that encompasses the entire volume.

Command (? for help): n
Partition number (1-128, default 1):
First sector (34-157286366, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-157286366, default = 157286366) or {+-}size{KMGTP}:
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help): p
Disk /dev/xvdb: 157286400 sectors, 75.0 GiB
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): DBE6F693-6761-4356-BD24-0F0ACE48768E
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 157286366
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048       157286366   75.0 GiB    8300  Linux filesystem

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/xvdb.
The operation has completed successfully.

Verify the partition was created

Use the lsblk command to confirm that your new partition was created. Here we can see that partition xvdb1 was successfully created on volume xvdb, that the partition is the full size of the disk, and that it isn’t mounted yet:

$ lsblk
NAME     MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda     202:0    0   20G  0 disk
├─xvda1  202:1    0 19.9G  0 part /
├─xvda14 202:14   0    4M  0 part
└─xvda15 202:15   0  106M  0 part
xvdb     202:16   0   75G  0 disk
└─xvdb1  202:17   0   75G  0 part 

Encrypt the partition

Perform the disk encryption using luksFormat, and enter a passphrase when prompted. Remember that recovering a lost passphrase on the device is virtually impossible and losing it will be effectively the same as disk data loss in virtually every scenario, so store this information carefully.

$ sudo cryptsetup luksFormat /dev/xvdb1

WARNING!
========
This will overwrite data on /dev/xvdb1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase for /dev/xvdb1:
Verify passphrase: 

Open the encrypted device

Now that the disk is encrypted, use luksOpen to access the volume using the passphrase:

$ sudo cryptsetup luksOpen /dev/xvdb1 secure
Enter passphrase for /dev/xvdb1: 

List devices

The device should now be accessable and listed as available.

$ lsblk
NAME       MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
xvda       202:0    0   20G  0 disk
├─xvda1    202:1    0 19.9G  0 part  /
├─xvda14   202:14   0    4M  0 part
└─xvda15   202:15   0  106M  0 part
xvdb       202:16   0   75G  0 disk
└─xvdb1    202:17   0   75G  0 part
  └─secure 253:0    0   75G  0 crypt

Create and mount a filesystem

Now that partitioning and creating the encrypted volume is completed, you will need to format the filesystem so that Linux can make use of the space, and then mount the finished volume to be recognized as part of the server’s file system.

Create an ext4 filesystem

$ sudo mkfs.ext4 /dev/mapper/secure
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 19660027 4k blocks and 4915200 inodes
Filesystem UUID: 471ca710-4206-4834-98f7-d7795ee89981
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000, 7962624, 11239424

Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done   

Create the mount point

sudo mkdir /data

Mount the newly created filesystem

$ sudo mount /dev/mapper/secure /data

Verify the device now has a mount point

$ lsblk
NAME       MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
xvda       202:0    0   20G  0 disk
├─xvda1    202:1    0 19.9G  0 part  /
├─xvda14   202:14   0    4M  0 part
└─xvda15   202:15   0  106M  0 part
xvdb       202:16   0   75G  0 disk
└─xvdb1    202:17   0   75G  0 part
  └─secure 253:0    0   75G  0 crypt /data

All set! You can now read and write the device just as you would a normal filesystem.

Close the device

Once you’re done, you can unmount and close the device in order to make use of the encryption protecting it. You’ll need to reopen it with your password before it can be used again.

Unmount the volume

Unmount the volume from the server with the following command:

$ sudo umount /dev/mapper/secure

Close the encrypted partition

Finally, use the luksClose command to effectively “re-lock” the encrypted drive, preventing access until such time as it is opened again using the passphrase:

$ sudo cryptsetup luksClose secure

How to Encrypt a Block Storage volume with LUKS on CentOS 7

Encrypting your Block Storage volume adds an extra layer of security to your most sensative data and can help protect it even in the event of server or account level compromise. We’ll be using the standard LUKS (Linux Unified Key Setup) encryption specification in this article.

Install cryptsetup

Cryptsetup is the tool we will use to setup LUKS encryption. The package should already be installed, but if it’s missing, this command will install it:

$ sudo yum install cryptsetup

Prepare your volume

This will destroy any data on the volume, so make sure you are using a fresh one or have backups you can restore from. 

Find the volume name

$ lsblk
NAME     MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda     202:0    0   20G  0 disk
├─xvda1  202:1    0 19.9G  0 part /
├─xvda14 202:14   0    4M  0 part
└─xvda15 202:15   0  106M  0 part
xvdb     202:16   0   75G  0 disk 

My Block Storage volume was assigned the name xvdb, which I’ll be using throughout this article. Make sure you use the correct name to avoid formatting the wrong volume.

Create a new GPT partition table

We are using gdisk to format the volume. This can seem intimidating, but it’s actually a very easy utility to use. Just make sure to use the help command “?” if you aren’t sure what to do next. 

$ sudo gdisk /dev/xvdb
GPT fdisk (gdisk) version 1.0.3

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): o
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): y

Create a new partition

Still in gdisk, we are creating a single partition that encompasses the entire volume.

Command (? for help): n
Partition number (1-128, default 1):
First sector (34-157286366, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-157286366, default = 157286366) or {+-}size{KMGTP}:
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help): p
Disk /dev/xvdb: 157286400 sectors, 75.0 GiB
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): DBE6F693-6761-4356-BD24-0F0ACE48768E
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 157286366
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048       157286366   75.0 GiB    8300  Linux filesystem

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/xvdb.
The operation has completed successfully.

Verify the partition was created

Use the lsblk command to confirm that your new partition was created. Here we can see that partition xvdb1 was successfully created on volume xvdb, that the partition is the full size of the disk, and that it isn’t mounted yet:

$ lsblk
NAME     MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda     202:0    0   20G  0 disk
├─xvda1  202:1    0 19.9G  0 part /
├─xvda14 202:14   0    4M  0 part
└─xvda15 202:15   0  106M  0 part
xvdb     202:16   0   75G  0 disk
└─xvdb1  202:17   0   75G  0 part 

Encrypt the partition

Perform the disk encryption using luksFormat, and enter a passphrase when prompted. Remember that recovering a lost passphrase on the device is virtually impossible and losing it will be effectively the same as disk data loss in virtually every scenario, so store this information carefully.

$ sudo cryptsetup luksFormat /dev/xvdb1

WARNING!
========
This will overwrite data on /dev/xvdb1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase for /dev/xvdb1:
Verify passphrase: 

Open the encrypted device

Now that the disk is encrypted, use luksOpen to access the volume using the passphrase:

$ sudo cryptsetup luksOpen /dev/xvdb1 secure
Enter passphrase for /dev/xvdb1: 

List devices

The device should now be accessible and listed as available.

$ lsblk
NAME       MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
xvda       202:0    0   20G  0 disk
├─xvda1    202:1    0 19.9G  0 part  /
├─xvda14   202:14   0    4M  0 part
└─xvda15   202:15   0  106M  0 part
xvdb       202:16   0   75G  0 disk
└─xvdb1    202:17   0   75G  0 part
  └─secure 253:0    0   75G  0 crypt

Create and mount a filesystem

Now that partitioning and creating the encrypted volume is completed, you will need to format the filesystem so that Linux can make use of the space, and then mount the finished volume to be recognized as part of the server’s file system.

Create an ext4 filesystem

$ sudo mkfs.ext4 /dev/mapper/secure
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 19660027 4k blocks and 4915200 inodes
Filesystem UUID: 471ca710-4206-4834-98f7-d7795ee89981
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000, 7962624, 11239424

Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done   

Create the mount point

sudo mkdir /data

Mount the newly created filesystem

$ sudo mount /dev/mapper/secure /data

Verify the device now has a mount point

$ lsblk
NAME       MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
xvda       202:0    0   20G  0 disk
├─xvda1    202:1    0 19.9G  0 part  /
├─xvda14   202:14   0    4M  0 part
└─xvda15   202:15   0  106M  0 part
xvdb       202:16   0   75G  0 disk
└─xvdb1    202:17   0   75G  0 part
  └─secure 253:0    0   75G  0 crypt /data

All set! You can now read and write the device just as you would a normal filesystem.

Close the device

Once you’re done, you can unmount and close the device in order to make use of the encryption protecting it. You’ll need to reopen it with your password before it can be used again.

Unmount the volume

Unmount the volume from the server with the following command:

$ sudo umount /dev/mapper/secure

Close the encrypted partition

Finally, use the luksClose command to effectively “re-lock” the encrypted drive, preventing access until such time as it is opened again using the passphrase:

$ sudo cryptsetup luksClose secure

Securing SSH on Ubuntu 18.04

Securing SSH is highly recommended as it is a common target for hackers on the internet. I’ll show you how to secure SSH by changing the port, disabling password authentication, and disabling root login over SSH.

 

Changing the SSH port

Changing from the default port will immediately increase your SSH security by thwarting the efforts of hackers trying to brute force into port 22.

 

1. Update the sshd configuration file

sudo nano /etc/ssh/sshd_config

Change this line:

#Port 22

To this:

Port 578

Or whichever port you prefer.

 

2. It’s a really good idea to use a firewall, but if you haven’t yet configured UFW, you can skip this step until you do.

Add the new port:

sudo ufw allow 578/tcp

 

2. Reload sshd

sudo systemctl reload sshd

 

Disable root user login over SSH

By disabling root logins over SSH, you force hackers to have to guess your user name as well as your password.

 

1. Create a user with sudo privileges

Create user:

adduser 

Add the user to the sudo group to give it sudo access:

usermod -aG sudo 

 

2. Update the sshd configuration file

sudo nano /etc/ssh/sshd_config

Change this line:

PermitRootLogin yes

To this:

PermitRootLogin no

 

3. Reload sshd

sudo systemctl reload sshd

 

Disable password authentication

Finally, we’ll disable password authentication in favor of using super long, basically impossible to brute force, ssh keys!

 

1.  Create an SSH key pair

On your local workstation, create an ssh keypair at the command line:

ssh-keygen

 

2. Copy the public key to your server

ssh-copy-id @ -p 578

 

3. Update the sshd configuration file

sudo nano /etc/ssh/sshd_config

Change this line:

PasswordAuthentication yes

To this:

PasswordAuthentication no

 

Conclusion

By making all of these changes, we’ve forced hackers to guess our username, port, and super long ssh key! This should make any hack over SSH basically impossible!

Securing SSH on CentOS 7

Securing SSH is highly recommended as it is a common target for hackers on the internet. I’ll show you how to secure SSH by changing the port, disabling password authentication, and disabling root login over SSH.

 

Changing the SSH port

Changing from the default port will immediately increase your SSH security by thwarting the efforts of hackers trying to brute force into port 22.

 

1. Update the sshd configuration file

sudo vim /etc/ssh/sshd_config

Change this line:

#Port 22

To this:

Port 578

Or whichever port you prefer.

 

2. Update firewalld

Add the new port:

sudo firewall-cmd --permanent --zone=public --add-port=578/tcp

Reload the firewall:

sudo firewall-cmd --reload

 

3. Reload sshd

sudo systemctl reload sshd

 

Disable root user login over SSH

By disabling root logins over SSH, you force hackers to have to guess your user name as well as your password.

 

1. Create a user with sudo privileges

Create user:

adduser 

Give the user a new password:

passwd 

Add the user to the wheel group to give it sudo access:

usermod -aG wheel 

 

2. Update the sshd configuration file

sudo vim /etc/ssh/sshd_config

Change this line:

#PermitRootLogin yes

To this:

PermitRootLogin no

 

3. Reload sshd

sudo systemctl reload sshd

 

Disable password authentication

Finally, we’ll disable password authentication in favor of using super long, basically impossible to brute force, ssh keys!

 

1.  Create an SSH key pair

On your local workstation, create an ssh keypair at the command line:

ssh-keygen

 

2. Copy the public key to your server

ssh-copy-id @ -p 578

 

3. Update the sshd configuration file

sudo vim /etc/ssh/sshd_config

Change this line:

PasswordAuthentication yes

To this:

PasswordAuthentication no

 

Conclusion

By making all of these changes, we’ve forced hackers to guess our username, port, and super long ssh key! This should make any hack over SSH basically impossible!

How to use Windows Defender Firewall with Advanced Security on Windows Server 2016

How to use the Windows Defender Firewall with Advanced Security

The Windows Defender Firewall is a host-based firewall that runs on Windows Server and is enabled by default. Management of the firewall can be accomplished in multiple ways, but for this tutorial, we will solely use the management snap-in, “Windows Defender Firewall with Advanced Security”. Using this snap-in you can control both the inbound and outbound traffic to/from the server.

Accessing the Windows Defender Firewall with Advanced Security snap-in

  • Open the Server Manager from the task bar.
  • On the right-hand side in the top navigation bar, click Tools and select Windows Defender Firewall with Advanced Security.
  • Review the current configuration settings by selecting Windows Firewall Properties from the MMC landing page. You can access and modify the settings for each of the three firewall profiles, Domain, Private, and Public, as well as IPSec settings.

*Alternatively the Windows Defender Firewall can also be accessed quickly with the following:

Start → Run → wf.msc

The Windows Firewall has a default preference of, Deny all incoming traffic that is not explicitly allowed by an Inbound Allow rule, and conversely, Allow all outgoing traffic unless a corresponding Outbound Deny rule exists. Windows Server will automatically add exceptions to the firewall based on the roles, features, or apps that you install, or in some cases, Windows will simply toggle the state of existing rules.

For instance, if you install the “Web Services (IIS)” role, then Windows will automatically create an inbound exception for traffic on Port 80 for the IIS process specifically. This will allow incoming client requests to reach your website. Or, if you enable Remote Desktop via the system properties it will automatically toggle the state of the existing rules, “Remote Desktop User Mode (Tcp-In)” and “Remote Desktop User Mode (UDP-In)” to enabled, allowing incoming RDP requests on port 3389. Enabled Rules can be identified by the green check mark preceding the name of the rule.

Using the Window Firewall with Advanced Security one can limit the exposure of an application to improve security. This can be done fairly easily by limiting the scope of remote IP addresses that are allowed to connect or disabling the rule if it’s not needed.

Below is an example:

Restricting access to the RDP Port 3389:

  • Open Windows Firewall, Start → Run → wf.msc
  • Select Inbound Rules from the left side navigation pane

  • Within the list of Inbound Rules, locate the rule, “***Remote Desktop User Mode (Tcp-In)***” and double-click it to bring up the rule’s properties pane.
  • Select the tab, “Scope“, then select “These IP addresses” under “Remote IP Addresses” then hit “Add…” to enter one or more IP addresses.

  • Now any request to the server’s port 3389 from a remote IP not on the list will be dropped.

Creating Custom Firewall Rules.

Custom rules can allow for more granular control over inbound and outbound traffic to your Windows Server. In this example, we will create a custom firewall rule to limit access to ports 80 and 443.

  • Open Windows Defender Firewall with Advanced Security snap-in

(Start → Run → wf.msc).

  • Select “Inbound Rules” from the left-hand side Navigation pane.
  • Under the “Actions” Pane, on the right-hand side, choose “New Rule
  • In the “New Inbound Rule Wizard”, select rule type “Custom“, then hit next.

  • Choose “All Programs”, then hit next.

  • Next, select the protocol type that your application uses. For this example, we will use TCP.
    • Change Local Port from all ports to ‘Specific Port‘, then enter the port(s) that your application listens on:

  • On the next screen, choose “These IP addresses” under, “Which remote IP addresses does this rule apply to?” and select Add to enter one or more IP addresses that this rule should apply to.
  • On the next page, you can choose to either, “Allow the connection”, or “Block the connection”. Depending on the option you choose will dictate whether or not the remote IP addresses are permitted to connect to your application on the port you defined.

Once you have finished adding the rule, it immediately goes into effect without need for rebooting the server or restarting services.

Configuring UFW with Ubuntu

Firewalls are an important part of configuring basic security for your server.

Firewalls are network appliances that monitor and filter traffic to and from your instance and decides what traffic is allowed to reach your server, and what traffic should be dropped.

At its core, UFW or Uncomplicated Firewall acts as a front end for managing iptables/nftables, which actually do the heavy lifting of filtering packets.

In this article, we’re going to make it even less complicated to configure a firewall based on your specific needs using UFW!

Install UFW on Ubuntu

You can run the following command to install UFW on Ubuntu using the apt package management tool:

# apt-get install ufw

Follow the prompts as appropriate to ensure you have the latest version of UFW installed.

Adding Rules

UFW is very straight forward in that you build a list of rules. You can build this list using a specific IP address, a subnet, an interface, a service or a port number.

First lets allow traffic over port 22 (or whatever port you’re using for SSH)

# ufw allow 22

This will allow traffic in on port 22. Alternatively, you could issue the following command for the same effect

# ufw allow ssh

Now lets make the firewall active by issuing the following

# ufw enable

Now lets check to ensure its running

# ufw status
Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere
22 (v6)                    ALLOW       Anywhere (v6)    

Nice! We see that not only is UFW running, but our rule regarding port 22 was also honored.

We can issue the following command and see a full list of applications we have installed, elligble to be used with ufw:

# ufw app list
Available applications:
  Apache
  Apache Full
  Apache Secure
  OpenSSH

In a brand new install, all that would appear here is OpenSSH, for the sake of the example, I installed Apache2.

so lets say we want to block and IP address. We can use the following method.

# ufw deny from 8.8.8.8

This will drop all incoming connections from the IP address 8.8.8.8 . We can also block an entire subnet, on a specific interface:

# ufw deny in on eth0 from 8.8.8.8/24

Next, we can allow access to only a certain port, if we so choose, for a given subnet.

# ufw allow from 8.8.8.8/24 to any port 21

Further we can open access to a port range, and even specify wether we want to allow TCP or UDP traffic.

# ufw allow 5000:5005/tcp

If we want to allow both types, not just TCP like we mentioned above, we’d simply omit the ‘/’ and everthing after.

We’ve got quite a few rules in place at this point, if you’ve been following along.

# ufw status
Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere
Anywhere                   DENY        8.8.8.8
Anywhere on eth0           DENY        8.8.8.0/24
21                         ALLOW       8.8.8.0/24
5000:5005/tcp              ALLOW       Anywhere
22 (v6)                    ALLOW       Anywhere (v6)
5000:5005/tcp (v6)         ALLOW       Anywhere (v6)

What if we want to remove a rule? Lets get a numbered list of them so that we can specify which rule we might want to modify or delete.

# ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22                         ALLOW IN    Anywhere
[ 2] Anywhere                   DENY IN     8.8.8.8
[ 3] Anywhere on eth0           DENY IN     8.8.8.0/24
[ 4] 21                         ALLOW IN    8.8.8.0/24
[ 5] 5000:5005/tcp              ALLOW IN    Anywhere
[ 6] 22 (v6)                    ALLOW IN    Anywhere (v6)
[ 7] 5000:5005/tcp (v6)         ALLOW IN    Anywhere (v6)

# ufw delete 2

This makes removing a rule straightforward and easy to understand. If we’ve completely mangled our setup and want reset, we can use just that command!

# ufw reset

You’ll get a prompt asking you to confirm, and if you issue a # ufw status again you’ll see your rules are gone and UFW will be listed as inactive.

Thanks for reading!

Setting up SSH Key Authentication on Linux/Mac

While password authentication can be made secure with complex passwords, changing the SSH port, and disabling the root user, it is best to make use of SSH keys for accessing your VM. You use these to protect your cloud server against brute force password attacks by using a public-private SSH key pair. 

Prerequisites: First, you would need to create an SSH key using an SSH client that is installed on your local machine. With Linux and Mac, OpenSSH is included, but if you’re using Windows you’d need to use an SSH client like PuTTY.


The following Steps will guide you through setting up SSH Keys:

1) Run the following command to generate an SSH key.

# ssh-keygen

This will prompt you to set a location for the keys. The default location is the ~/.ssh directory, and the default filenames would be id_rsa for the private, and id_rsa.pub for the public. Unless you’re very familiar with the process, it’s best to use the default locations so that no additional configuration would be needed. Pressing ENTER on the keyboard should tell it to advance using the default locations.

After you choose the location, you’ll be prompted to enter a password which will encrypt the SSH key file on your machine. You can choose to enter one, or press ENTER to skip this process. If you do choose to encrypt the key, you’ll be asked for the password each time you authenticate with the key.

Next, you’ll want to copy the public key onto the server you wish to use the SSH Key authentication on. You should be able to output the contents of the key file with the following command:

# cat ~.ssh/id_rsa.pub

Copy the entire output to you clipboard and SSH into the server you wish to install the public key on. Once you have logged into the server you want to place the SSH key into, you may need to create the ~/.ssh directory if one is not already present. You can do so by running the following command:

# mkdir -p ~/.ssh

Now you’ll need to create the file to place the output of the public key you copied. 

# nano ~/.ssh/authorized_keys

Paste the output of the public key that you copied using CTRL+SHIFT+V (or right clicking > paste). After the content is placed into the file, save and close the file by pressing CTRL+O and then ENTER, followed by CTRL+X.

Finally, you’ll need to modify the permissions on the ~/.ssh and the authorized_keys files with the following commands:

# chmod 700 ~/.ssh
# chmod 600 ~/.ssh/authorized_keys

Once this is done, test that you’re able to log into your VM without being prompted for a password. If access without a password is granted, your SSH Key setup was successful. You can now modify your /etc/ssh/sshd_config file and change PasswordAuthentication yes to PasswordAuthentication no

 

Configuring firewalld on CentOS 7

Firewalls are an important part of configuring basic security for your server.

Firewalls are network appliances that monitor and filter traffic to and from your instance and decides what traffic is allowed to reach your server, and what traffic should be dropped.

At its core, firewalld acts as a front end for managing iptables/nftables, which actually do the heavy lifting of filtering packets.

Install firewalld on CentOS 7

Before we get started, lets ensure we have firewalld installed by issuing the following command:

# yum install firewalld

Follow the prompts as needed to ensure you’ve got the latest version of firewalld installed before proceeding.

Zones

Now that firewalld is installed, let’s better explain a few concepts. Firewalld uses zones to manage various rules that dictate how strict or relaxed traffic should be, based
on what network or interface you’re using. This is mostly useful with dynamic networks or shifting interfaces, in other words, less important for servers as networks and interfaces are more static.

With that being said, there are some predefined zones we should be made aware of, ordered by most strict to most relaxed:

  • Drop – Ensures all incoming connections are immediately dropped without reply. Outgoing connections are possible and if made, bilateral traffic is allowed to pass.
  • Block – Similar to drop, but rejected connections are sent a reply message of icmp-host-prohibited or icmp6-adm-prohibited.
  • Public – For public, untrusted networks.
  • External – For use on external networks with masquerading enabled, especially for routers.
  • DMZ – For computers in your demilitarized zone. A DMZ is defined as publicly accessible, but with limited access to your internal network.
  • Work – For use in work areas. You mostly trust the other computers on this network not to harm your computer.
  • Home – For use in home areas.
  • Internal – For use on internal networks.
  • Trusted – All network connections are accepted.

Rule Permanence

A common issue we see is when a reboot occurs – expected or not – and suddenly your website stops loading or you’re unable to access it. This is often due to a problem with rule permanence. Changes made through firewall-cmd change the active firewall session only, and will not persist through a reboot. “Live session only” changes of this kind are for live testing of your rules before creating a disruptive change, that could end up locking you our of your server!

You can make rule changes permanent by using the the –permanent flag with firewall-cmd commands.

Becoming Familiar

The service firewalld can also be configured using XML, however we’ll be focusing on the use of firewall-cmd. Once you’ve got firewalld installed, lets go ahead and enable it to start by default:

# systemctl enable firewalld

Next, lets perform a reboot:

# shutdown -r now

Log back in to your server. Check whether the firewalld daemon is running with the following:

# firewall-cmd --state

If the status is ‘running’, you’re good to go. Next, let’s review our default zone:

# firewall-cmd --get-default-zone

This should return ‘public’. Now let’s take a look at what zones are active:

# firewall-cmd --get-active-zones
public
  interfaces: eth0 eth1

Taken what we’ve learned so far, let’s break down what this response indicates. First, we have an active zone, public. If more than one zone was active, they would also be listed here. Interfaces listed are where the active zone is being applied. Here we see the public zone is active on both eth0 and eth1.

You can specify which interface the rule applies to with the following:

# firewall-cmd --zone=home --change-interface=eth0

So now lets explore the rules for our zone:

# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0 eth1
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Again, because we only have one active zone, as is the default setting, we see the public zone listed with its associated rules. What we’ll want to take note of here, is the services section. This section details what services and traffic are being defined by that zone.

What we see here is SSH service and DHCP services are permitted, thus port 22 and 53 are open.

To explore other zones without applying them, you can issue the following command:

# firewall-cmd --zone=$zone --list-all

Where $zone is one of the zones we covered earlier.

Adding and Removing Services

To allow traffic for specific services, we can add them to an existing zone. To get a list of available services, run the following:

# firewall-cmd --get-services

This will return the services included in a fresh CentOS 7 install:

RH-Satellite-6 amanda-client amanda-k5-client amqp amqps apcupsd audit bacula bacula-client bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-collector ctdb dhcp dhcpv6 dhcpv6-client distcc dns docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server finger freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master git gre high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target isns jenkins kadmin kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls lightning-network llmnr managesieve matrix mdns minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole plex pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius redis rpc-bind rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips slp smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh steam-streaming svdrp svn syncthing syncthing-gui synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server

So lets say we’re running a web server, we’d likely be interested in opening up port 80 so that people can reach our site.

# firewall-cmd --zone=public --add-service=http
success

Let’s not forget that these changes are not permanent! If after we add these rules and ensure everything is as expected; we can add the –permanent flag to the end of this to ensure it services a restart.

This should cover most beginner use cases, if you have a custom port you want to open, or a service that is not listed in our –get-services command, you can open that port by adding the port, with the protocol defined after a forward slash:

# firewall-cmd --zone=public --add-port=1776/tcp --permanent