OpenSSH-server is used to login remotely to your server thru a secure connection. For a server, this means that we will no longer be needing a monitor and keyboard.

For an advanced or even moderate user they would have used SSH as soon as the installation had finished. For our case, it is assumed we are a beginner and for that, it's important to setup the environment such as a static ip address and a firewall before we start using an SSH connection.

To check if the SSH server has been installed, type:

$ ssh -V

Output:

OpenSSH_8.9p1 Ubuntu-3, OpenSSL 3.0.2 15 Mar 2022

If you see similar output as above then skip the next step. Otherwise install OpenSSH-server:

$ sudo apt install openssh-server

Set Static ip

Note: This step is not necessary if Proxmox LXC container.

Unless you have DNS setup on your router pointing your server's hostname to a dynamically changing ip address, we are going to setup a static ip so our server's ip never changes.

1. Get Network Information

  • Let's take a look at what our current ip and gateway(router) addresses are, type:

    $ ip r
  • The output should look something to this:

    default via 192.168.1.1 dev enp0s25 proto dhcp src 192.168.1.119 metric 100 
    192.168.1.0/24 dev enp0s25 proto kernel scope link src 192.168.1.119 
    192.168.1.1 dev enp0s25 proto dhcp scope link src 192.168.1.119 metric 100


    From the result above, the gateway is 192.168.1.1 and my network adapter is named enp0s25 with an address of 192.168.1.119. Your adapter could have a different name, so take note of it and it's ip address. Also take note of the gateway address.

2. Setup Netplan

If you are new to Ubuntu Server versions 18.04 and up, Netplan now replaces ifupdown as the network configuration utility and uses .yaml files to generate the network process. This new system is a bit picky with the syntax inside the configuration file. So make sure you use the proper indentation.

  • Let's change directory to that of netplan:

    $ cd /etc/netplan
  • Now we need to list files that are in the netplan directory, type:

    $ ls
  • The resulting output for me is:

    00-installer-config.yaml

    Your yaml file could have a different name then mine, just make sure to replace the following commands with name_of_your_file.yaml.

  • Before editing the file 00-installer-config.yaml we will make a copy. Here I will use the extension .bak for my backup copy, type:

    $ sudo cp 00-installer-config.yaml 00-installer-config.yaml.bak

Tip: It is best practice to make a copy of a file before editing with sudo cp original_file backup_file. If a mistake is made you can always revert to original file by reversing the command this way: sudo cp backup_file original_file

  • Confirm copy of the file exists:

    $ ls

    Output:

    00-installer-config.yaml  00-installer-config.yaml.bak

    As we can see, our file is backed up.

  • Let's edit our .yaml file with vi to keep a static ip and use default nameservers, type:

    $ sudo vi /etc/netplan/00-installer-config.yaml

    If you try the command and your server returns that vi is not installed do:

    $ sudo apt install vim

    The file should look like this(if using 22.04 see bottom section):

    # This is the network config written by 'subiquity'
    network:
    ethernets:
        enp0s25:
        dhcp4: true
    version: 2
    ~
    ~
  • Hit the "i" key to enter insert mode.

  • Use the "arrow" keys to navigate to each line, and edit the file like so(keep in mind to replace addresses and interface name with your own):

    # This is the network config written by 'subiquity'
    network:
    renderer: networkd
    ethernets:
        enp0s25:
        dhcp4: no
        addresses: [192.168.1.119/24]
        gateway4: 192.168.1.1
        nameservers:
            addresses: [8.8.8.8, 192.168.1.1, 127.0.0.1]
    version: 2
    ~
    ~

    Line by line explanation:

    • We are using renderer: networkd to specify systemd-networkd. You can use NetworkManager as renderer but this is beyond the scope here.

    • The dhcp4: no line specifies static instead of dynamic(dhcp4: true). Can also use dhcp4: false.

    • The addresses: [192.168.1.119/24] line is the static ip address we will use. Replace with your own ip address.

    • The gateway4: 192.168.1.1 line is our router address. Remember to replace with the address you have noted previously.

    • The nameservers: line has all our dns servers addresses line beneath it and properly indented. We are using googles dns 8.8.8.8 and you can also use another google dns 8.8.4.4 as well. Optionally we are using the gateway address 192.168.1.1 as my own router is setup as a dns server and my network has it's own domain name such as .lan. You can safely omit this one but it does not hurt to have it there for future plans. And finally, our reason for using the Loopback address 127.0.0.1 as nameserver is for setting our Fully Qualified Domain Name(FQDN) later in our setup and configuring the hosts file. This is also optional but still it will come in handy down the line.

