How I configure sshd at home

My “server” at home isn’t particularly important to the outside world. But by virtue of being on the Internet, it’s subject to a lot of SSH logins. The easiest thing to do is to shut it off from the outside world. But I need to access it when away from home, so that’s not a particularly useful solution.

So what I’ve done is use the SSH daemon’s (sshd) configuration to reduce the risk profile. The first thing I wanted to do is forbid login as root:

PermitRootLogin no

I also don’t want anyone to be able to log in with passwords. “Anyone” is essentially me here, but since I have sudo on the box, if someone is able to figure out my password they are able to get root remotely.

PermitRootLogin no
ChallengeResponseAuthentication no

Finally, I want to restrict remote login to only explicitly-permitted users. I do this with a dedicated Unix group that I call “sshusers”.

AllowGroups sshusers

These are pretty standard changes and not really worth a blog post. But it turns out that sshd has a very flexible configuration. When a client is coming from inside the LAN, I want to enable password authentication. This is particularly helpful when I’m installing a new system and don’t have SSH keys setup yet.

Match Address 192.168.1.*
    PasswordAuthentication yes

Also within the LAN, it’s easier to run Ansible playbooks across machines if the root user can SSH in with a key. So I combine user and address matching to permit key-based root login only from the server with the Ansible playbooks.

Match User root Address 192.168.1.10
    AllowGroups root sshusers
    PermitRootLogin prohibit-password

Finally, I want my ex to be able to access the server in order to access photos, etc. So I set up her account so that she can use an sftp client but can’t log in (not that she would anyway, but it was a fun challenge to set this up).

Match User angie
    ForceCommand internal-sftp
    PasswordAuthentication yes
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no

Why didn’t you … ?

The configuration above isn’t the only way to secure my SSH server from the outside world. It’s not even necessarily the best. I could, for example, move SSH to a different port, which would cut down on the drive-by attempts significantly. I resisted that in the past because I felt “security through obscurity isn’t security.” But in practice, it can be a layer in a more secure approach. In the past, I also recall some clients I used (particularly on mobile) not having the ability to use a non-default port. If that recollection is correct, it seems to also be outdated now. So basically I’m still on port 22 because of inertia.

I could also set up a VPN server and use that for remote access. That requires an additional service to manage, of course. And it also presents challenges when I’m also connected to a work VPN server. The sshd configuration approach is a simpler way for my needs.

SSH login failures when you have too many keys

I recently had an interesting issue where I SSH login failures in to both work and personal servers. When I tried to log in, I’d immediately get

Received disconnect from w.x.y.z port 22:2: Too many
authentication failures for funnelfiasco
Authentication failed.

This was a surprise, because I hadn’t tried to log in for a while. Why would I get “too many authentication failures”? I knew we ran fail2ban on the work servers and I figured my web host used something like that, too, so I thought maybe something was triggering a ban.

I checked that there wasn’t something on my network that was generating SSH attacks. tcpdump didn’t show anything (whew!).

It turns out that the issue is due to how the SSH agent works. The SSH agent holds your SSH keys. This allows you to remote into a Unix server with a key without having to re-type your passphrase every time. This is really useful behavior, especially if you make remote connections regularly (whether directly SSHing or using something like git over SSH). But it has some behaviors that can cause problems.

By default, if you have an SSH agent running, it will send all of the keys in the agent, even if you’ve explicitly specified the identity to use. If you have more keys than the server’s MaxAuthTries setting, you may end up with too many login attempts before it gets to the one you want. If you don’t want this behavior, you can add IdentitiesOnly yes to your SSH config file.

Secure file transfer from (potentially) anonymous users

There are many cases in which you want to share files with someone “on the outside.”  While e-mail attachments can be useful, when the file sizes start to get large, it becomes more and more problematic.  Of course, if you only want to share files out, there’s the simple method of setting up a web server.  But what if you want to receive files from others?  That’s when it gets more complicated.  One option is to find code for a file uploader that runs on a website, but that’s a bit heavy.  What if you just want to receive a few large (or many small) files from a friend.  Perhaps you’re providing an off-site backup, or you really want to see the 15,000 pictures they took on their recent trip to Conway, Arkansas.  Either way, there’s a simple way to set up a place for friends to drop off your files, without having to set up a separate account for them, and without having to use the insecure File Transfer Protocol (FTP).

The first step is to create a generic user account that the outsiders will use.  In this case, we assume that you don’t want this account to have shell access in order to run commands, so we’ll use /sbin/nologin as the shell.  We’ll call the user ‘rsyncft’ (for “rsync file transfer”, although you could use whatever you want) and put the home directory in /var (again, you can put it wherever it makes sense for you).    When it’s all put together. the command to add the user will look something like this:

