From the Terminal
I recently wanted to share a bunch of files with a friend over the internet. These files were on my mediacenter which is a Windows machine running a RAID. This machine was already sharing these files on a Windows file share but I didn't want to expose these files to the internet. Since my workstation was a Linux box already running SSH server on port 22 with SSH key authentication already working I figured the cleanest thing would be to add a new user and set the home directory to the network share with the shell disabled. Easier said than done so I'm writing this post to discuss some blockers I encountered and how I solved them.
First I needed to add a new user. This is the command I used in Gentoo however in most Linux distros you will likely need to use adduser instead.
sudo useradd ftp -M -N -s /sbin/nologin -R /dev/null
- -M Don't create a home directory
- -N No user group
- -s /sbin/nologin sets the shell to nologin to disable any logins
- -R /dev/null sets the home directory to /dev/null to disable the home directory
Now we need to edit sshd_config for this specific user.
Near the bottom of the file we add this to the config.
Match User ftp AuthorizedKeysFile /etc/ssh/authorized_keys_%u ForceCommand internal-sftp AllowTCPForwarding no X11Forwarding no ChrootDirectory /home/ftp
Since the AuthorizedKeysFile depends on having a home directory by default we must override that setting to specify a different one for just this one user. Configure that as you would normally.
For security reasons we disable AllowTCPForwarding so people can't use your SFTP as a free proxy and X11 forwarding so that people can't access your X session. Finally we need to use a chroot directory.
My initial instinct was to directly use my media center mount as /mnt/mediacenter/ but this was failing since that directory was a network share. SFTP server requires that the chroot directory is owned by root. So despite us setting this user to not use a home directory I decided to use /home/$user for that reason anyway. But in this case I set it as owned by root instead of the user like normal. Now I had to setup some link to the mediacenter mount. Soft links will not work with SFTP so instead I used the mount command like so.
sudo mount --bind /mnt/mediacenter/Library/Anime/ /home/ftp/Anime
Now we can test it. I decided to use my laptop.
There you have it. A fully secure SFTP over SSH.
This technique should work well with WSL1 and WSL2 as well if you're using Windows.
With OpenSSH, port forwarding is configured using the -L option.
You can initiate a port forwarding operation with this command:
ssh -L 80:example.com:80 technex.us
In this example we are telling OpenSSH to open port 80 on the current machine to example.com on port 80 from the server we are connecting to. In this case the server is technex.us.
Don't forget that anyone can connect to this port on your machine so you might want to limit connects to localhost by telling OpenSSH to listen on a specific IP. In this case you can specify 127.0.0.1 like so:
ssh -L 127.0.0.1:80:example.com:80 technex.us
Since this is OpenSSH you can actually use the alias you specified in your ~/.ssh/config file.
I talk more about the OpenSSH config file here.
Building on top of that guide if you want to maintain a port forward everytime you connect to a specific machine you can use this syntax:
Host alias HostName technex.us User user IdentityFile /Users/user/.ssh/mykey_rsa LocalForward 127.0.0.1:80 example.com:80
Now you can simply type in ssh alias in terminal and be connected with a port forward.
If you're like me you need to login to multiple servers via SSH on a daily basis. For many years when I was younger I typed in the whole IP or hostname of a server everytime I wanted to login to that server. After learning how to use the ssh config file logging into your SSH machine can be cut down to just a few keystrokes.
The SSH config file is always in ~/.ssh/config
Here's a template you can use.
Host alias HostName example.com User user IdentityFile /Users/user/.ssh/mykey_rsa
You can create as many entrees in the file as you like.
- Hostname can be a DNS resolved domain name or an IP address but that is what SSH will try to actually connect to.
- Host is actually just the name of this entry in this case I used "alias".
- User when you type in the SSH command in terminal you can specify a user like normal but if you don't it will use the option you put in
- IdentityFile is an optional setting to specify your private key SSH key.
When I type in ssh alias in the terminal it will simply connect to example.com as user.
Here's an example
Host henryparadiz.com hp Hostname henryparadiz.com User henry IdentityFile /Users/henry/.ssh/personal_rsa
henry@Coder-Laptop:~$ ssh hp Enter passphrase for key '/Users/henry/.ssh/personal_rsa': Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-116-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage 23 packages can be updated. 13 updates are security updates. Last login: Mon Apr 16 05:26:15 2018 from 127.0.0.1
Notice how I use the second alias under the host option simply "hp" which allows me to shorten the entire command to just the above. Easy and simply way to speed up your development.