Skip to content

Lab: your own SSH server ​

Turn a Linux computer you own into an SSH server and use it from SecureShell Go: check its host key, sign in with a key, copy files both ways, and reach a mock API on it through a tunnel. You finish by putting everything back the way it was.

Level: beginner · Time: 45 to 60 minutes · Before this: the five lessons of this track

What you need ​

  • A Linux computer you own, where you can use sudo, and where you are sitting at the keyboard. The steps are written for Ubuntu 22.10 or later; differences for Ubuntu 22.04 are noted. This lab calls it the server.
  • A client: an Android phone with SecureShell Go, or a second Linux computer with SecureShell Go. See Install SecureShell Go.
  • Both on the same network, such as your home Wi-Fi. Not a guest network: it may stop devices from seeing each other.
  • Mock Studio on the server, and the file todo-api.mockstudio.json from the Todo API lab.
  • Optional: ApiWorkbench on the phone, for part 7.

The examples use the address 192.168.1.20 and the account maya. Use your own server's address and account wherever you see them.

Your own computer only

Do this lab on a computer that is yours. Turning on an SSH server, changing its settings or its firewall on someone else's machine needs their permission, and on a work computer it may break your organisation's rules.

Part 1: turn on SSH ​

  1. On the server, open a terminal and install the SSH server:

    bash
    sudo apt install openssh-server

    Expected: the package installs. If it says openssh-server is already the newest version, SSH was already installed; carry on.

  2. Check that it is listening:

    bash
    systemctl status ssh.socket

    Expected: Active: active (listening). Press q to leave. On Ubuntu 22.04, run systemctl status ssh instead and look for active (running).

  3. Check the port:

    bash
    ss -tln | grep ':22 '

    Expected: two lines, one with 0.0.0.0:22 and one with [::]:22. The server accepts SSH on every interface.

  4. Check the firewall:

    bash
    sudo ufw status

    Expected: Status: inactive on a fresh Ubuntu desktop. If it says active, allow SSH from your LAN, using your own range:

    bash
    sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp

Part 2: find the server's address ​

  1. On the server, run:

    bash
    hostname -I
    whoami

    Expected: the first address, such as 192.168.1.20, and your account name, such as maya. Write both down.

Part 3: read the host key on the server's own screen ​

  1. On the server, run:

    bash
    ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

    Expected: one line like 256 SHA256:L8BPGUED… root@maya-desktop (ED25519). Leave it on the screen.

    This is the fingerprint you got from a source you trust: the server itself, read with your own eyes, not over the network.

Part 4: connect and compare ​

  1. In SecureShell Go, tap +. In Add host, fill in:

    • Label (optional): Lab server
    • Host: 192.168.1.20
    • Port: 22
    • Username: maya

    Keep Password selected, type the account's password, and tap Save & connect.

  2. The Unknown host dialog appears. Check that Key type is ssh-ed25519, then compare its SHA256 fingerprint with the one on the server's screen, character by character.

    If the dialog shows another key type, read the matching file on the server instead, such as /etc/ssh/ssh_host_ecdsa_key.pub.

  3. If they match, tap Accept & save. If they do not, tap Reject and stop: something is wrong with the address or the network.

    Expected: the terminal opens with the server's prompt, such as maya@maya-desktop:~$.

  4. In the SecureShell Go terminal, run:

    bash
    hostname
    who

    Expected: the server's name, and a line for your session ending with your phone's or client's address in brackets, such as (192.168.1.35).

Part 5: switch to a key ​

  1. Tap Disconnect and confirm. On the host list, tap ⋮ next to Lab server and choose Edit.

  2. Under the sign-in choice, select Private key, then tap Generate new key.

    Expected: the New key generated dialog shows a public line starting with ssh-ed25519. Tap Done. The private key now fills Private key (PEM).

  3. Tap Save changes.

  4. Open the form again (⋮ › Edit) and tap Install public key on server…. Enter the account password and tap Install.

    Expected: Public key installed on the server.

  5. Tap Lab server to connect.

    Expected: the terminal opens without asking for a password.

  6. On the server's own terminal, look at what was added:

    bash
    tail -n 1 ~/.ssh/authorized_keys
    ls -ld ~/.ssh ~/.ssh/authorized_keys

    Expected: a line ending in secureshellgo@192.168.1.20, and the permissions drwx------ for the folder and -rw------- for the file.