Note: Make sure indentation is set to two or four spaces. Netplan can be quite finicky with indents.

  • The file is now ready to save. Hit the "Esc" key to exit "INSERT" mode and type :wq to write the file and save it by pressing "enter" key to exit the editor.

  • Now we test our configuration with the following command:

    $ sudo netplan try
  • Press "enter" to accept. If the return is "Configuration accepted", apply the configuration with:

    $ sudo netplan apply

If there are any errors the program will let you know where they are.

  • Finally we test by pinging Google:

    $ ping google.com
  • If pinging is successful hit Ctrl + C keys to stop ping process.

  • Let's get back to our home directory as we are still in /etc/netplan directory. Simply type:

    $ cd

Our ip address is now static and will never change unless you manually do so.


Ubuntu 22.04

  • For Ubuntu 22.04 gateway4 has been depricated and now uses routes. Also please note how the addresses lines are now written. Your netplan file should look like this :
    # This is the network config written by 'subiquity'
    network:
      renderer: networkd
      ethernets:
      eno1:
        dhcp4: no
        addresses: 
          - 192.168.1.130/24
        routes: 
          - to: default
            via: 192.168.1.1
        nameservers:
          addresses: [8.8.8.8, 192.168.1.1, 127.0.0.1]
      version: 2
    ~
    ~

Enable UFW(Uncomplicated Firewall)

UFW sets our firewall rules. Most notably during future component installations so that we can allow/deny ports and/or services. Using UFW will write to the "ip tables" file. Basically, "ip tables" is our firewall and UFW is used to add/remove firewall rules.

  • Let's start by enabling UFW:

    $ sudo ufw enable


    Output:

    Firewall is active and enabled on system startup
  • Check status:

    $ sudo ufw status


    The output should look like this in Ubuntu 18.04 and 20.04:

    Status: active
    
    Logging: on (low) 
    Default: deny (incoming), allow (outgoing), disabled (routed) 
    New profiles: skip


    Ubuntu 22.04 should just be Status: active.

Now let's allow SSH(default port 22) access from the client device's ip address that we will use to connect to our server later in this tutorial.

Be sure to replace the ip address I am using here with the client's ip address you will use.

  • My client's ip address is 192.168.1.102, so type:

    $ sudo ufw allow from 192.168.1.102 proto tcp to any port 22
  • Check status using numbered rules:

    $ sudo ufw status numbered


    Output:

    Status: active
    
         To                         Action      From
         --                         ------      ----
    [ 1] 22/tcp                     ALLOW IN    192.168.1.102


    Optionally, you could allow more clients to connect with SSH.

  • Let's allow SSH(Secure Shell) as we are going to use it soon, type:

    $ sudo ufw allow OpenSSH
  • Check status:

    $ sudo ufw status numbered


    The output should be:

    Status: active
    
     To                         Action      From
     --                         ------      ----
    [ 1] 22/tcp                     ALLOW IN    192.168.1.102
    [ 2] OpenSSH                    ALLOW IN    Anywhere
    [ 3] OpenSSH (v6)               ALLOW IN    Anywhere (v6)


    You will notice that 2 rules have been added. One for "ipv4"(as "Rule added") and the other for "ipv6"(Rule added (v6)). We have added rules based on the application used

  • For now ssh will be allowed from anywhere, so lets remove the rules pertaining to OpenSSH just so we learn how to delete rules. Now type:

    $ sudo ufw delete 1

That's it for UFW. If you would like to learn more see here

SSH with key-based Authentication

During this section we will refer to "host" as being our server and "client" as the device from which we are connecting with.

If you are using a Windows computer as client you may want to consider using Putty. But for the purpose of this tutorial we will be using Ubuntu Desktop and it's Terminal.

Assuming that you have installed SSH during the previous step and enabled UFW, let's get started.