useradd -m -c "rsync user" -N -d /var/rsyncft -s /sbin/nologin rsyncft

After you’ve added the user, the next step is to add yourself to the ‘rsyncft’ group you’ve created.  This step is optional, but it will make it easier for you to get files in and out of the directory.  (See the sidebar about group membership for more discussion on this topic). Next, you need to make sure you’ve got the lim_rsync script.  I got this from some colleagues and have shared it on a previous post, but here it is again:

#!/bin/bash

PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
TERM='vt100'

# Make sure a command is specified (e.g. we're not trying to actually log in)
if [[ $SSH_ORIGINAL_COMMAND == "" ]]; then
 exit 1
fi

# Extract the first three bits of the command
TEST_COMMAND=`echo $SSH_ORIGINAL_COMMAND | awk -F" " '{ print $1 " " $2 }'`

# If rsync is called with "--server --sender", it means somebody is trying
# to remotely copy files from us.  Allow this.  Deny all others.
if [[ $TEST_COMMAND == "rsync --server" ]] || [[ $TEST_COMMAND == "/usr/local/bin/rsync --server" ]]; then
 exec $SSH_ORIGINAL_COMMAND
else
 exit 2
fi

The script should work on both Linux and Solaris.  I put it in /usr/local/bin, but you can put it anywhere you want, provided the rsyncft account can run it (but not write to it!)  The point of this script is to check to see if the connection is an rsync connection or not.  So how do we do this?  Well, the last step is to add your friend’s SSH public key (if you’re not sure what I’m talking about, see this post from the Standalone Sysadmin blog).  To do this, you’ll need to create the file ~rsyncft/.ssh/authorized_keys (you may need to create the .ssh directory, too) to include

command="/usr/local/bin/lim_rsync",no-pty,no-agent-forwarding,no-X11-forwarding,no-port-forwarding

Followed by the public key contents.  If you know where the connections will be coming from, you can further secure the key by including a from= option (e.g. from=”*.myemployer.com” or from=”192.168.1.10″).

That’s it for the setup, your friends can now copy files into your computer.  If you need to have multiple people connect, you can just add more keys to the authorized_keys file.  By playing with the directory permissions, you can also make sure that files can be read or only written, depending on what it is you’re trying to accomplish.  The people trying to connect to you will need to use SSH to make the rsync connection, like this:

rsync -e "ssh" file_to_copy rsyncft@your.computer.net:/var/rsyncft

Of course ‘your.computer.net’ should be replaced with the DNS name or IP address of your computer, and you’re free to use other options to rsync to modify the behavior.  Now what if you want potentially anonymous users to be able to give you files?  Perhaps you have some kind of scanner that runs on unmanaged machines in your department, and you need to collect the output.  In that case, you can just create an SSH key that has no passphrase and include the public key in rsyncft’s authorized_keys file and add the location of the private key to your ssh  command:

rsync -e "ssh -i /path/to/private_key" file_to_copy rsyncft@your.computer.net:/var/rsyncft

Sidebar: Being smart about group membership

When I wrote the first draft of this post, I suggested adding rsyncft to a group that you are a member of, for example “users”.  Fortunately, I realized before I published that this is a Very Bad Idea™.  If you were to do it this way, any group-writable files owned by this group could be modified.  This is a really terrible security risk.  A better alternative is to let useradd create a new group, and then add yourself to it.  Then only the files that you want to be available are.  A much heavier option would be to run this in a VM so that the outside user has no way to get to your files.  This is more secure, but overkill for most users, and a bit more difficult to setup (not to mention more of a system overhead).

Cyber security awareness month: Other uses for SSH

As I noted a few weeks ago, October is cyber security awareness month.  I’d planned on writing a big how-to for remotely and securely connecting to another computer, but time has escaped me, so what I’ll give here is the quick and dirty version, and trust that my readers can use Google to fill in the backstory.

Back in May, I wrote an article about using SSH as a proxy to help secure your web browsing when away from home.  SSH was designed primarily to provide shell (command line) access to remote machines using encryption and other features to prevent someone from eavesdropping, but it can be used to tunnel all kinds of other traffic.  For example, you can tunnel your Subversion version control over SSH, using the svn+ssh argument (e.g. svn co svn+ssh my_svn_files). Or you could tunnel your VNC (a remote desktop protocol) over an SSH connection.

Why would you want to tunnel VNC?  The first reason is that VNC by default passes all traffic in plain text, which means all of your keystrokes (read: passwords) are exposed.  By using an SSH tunnel, your session is encrypted. The second reason is that by using an SSH tunnel, you don’t have to open the firewall for the VNC port(s).