Part 6: copy files both ways ​

  1. On the server, make a file to fetch:

    bash
    echo "Hello from the server" > ~/from-server.txt
  2. In the SecureShell Go session, tap Browse files. You start in your home folder on the server.

  3. Long-press from-server.txt and choose Download. When it finishes, tap Open in Transfers.

    Expected: the file opens on your phone and reads Hello from the server. It is saved in your device's Downloads.

  4. Tap Upload here and pick a small file from your phone, such as a photo.

  5. On the server, run:

    bash
    ls -l ~

    Expected: the file you uploaded is in the list.

Part 7: reach a mock API through a tunnel ​

Mock Studio's Todo API runs on the server at port 4010. You will reach it from the phone at localhost:14010, through SSH.

text
 Phone                                    Server 192.168.1.20
 ┌─────────────────────────┐              ┌─────────────────────────────┐
 │ browser or ApiWorkbench │              │                             │
 │  http://localhost:14010 │  SSH, port 22│ sshd ──► localhost:4010     │
 │        │                │═════════════►│          Mock Studio        │
 │ SecureShell Go listens  │              │          Todo API (sample)  │
 │ on 127.0.0.1:14010      │              │                             │
 └─────────────────────────┘              └─────────────────────────────┘
  1. On the server, open Mock Studio. Select Import, choose Mock Studio project file and pick todo-api.mockstudio.json. Select Start server.

  2. Check it on the server:

    bash
    curl http://localhost:4010/health

    Expected: a small JSON reply containing "status": "ok" and the current time.

  3. In SecureShell Go, tap the Tunnels button on the host list, then Add tunnel. Fill in:

    • Name: Todo mock
    • Carried by: Lab server
    • Type: Local forward
    • Local port: 14010
    • Destination host: localhost
    • Destination port: 4010

    Leave Allow other devices to use it off. Save.

  4. In the Tunnels list, switch Todo mock on.

    Expected: the tunnel starts and shows how many connections it carries.

  5. Open the phone's browser and go to http://localhost:14010/health.

    Expected: the same JSON as in step 2. In Mock Studio on the server, the request appears in Live.

  6. Optional: in ApiWorkbench on the phone, send a GET request to http://localhost:14010/health.

    Expected: 200 OK and the same body.

If the page does not load

Keep a terminal session to Lab server open in SecureShell Go while you test: with a session open, Android keeps the app running in the background. If localhost does not work in the browser, try http://127.0.0.1:14010/health. If the tunnel shows an error, set Destination host to 127.0.0.1.

Notice what happened: the phone talked to its own localhost. SecureShell Go carried the connection inside SSH, and the SSH server on the computer opened it to port 4010 there. To Mock Studio, the request came from the computer itself.

Break it, try it ​

Each of these shows one idea from the lessons. Put things back after each one.

Stop the tunnel. Switch Todo mock off and reload the page. The browser cannot connect at all: nothing on the phone listens on port 14010 now, so the connection is refused. Switch it back on.

Stop the mock. In Mock Studio, stop the server and reload the page, with the tunnel still on. The page still fails, even though the tunnel is running: the tunnel reached the computer, but nothing listened on port 4010 there. Start the server again.

Go direct, then close the door. In the phone's browser, open http://192.168.1.20:4010/health, without the tunnel. It works, because Mock Studio listens on all interfaces (lesson 1). Now, on the server, if sudo ufw status said inactive in part 1, turn on a firewall that allows only SSH from your LAN:

bash
sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp
sudo ufw enable

