When you setup a SSH server on a public IP - within minutes you will be spammed with attempts to brute force your login.
Your first task as admin of a SSH server is to secure it.
Your SSH server is not the only server you may come across using ssh public key. If you are a using services like Github, GitLab, SourceForge, OSDN and many more - you have come across this before.
A SSH public key is actually a key pair - a public and a private key. The public part has the extension .pub and this is the key you place on the server or service.
You create key pair using the ssh-keygen utility. This utility takes various arguments which affects how the key-pair is generated and where the files are placed.
The defaults are sane but in case you want a stronger key, you can use the man-pages to expand your knowledge.
$ man ssh-keygen
It is recommended to use a separate key for each server and each device you are using to connect with and to tell the keys apart you use a different filename e.g. the name of the service. If you have a Linode cloud instance you could name the file linode or if you are using OSDN you may name it osdn.
To create a key-pair for a service using the service as name for the key-pair you supply the path to the file using the -f argument - in this example a Linode cloud server and the name of your instance e.g.
$ ssh-keygen -f ~/.ssh/linode-server.ppk
You don't need to use the .ppk part but doing so makes it easy to configure FileZilla as SFTP client using keyfile.
To upload the public part to the server - use the scp which is a shortname for secure copy. The command consist of three parts
$ scp ~/.ssh/linode-server.ppk.pub email@example.com:/root
SSH into your server and add it to the authorized_keys file
$ ssh firstname.lastname@example.org # cat linode-server.ppk.pub >> ~/.ssh/authorized_keys
A simpler option is to use ssh-copy
$ ssh-copy-id -i ~/.ssh/mykey user@host
Log off the server and test your connection using your identity file
# ssh email@example.com -i ~/.ssh/linode-server.ppk
You should now be logged in and have a root shell without being prompted for password.
While you are logged in as root edit the file /etc/ssh/sshd_config
# nano /etc/ssh/sshd_config
Scroll down to the lines reading
# To disable tunneled clear text passwords, change to no here! #PasswordAuthentication yes #PermitEmptyPasswords no
And change to
While you are logged in - seriously consider changing the port from default 22 to something else. Consult /etc/services to avoid collision with known services - but in reality any port over 10000 can be used.
The port is located at the top of the configuration
# Port 22 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress ::
Uncomment the line and change the port number
Save the changes and restart the sshd daemon
# systemctl reload sshd
Connecting to SSH server can be automated by means of the user's local configuration. One point to remember - the file is parsed from top to bottom - and the first match is used - so don't keep duplicated entries.
If you plan connect to the same server using different users this can easily be done using different names for the Host entry.
Every server or service is designated by the Host - all lines between Host entries belong to the preceding Host.
$ nano ~/.ssh/config
Based on experience - client side with a lot of key-pairs (using no password) - you may run into the message - too many failed logins - it took me a while - several hours to get to the bottom of it and the solution was to disable the ssh identity agent - it worked - so I have not bothered researching further.
Host * IdentityAgent none
Add your server details - examples
Host nickname Hostname server.domain.tld IdentityFile ~/.ssh/linode-server.ppk user root Port 33000 Host fido.domain.tld IdentityFile ~/.ssh/fido.ppk user fido
$ ssh nickname
You don't want to loose your key collection.
IMPORTANT: Keep a copy of your ~/.ssh folder in a secure location and if you are using password less keys - keep them safe by
chown $USER:$USER .ssh -R && chmod 600 ~/.ssh -R
Next step is to ensure only allowed services are accessible by implementing a firewall.
Firewalld a very good firewall service - well suited on systemd based systems like Manjaro. Firewalld can be configured using the term application since an application is merely a definition of which ports should be allowed - e.g. a http application or ssh or smtp.
When you configure the firewall you use zones to define where you are and services to define what you allow. Install firewalld
# pacman -Syu firewalld
When firewalld is enabled and started the default zone is public which allows the computer to be visible but all ports closed.
Adding a specific service (application) is most easily done using the command line. A GUI is available if you install the dependencies for it. Adding services has immediate effect - no need to reload the service. Simply add the service to the allowed service to the desired zone
Example - adding http to public zone
# firewall-cmd --zone=public --add-service=http success
It is important to realize that changes you make on the fly is not permanent. To make a certain service available on a permanent base you add the --permanent argument
# firewall-cmd --permanent --zone=public --add-service=http success
What if you want to add your own service definition?
Easy-peasy - look in the folder /usr/lib/firewalld/services and make a copy of an appropriate service definition.
Example - you want to run a ssh server on a non default port.
Copy the ssh.xml service definition to /etc/firewalld/services
# cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/my-ssh.xml
Edit the service definition
# nano /etc/firewalld/services/my-ssh.xml
Change the port to match your service and the short name to distinguish from the original service.
<?xml version="1.0" encoding="utf-8"?> <service> <short>My SSH service</short> <description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description> <port protocol="tcp" port="30000"/> </service>
Wait 5-10 seconds for the service file to be recognized and activate it
# firewall-cmd --zone=public --add-service=my-ssh success
Same rule on permanent applies and that's it.