Client

Note: If you have already setup an SSH Key Pair and wish to re-use it, read the last paragraph in this section.

  • Now we open the Terminal on client computer and create a private/public key pair by typing:

    $ ssh-keygen

    You will see the following output, just hit "enter" to accept the default file location.

    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/user/.ssh/id_rsa): 
  • Here we are asked for a passphrase. It is recommended to enter a passphrase to prevent unauthorized access. Type one and press "enter" to accept:

    Enter passphrase (empty for no passphrase): 

    You will now see the following output which confirms we have our key pair:

    Your identification has been saved in /home/user/.ssh/id_rsa.
    Your public key has been saved in /home/user/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:0PmorbXbMy0wM+Sjdbe67ls15Zh8EgyHMpcge9E78gvw user@server
    The keys randomart image is:
    +---[RSA 2048]----+
    |     . ...o      |
    |      =o+=     |
    |      .*o=     |
    |    . +o+ +   |
    |     + *S.+ = o  |
    |    . ooO  + o   |
    |     .. o*o.E    |
    |       o.++ .    |
    |      ..+..+     |
    +----[SHA256]-----+

    Before copying the public key to the host, there is a file in Ubuntu(your client) called "known_hosts" in the ssh directory. This file, does not have the proper permissions for "user"(your_username), to copy the key to the host. If permission remains as "root" you will get this error:

    failed to add the host to the list of known hosts
    • To prevent this error, we type the following command exactly as is:
      $ sudo chown -v $USER ~/.ssh/known_hosts
  • Now we can copy the public key to the host with "ssh-copy-id" utility:

    $ ssh-copy-id your_username@host_ip_address
  • You will see this output, enter your password:

    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    "your_username@server_ip" password: 

    You will see the following confirming the key has been added:

    Number of key(s) added: 1
    
    Now try logging into the machine, with:   ssh your_username@server_ip
    and check to make sure that only the key(s) you wanted were added.
  • Now connect to your server(host) with SSH to confirm it works, type:

    $ ssh your_username@server_ip_address

After confirming you should now be connected to your server via SSH.

  • If you have other devices you would like to use for connecting to the host in this manner, and I recommend you do so, repeat the steps from above.

  • If you have other hosts you would like to connect to using the same client, follow the steps starting from ssh-copy-id your_username@host_ip_address. You can use the same key pair as previously created, but if you choose to generate another one, you must store it in a location other then /home/user/.ssh/id_rsa which was the accepted default location for previously created key pairs.

Host

Although an SSH connection is somewhat secure in itself, meaning that the communication and data between client and host is encrypted, we are still vulnerable to many different attacks. Disabling password authentication is a good way to render one of the most common attacks unsuccessful on SSH protocol; brute force. A brute force attack involves guessing username and passwords to gain unauthorised access to a system. In a later chapter we will work on preventing these attacks server-side with fail2ban. For now let's secure SSH.

This is a sensitive step whereas you could be locked out of your server if the key pair process was NOT properly done. So, be positively sure that your ssh key-based authentication is working before continuing.

  • Let's first make a backup copy of the configuration file before editing it:

    $ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
  • Now open the file with the editor:

    $ sudo vi /etc/ssh/sshd_config
  • Inside this file, scroll down until you find the line #PasswordAuthentication yes and set to no. This line is probably commented out(hashtag to the left). Hit the "i" key to enter insert mode, "backspace" to remove the hashtag, and change "yes" to "no". The line should look like this:

    PasswordAuthentication no
  • While we are here we can also make sure that root login is disabled via SSH. Look for the following line and if not there, insert it anywhere in the file:

    PermitRootLogin no
  • Also we will uncomment the following line for public key authentication:

    PubkeyAuthentication yes
  • Hit "Esc" key and type :wq to save and exit.

  • Now restart ssh service:

    $ sudo systemctl restart ssh

Now type exit and try to connect with host using the command ssh your_username@server_ip_address.

Note: If error Permission denied (publickey) run the following command from the client:

$ ssh-keygen -R host_ip_address

We can now use SSH to connect to our server. You can disconnect the keyboard and monitor from now on. Just reboot the system so that it removes the hardware from the ports and memory.

Previous Post