Reload the direct address: it now times out, because the firewall drops it silently. Reload http://localhost:14010/health: it still works. The firewall only lets in port 22, and the tunnel's traffic arrives inside SSH. You undo the firewall in the clean-up.

Forget the host key. On the host list, tap ⋮ › Forget host keys next to Lab server, then connect. The Unknown host dialog appears again: the app no longer trusts the server until you compare the fingerprint once more. Compare it with the server's screen and accept.

Optional: keys only, with a way back ​

This turns off password sign-in on the server (lesson 5). Your key from part 5 must work first, and you stay at the server's keyboard throughout, so you cannot lock yourself out.

  1. Keep a SecureShell Go session to Lab server open.

  2. On the server, create the settings file:

    bash
    printf 'PasswordAuthentication no\nKbdInteractiveAuthentication no\nPermitRootLogin no\n' | sudo tee /etc/ssh/sshd_config.d/10-keys-only.conf

    Expected: tee prints the three lines it wrote.

  3. Test the settings, then apply them:

    bash
    sudo sshd -t
    sudo systemctl restart ssh

    Expected: no output from either command. Your open session in SecureShell Go keeps working.

  4. Try a password sign-in from the server to itself:

    bash
    ssh -o PubkeyAuthentication=no maya@localhost

    The first time, ssh asks you to check the host key for localhost. It is the server's own key: compare it with part 3 and type yes.

    Expected: maya@localhost: Permission denied (publickey). Passwords are no longer accepted.

  5. In SecureShell Go, disconnect and connect to Lab server again.

    Expected: it connects with your key, as before.

To undo it:

bash
sudo rm /etc/ssh/sshd_config.d/10-keys-only.conf
sudo systemctl restart ssh

Clean up ​

Do these at the server's keyboard.

  1. In SecureShell Go, open Tunnels and switch Todo mock off, or tap Stop all.

  2. In Mock Studio, stop the server.

  3. If you turned on ufw in "Break it, try it", turn it off again:

    bash
    sudo ufw disable

    If ufw was already on before the lab, leave it on, and remove only the rule you added: sudo ufw status numbered shows each rule with a number, and sudo ufw delete followed by that number removes it.

  4. Remove the lab key from the server. First find it, then delete that line, keeping a backup:

    bash
    grep -n "secureshellgo@192.168.1.20" ~/.ssh/authorized_keys
    sed -i.bak '/secureshellgo@192.168.1.20/d' ~/.ssh/authorized_keys

    Expected: grep shows one numbered line. After sed, run the grep again: it prints nothing. When you are sure nothing else was removed, delete the backup with rm ~/.ssh/authorized_keys.bak. You can also delete the line by hand with nano ~/.ssh/authorized_keys.

  5. In SecureShell Go, tap ⋮ next to Lab server and choose Delete. In Delete host?, tick Also forget its trusted host key(s) and confirm. This removes the host, its saved password and its private key from your device.

  6. Delete the lab files on the server:

    bash
    rm ~/from-server.txt

    Delete the file you uploaded in part 6 too.

  7. If you do not need SSH on this computer, turn it off:

    bash
    sudo systemctl disable --now ssh.socket ssh.service

    On Ubuntu 22.04, use sudo systemctl disable --now ssh.

    Expected: ss -tln | grep ':22 ' prints nothing. If you keep SSH on, consider keeping the keys-only file from the optional part.

Check yourself ​

QuizLab: your own SSH server

Question 1 of 6

In part 4, why do you compare the fingerprint with ssh-keygen -lf run on the server's own screen?

Score: 0

What you learned ​

  • An SSH server on Ubuntu is one package, and ss -tln proves it is listening.
  • The host-key fingerprint is checked against the server's own screen, not the network.
  • A key installed in authorized_keys replaces the password, and deleting its line takes it away.
  • SFTP copies files both ways over the same connection.
  • A local forward reaches a service on the server through SSH, even when a firewall blocks the service's own port.

Next steps ​