In this tutorial we shall be going through the process of setting up a server on the internet using Ubuntu 16.04, from the command line, configuring the initial server build, user accounts, to hardening SSH and installing the relevant software for making our server accessible to the Tor network.
This article is going to be lengthy so I would strongly advise that you grab a cuppa and make yourself comfortable! Ideally you will have a reasonable level of confidence in navigating the command line if you’re attempting the steps outlined in this tutorial, though you may simply copy and paste from here.
What is Tor?
The Onion Router (Tor) is an open-source software program written in C programming language with roughly 146,000 lines of source code, originally developed for the U.S. Navy in an effort to protect government communications. The name of the software originated as an acronym for the The Onion Router, but Tor is now the official name of the program.
Tor was released in 2002 and is geared toward protecting users from online surveillance that aims to track their online activities. The main idea behind designing Tor was to protect the personal privacy of network users, journalists, the military, activists, law enforcement officers and allow them to conduct confidential business. It is also widely used in location-hidden services providing anonymity to servers and allows users to protect against traffic analysis.
Tor is an implementation of onion routing, which involves running an onion proxy on a user’s machine. The software is designed to negotiate a virtual tunnel through the Tor network by encrypting and randomly bouncing communications through relay networks across the world. Tor networks provide anonymity to applications such as Internet relay chat, instant messaging and Web browsing. Tor is conjugated with Privoxy, a proxy server that provides privacy at the application layer.
Let’s Build!
This guide serves as the template for all my servers running Ubuntu 16.4. The default server installation needs additional configuration before being considered appropriate to use in production. Although it is popular to use automation tools nowadays, this guide does not!
Prerequisites
Assuming that you will be using a remote server, the server should already have Ubuntu 16.04 installed, and you have root access to it. We will be using REMOTE_SERVER_IP
as placeholder for the IP address of your remote server. We will also be using USER_NAME
as the placeholder for your user account on the server, and PUB_KEY
as a placeholder for your public key.
Remote Login
From your local computer connect to your remote server with ssh. You may use Microsoft Windows PowerShell if you’re on a PC. I prefer to use Token2Shell as I find it much more unique and a lot more slick!
Regardless of the application you choose, the commands will be the same:
ssh root@REMOTE_SERVER_IP
Update & Upgrade
It is good practice in my opinion to run this operation whenever you start a new session on a remote server. It only takes a moment:
apt-get update && apt-get upgrade
Nano
Unless you have confidence with another terminal editor, you should use ‘nano
‘. If nano is not already installed, you can install it easily with the following command:
apt-get install nano
Create a User
When you log in as your own user account, programs you run are restricted from writing to the rest of the system – they can only write to your home folder. You can’t modify system files without gaining root permissions. Therefore running as root
by default is obviously discouraged as it poses a security risk… Instead we will create a new user with 'sudo'
privileges:
adduser USER_NAME
You will be asked to set the new user’s password. You will also have the opportunity to fill in the users full name, room number, telephone numbers etc. but this may be left blank by hitting carriage return, until you are asked to confirm the account creation information is correct.
Now give this user 'sudo'
privileges.
usermod -aG sudo USER_NAME
You should now logout of the remote server as we are going to move on to creating SSH key pairs to further enhance the security of any future sessions with this server. If you have already generated SSH keys and wish to use them then you may skip the next section, which is about how to…
Generate SSH Keys
On your local machine generate your pair of SSH keys by using the following command:
ssh-keygen
You will be asked several questions. Accept the default file location for the key. Answer the others as you wish.
Note: If you leave the passphrase blank, then your system will be less secure. Possession of the keys will be enough to gain access.
Convenience is often the enemy of security!
Copy Public Key
Still on your local machine, copy your public SSH key to the remote server. We will presume that you are using Microsoft Windows as the majority of my traffic seems to come from those who are visiting this website on that operating system, and so the command 'ssh-copy-id'
will likely be an issue. Let’s instead use a different approach to achieve the same thing:
cat ~/.ssh/PUB_KEY | ssh USER_NAME@REMOTE_SERVER_IP "mkdir ~/.ssh; cat >> ~/.ssh/authorized_keys"
Remember to use the password for the new user we setup earlier!
After the key has been successfully copied, log into the remote server as USER_NAME
using the key we generated – you will be asked for your passphrase after this command:
ssh -i ~/.ssh/PUB_KEY USER_NAME@REMOTE_SERVER_IP
Excellent! You should now be logged in to the remote server using your unique key.
From here on we will proceed all of our commands with ‘sudo’ to ensure access is granted on a system level when we start to…
Harden SSH
We are going to reconfigure our SSH server to enhance the security of the remote server by editing the sshd_config
. As with any important configuration changes, one must first make a backup copy of the initial configuration before we go editing it:
sudo cp /etc/ssh/sshd_config /etc/ssh/backup.sshd_config
Then we can proceed to:
sudo nano /etc/ssh/sshd_config
Check Protocol
Our very first edit will be a simple one. It is really more of a double check than an edit. Make sure that Protocol
it is set to 2 and not 1. The current default is 2. However, this may not be present in the file, in which case, add it.
Protocol 2
Review Authentication
Check and make sure that public key authentication is enabled. Find the line that starts PubkeyAuthentication
. Make sure it is set you yes
.
PubkeyAuthentication yes
We want to disable password authentication. Find the line that starts PasswordAuthentication
. Set this to no
.
PasswordAuthentication no
Disable Root
We do not want root to be able to log in remotely. Find the line that starts PermitRootLogin
. Set this to no
.
PermitRootLogin no
Disconnect Idle Sessions
Idle sessions can be dangerous. It is a good idea to log people out after a set amount of inactivity. The ClientAliveInterval
is the amount of time in seconds before the server will send an alive message to the client after no data has been received. ClientAliveCountMax
is the number of times it will check before disconnecting. In the example below, the server will check on the client after 5 minutes of inactivity. It will do this twice then disconnect.
ClientAliveInterval 300
ClientAliveCountMax 2
Whitelist Users
We can limit the users that are allowed to log in SSH. This is a whitelist. Only users in this list will be allowed. Everyone else will be denied. Let’s say that I want to allow user norton
to log in remotely through SSH. We will add the line:
AllowUsers USER_NAME
Don’t forget to add your username to the AllowUsers
list!
Change Ports
Normally SSH runs on port 22. The idea is that most script kiddies are only going to target that default port. If you change the default port, maybe your attacks will decrease… In the configuration file find the line:
Port 22
Then change it to another available port, maybe 31337.
Port 31337
I do not recommend that you reset the SSH port – but, maybe you’re paranoid and wish to be extra careful…
Disable X11Forwarding
Generally speaking, since we are using a CLI there is no reason to use a GUI for a remote server. So disable X11 forwarding:
X11Forwarding no
SSH Configuration Test
After editing the configuration file you should test that it is valid before reloading the service, with the following command:
sshd -t
Reload the Configuration File
Once you think your edits are good, reload the SSH daemon, like so:
sudo systemctl reload sshd
Fail2Ban
This is a great program that can scan logs and ban temporarily ban IPs based on possible malicious activity. You will need to install Fail2ban:
sudo apt-get install fail2ban
Once installed, we copy the fail2ban configuration file:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Open the /etc/fail2ban/jail.local
files and find the spot that starts [sshd]
. Edit it like so, adding enabled = true
:
[sshd] enabled = true
port = ssh
logpath = %(sshd_log)s
Then restart fail2ban:
sudo service fail2ban restart
Fail2ban will monitor your SSH logs for possible malicious activity and then temporarily ban the source IP.
SSH Audit
So far we have been covering the basics. Now we move into some more advanced SSH hardening. SSH Audit is a Python script that will scan your SSH server for some security issues. Download it and run it like any other python script, just point it at your target SSH server.
python ssh-audit.py REMOTE_SERVER_IP
This report gives us a peek behind the SSH curtain. This is a report on the ciphers and algorithms used by your SSH server to secure communications with the client. If you have done work with OpenSSL some things might look familiar. As you may have learned using OpenSSL, not all ciphers and algorithms are equal. Some are strong and some are weak. Eliminating the weak ones can help harden your system.
Change Hostkey Preference
We will be following the advice of stribika, mozilla, and the SSH audit report. We will change our HostKey preferences. Remove the current HosyKey entries in the ssh configuration file. Replace them with the following.
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
Change Default Ciphers and Algorithms
Continuing to follow the advice of stribika, mozilla, and the SSH audit report. We change our Key exchange algorithms, symmetric ciphers and, message authentication codes. Add or replace the following to the ssh configuration file.
KexAlgorithms curve25519-sha256@libssh.orgCiphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctrMACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
Rerun the Audit
Let us see if our changes made the SSH audit happy:
python ssh-audit.py REMOTE_SERVER_IP
Regenerate Moduli
The /etc/ssh/moduli
file contains prime numbers and generators used by the SSH server for the Diffie-Hellman key exchange. Your current /etc/ssh/moduli
is probably not unique. Generating a new file may harden your server. Generating these files might take awhile.
ssh-keygen -G moduli-2048.candidates -b 2048
ssh-keygen -T moduli-2048 -f moduli-2048.candidates
cp moduli-2048 /etc/ssh/moduli && rm moduli-2048
The Firewall
A simple yet effective firewall that is easy to maintain and lovely to use… Let’s install the Uncomplicated Firewall (UFW) – I told you this tutorial would be long – your tea is probably now cold!
sudo apt-get install ufw
Your firewall configuration will change as you add server programs. This guide only cares about the SSH server.
sudo ufw allow ssh
Then enable the firewall:
sudo ufw enable
Multi-Factor Authentication
We can also user TOTP (Time-Based One-Time Passwords) to harden our SSH security. In this example we will be using Google Authenticator. When we attempt to log into the system we will be challenged to provide a verification code. We will use the Google Authenticator app to generate that code. First we need to install some software:
sudo apt-get install libpam-google-authenticator
Then run the initialization:
google-authenticator
It will ask: Do you want authentication tokens to be time-based (y/n)
and we need to say yes. Then it will print out the QR code and ask if want to update our .google_authenticator
file. We do.
Scan that code into the Google Authenticator app and save those emergency codes! You will next be asked a few more question. We will answer them all with yes.
Edit the PAM rule file /etc/pam.d/sshd
adding the follow at the end:
echo "auth required pam_google_authenticator.so" >> /etc/pam.d/sshd
Now, go back and edit the ssh configuration file and update the following:
UsePAM yes
ChallengeResponseAuthentication yes
And restart the SSH server. The system will now require a verification code when you log into the server.
Name Your Server
Generic server names can be confusing. In this guide we will name our server skywalker
. Let’s change the hostname:
sudo nano /etc/hostname
Change it to skywalker
, then save. Now edit the hosts file:
sudo nano /etc/hosts
…And add you server name like so.
127.0.0.1 localhost
127.0.1.1 skywalker
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Now reboot!
sudo reboot
Configuring for Tor
Now we have secured our server to a level let’s get on to setting up our Tor website… Grab more tea!
The Tor packages found in the default repositories for Ubuntu are not reliably updated. The Tor project maintains their own repository. We must add that repository.
Open up your sources.list
file:
sudo nano /etc/apt/sources.list
Add the following to the end of the file:
deb http://deb.torproject.org/torproject.org xenial main
deb-src http://deb.torproject.org/torproject.org xenial main
Save the file, and now back in the command line add the gpg key:
gpg --keyserver keys.gnupg.net --recv A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89
gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add -
Run the update:
sudo apt-get update
Then install Tor:
sudo apt-get install tor deb.torproject.org-keyring
The Hidden Service
We need to edit the Tor configuration file to enable our hidden service. First we will make a backup of this configuration file.
sudo cp /etc/tor/torrc /etc/tor/OLD.torrc
Then edit the configuration file.
sudo nano /etc/tor/torrc
By default all Tor client services, relays, and hidden services are commented out and disabled. Let’s active the hidden service. Find the section for hidden services. It will look something like this.
############### This section is just for location-hidden services ##### Once you have configured a hidden service, you can look at the
## contents of the file ".../hidden_service/hostname" for the address
## to tell people.
##
## HiddenServicePort x y:z says to redirect requests on port x to the
## address y:z.
##
#HiddenServiceDir /var/lib/tor/hidden_service/
#HiddenServicePort 80 127.0.0.1:80
##
#HiddenServiceDir /var/lib/tor/other_hidden_service/
#HiddenServicePort 80 127.0.0.1:80
#HiddenServicePort 22 127.0.0.1:22
Un-comment the following lines:
#HiddenServiceDir /var/lib/tor/hidden_service/
#HiddenServicePort 80 127.0.0.1:80
The hidden services section should now look like this.
############### This section is just for location-hidden services ##### Once you have configured a hidden service, you can look at the
## contents of the file ".../hidden_service/hostname" for the address
## to tell people.
##
## HiddenServicePort x y:z says to redirect requests on port x to the
## address y:z.
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:80
#HiddenServiceDir /var/lib/tor/other_hidden_service/
#HiddenServicePort 80 127.0.0.1:80
#HiddenServicePort 22 127.0.0.1:2
Restart Tor!
sudo service tor restart
A couple of files should have generated by Tor. First is a hostname file. Open it up to get your .onion address.
sudo nano /var/lib/tor/hidden_service/hostname
My file contained 2rjp7e2cn4ppizgn.onion
. Your file should contain something similar. The other file is a private key. Open it up and take a look:
sudo nano /var/lib/tor/hidden_service/private_key
It should look similar to this.
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQCnNsOc9iODyPGeLFvkTcgENzZ/c1aKAwslQ/WwLjd9rRh4rfK7
4887uS+Thb3ggnVDc+GKHwkBlJY5Zvo95atYIHigGHR1QCbZ1GCBt4YebLcCBrNG
1zsDoDEbxu4MqVB+0dntEJ2CDciHz6lnSvz9VJoWA8m5PNlC4ITZ+v1prQIDAQAB
AoGBAKCCPCFmUE8HS492qzqqwy3wxfpvf4l5RHCgHK3in1efGZd1+kQLeHiu2ZF1
Vv+0mtWF3eDUy7g0oDluck1337Haxor1FcoKGEgpCXtVnOuEnEJEn/K+dFsxFYBd
AUuZ61yOC7cWySAJA1pi5CtJQm1aH10IxyNYg9kjOPbEiIjBAkEA3UtXwwTxHWLZ
hvcBLzM3uQ31CK93HKar40DyYmlOHZfHPhzgwjr3gwbAjqKnx0AXcnBuhy1gwwW8
U4V6yDSNyrqfiYcMPCYVEKZV/ebmBLW0BWOw+kimukGhGQ==
-----END RSA PRIVATE KEY-----
With these files two files you can move your server to a new machine if eventually necessary. Copy these files and keep them secure.
Nginx
Nginx is a good web server for this project. Install Nginx:
sudo apt-get install nginx
… And allow HTTP traffic through our firewall:
sudo ufw allow 'Nginx HTTP'
Visit your server’s external IP address to verify that the web server is operational, and if things are working correctly (you should see an informative web page), remove this rule. Then reload the firewall.
sudo ufw deny 'Nginx HTTP' && sudo ufw reload
nginx.conf
Edit the main Nginx configuration file to disable undesirable information sharing.
sudo nano /etc/nginx/nginx.conf
Inside the http
block add the following
server_name_in_redirect off;
server_tokens off;
port_in_redirect off;
Then restart the Nginx server:
sudo systemctl restart nginx
Web Server Root Directory
Make a directory to hold our files for the web server.
sudo mkdir /var/www/dark_web
Create a test page for your site. Echo anything as we are simply testing display. We don’t even need actual html, just something kinda unique for right now… So:
echo "Welcome to my dark web page!" > /var/www/index.html
Set the permissions so that Nginx can access the files:
sudo chmod 755 /var/www/dark_web
Remove Nginx Default
Remove the default site.
sudo rm /etc/nginx/sites-enabled/default && sudo rm /etc/nginx/sites-available/default
Add Available Site
Make a new site in the sites-available
directory.
sudo nano /etc/nginx/sites-available/dark_web
Inside add the following replacing the root
and server_name
values for your instance.
server {
listen 127.0.0.1:80;
root /var/www/dark_web/;
index index.html;
server_name 2rjp7e2cn4ppizgn.onion;
}
Add this site to the site_enabled
directory:
sudo ln -s /etc/nginx/sites-available/dark_web /etc/nginx/sites-enabled/
Then restart the Nginx server.
sudo systemctl restart nginx
Tor Browse!
Open up your Tor Browser and visit your .onion address that was generated earlier. If the system is properly operational then you will see the dummy index.html
page that we made previously.
Conclusion
You made it! Today we have learnt about how to build a simple server environment, securing it and adding a simple web page that is accessible through the Tor network – congratulations!
Looking to accept Bitcoin through your new Tor connected website? Market on the Blockchain will help to guide you through that process.