So how do you tunnel VNC, or another protocol?  The -L argument to SSH (or LocalForward in the config file) tells SSH to forward locally.  To tunnel to a VNC server running on display :1, you’d do something like:  ssh -L 5901:localhost:5901 username@my.server.org   and then point your VNC viewer to localhost:1.

In addition to interactive-type uses, SSH can be used for file transport as well.  The scp command copies files to and from a remote server in the same manner that the cp command works locally.  sftp can be used as a secure replacement for the FTP protocol (but there’s no provision for anonymous access).  And most importantly, the venerable rsync command can be used with SSH by specifying it as the argument to the -e flag (e.g. rsync -e “ssh” -av /some/local/directory username@my.server.org:/the/remote/directory).

So the moral of the story is: SSH can help keep you secure.

SOCKS it to me

(This is the first in a series of “there’s already a thousand other articles about this out there, but I’m writing my own so that I’ll have something to put on my blog” articles).

For security’s sake, some of the services I run in my department aren’t accessible off-campus, or even outside of my department’s subnets.  This is normally a good thing, but it can be a bit of a hassle sometimes.  If I’m at home and I want to check my Exchange e-mail with Entourage, or if I need to access my Samba server, I can always just fire up a VPN connection.  But if I need to play around with CUPS, and I’m not wired in to my department (say, for example, I’m sitting in a meeting and I want to get actual work done instead), then I’m just up a creek.  The VPN is at the University level, and I don’t really feel like letting the whole campus print to my printers.  We spend too much on printing anyway.

This is where SOCKS comes in.  SOCKS is a proxy protocol — instead of traffic going directly from a server to you, it goes through the proxy first.  SOCKS can be used to pass all kinds of traffic, but probably the most common use is to encrypt, hide, or otherwise mangle web traffic.

Some uses of SOCKS are completely honest, like my example above to access restriced resources when I’m away from my office.  Another reason to use SOCKS is if you’re on an untrusted network, like at a coffee house, and you don’t want anyone who is trying to snoop your network traffic to see what web pages you’re viewing.  A less noble case is tunneling your web traffic through somewhere else while you’re at work, thus allowing you to visit sites your boss would not approve of.  I suppose you could also use a SOCKS proxy to visit sites that the law would not approve of, but you’ll still get caught.

So I’ve gone on for over three hundred words so far, and I still haven’t said how you can actually do this.  As it turns out, it is surprisingly simple.  All you need is an SSH server, and SSH client, and a web browser.  The SSH server runs on whatever you want to use as a proxy, in this case my Linux desktop at work.  The SSH client and web browser run on the computer you’re using to surf ye olde intertubes.  (If you’re using Linux or Mac OS X, you’ve probably already got the SSH client and SSH server available, but you might have to get it started.  Windows users will need Cygwin or something similar.  In any case, Google is your friend).

To get started, just make an SSH connection to your proxy host.  Something like

   ssh -ND 8120 bcotton@host.department.employer.edu

will do quite nicely.  The “-ND” option does not mean to root for Notre Dame.  Do not do that under any circumstances.  “N” tells SSH not to run a command, so you won’t get a command line, which in this case is fine.  “D” specifies the local port to use.  I chose 8120, but you can choose pretty much whatever you want between 1025 and 65535.  The important thing is to remember it.  The rest is your username and then the server you want to connect to.

Okay, so now you’ve got the connection set up.  The next thing to do is to tell your browser to use it.  Firefox users, go to Preferences and select the “Advanced” tab.  Next, select the “Network” section.  You’ll see a line that reads “Configure how Firefox connects to the internet.”  Click on the “Settings” button next to that.  Select the “Manual Proxy Configuration.”  In the box labeled “SOCKS Host” enter “localhost” and in the “Port” box next to that, enter the port you chose when you set up your SSH connection.  Click “OK” and then you’re done.

If you did it right, you’re now sending all of your web traffic through the proxy.  Well done!

Securing your SSH keys

My ones of readers may recall that I’ve mentioned “Standalone Sysadmin” by Matt Simmons as one of my favorite blogs.  On Friday, he published a great introduction to SSH keys.  He covered how to set up keys and use them.  One aspect that deserves further coverage, though, is securing your keys.  Sure, a good passphrase will do a lot to keep your key from being used by the bad guys.  But what happens if you have a phraseless key?  It’s a bad idea for interactive use, but for automated tasks, it is nearly a requirement (unless you manually start the SSH agent).  So how can you minimize your risk? Continue reading