12

I need to perform backup of a server to my computer using Duplicity:

duplicity /etc sftp://[email protected]//home/backup

Before this can be done, I need to allow password-less access by doing the following:

$ ssh-keygen
$ ssh-copy-id [email protected]
$ ssh [email protected]

My question is, how do I restrict the command to just this SFTP transfer in the public key that is generated?

command="restrict to sftp",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA…

And since I am on a dynamic IP address, how do I overcome the "missing known host" problem each time my IP changes?

3

2 Answers 2

16

Question #1

My question is, how do I restrict the command to just this SFTP transfer in the public key that is generated?

There are 2 methods for doing this.

1. -- Restricting through sshd

This method involves setting up the SFTP feature within your SSH daemon, sshd. This is controlled through the /etc/ssh/sshd_config configuration file. NOTE: This will restrict the user, backup to only be allowed to SFTP into the server.

# /etc/ssh/sshd_config

Subsystem       sftp    internal-sftp

## You want to put only certain users (i.e users who belongs to sftpusers 
## group) in the chroot jail environment. Add the following lines at the end 
## of /etc/ssh/sshd_config

Match User backup
  ForceCommand internal-sftp

2. -- Restricting through authorized_keys

This method doesn't involve any changes to the sshd_config file. You can limit a user + a SSH key to a single command via the command= feature which you've already mentioned in your question. The trick is in what command you include. You can put the SFTP server in this command= line, which has the same effect as setting up the SFTP server in your sshd_config file.

# User backup's $HOME/.ssh/authorized_keys file
command="/usr/libexec/openssh/sftp-server" ssh-dss AAAAC8ghi9ldw== backup@host

NOTE: if the user has write access to ~/.ssh/authorized_keys, they can read and/or modify it. For example, they could download it, edit it, and reupload it stripping away the commmand=..., granting him unfettered command access, including the shell. If the user has write access to ~/.ssh, they could also simply unlink and recreate the file, or chmod it to write access. Many possible solutions exist, such as putting the ~/.ssh/authorized_keys files away in a non-user-writable place, such as with:

Match Group sftponly
    AuthorizedKeysFile      /etc/ssh/authorized_keys/%u

Question #2

And since I am on a dynamic IP address, how do I overcome the "missing known host" problem each time my IP changes?

This is trickier but doable using the from= feature within the authorized_keys file as well. Here we're limiting access from only the host, somehost.dyndns.org.

from="somehost.dyndns.org",command="/usr/libexec/openssh/sftp-server",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-dss AAAAC8ghi9ldw== backup@host

The additional settings after the command= are equally important, since they'll limit the use of SSH key even further.

breakdown of features

  • from='hostname1,hostname2,'' - Restricts access from the specified IP or hostname patterns
  • command='command' - Runs the specified command after authentication
  • no-pty - Does not allocate a pty (does not allow interactive login)
  • no-port-forwarding - Does not allow port forwarding
  • no-X11-forwarding - user won't be able to remove display X11 GUIs
  • no-agent-forwarding - user won't be able to forward through this host to other internal hosts

To get rid of the message about the "missing known hosts" you can add this SSH option to the client when it connects like so:

$ ssh -o StrictHostKeyChecking=no ....

See the man page, ssh_config for full details about this switch.

Restricting the user's shell

For both solutions above you'll likely want to lock down the backup user by limiting this user's shell in the /etc/passwd file as well. Typically you'll want to set it to scponly, but there are other choices for this as well. See this U&L Q&A titled: "Do you need a shell for SCP?" for ways of doing this.

The use of /sbin/nologin can also be used if you opt to use the chroot feature from sshd_config as outlined in #1 above. However if you opt to use the method outlined in #2, then you'll likely have to use scponly or something else for the user's shell in /etc/passwd.


BONUS - Extending #2 above

If you need to expose a set of commands for this user you can also do this. Create a script like so, /home/backup/commands.sh:

#!/bin/sh

case $SSH_ORIGINAL_COMMAND in
  "diskspace")
    df -h
    ;;
  "dirlist")
    ls -1
    ;;
  "apache_restart")
    /etc/init.d/apache restart
    ;;
  *)
    echo "Unknown command"
esac

You then setup the authorized_keys file like so:

command="/bin/sh /home/user/commands.sh" ssh-dss AAAAC8ghi9ldw== user@host

The backup user can then run these commands like so:

# diskspace
$ ssh -q user@remote_host diskspace
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/dev-root   39G  2.2G   35G   6% /

# dirlist
$ ssh -q remote_host dirlist
commands.sh
dump.sql

References

8
  • 2
    Be careful of what commands you allow the user to access or the user may have the ability to gain a full shell. As an example, if you give someone access to vim they could easily :!/bin/bash or :!/bin/someotherprogram.
    – rking
    Jan 26, 2014 at 2:06
  • @rking - yes that goes without saying...
    – slm
    Jan 26, 2014 at 2:07
  • Thanks for giving me such a detailed answer. The command restriction works perfect. But there are two problems. 1) The dynamic ip refers to my computer, not the server. The hostnames in the "from" field of the authorized_keys file only restrict the address from which the server can access my computer and does nothing to solve the "missing known host" problem on my computer. 2) Disabling shell login for the backup user on my computer with /sbin/nologin will prevent the server from accessing my computer with SFTP. This I tried. Jan 26, 2014 at 8:35
  • 1
    Sorry for the confusion. The server S becomes the client when it does the backend SFTP connection to my computer C. The "missing known host" problem occurs whenever the server S doing the backup connects to a location not listed on its ssh known_hosts file. Marki provided the correct solution in his comment. The from parameter in the authorized_keys file on my computer C only restricts the location from which S can connect to C. Jan 27, 2014 at 6:58
  • Yes, please go ahead to make the edit. By the way I realize that /sbin/nologin works if I use force command internal-sftp instead of /usr/libexec/openssh/sftp-server which you have specified on the cert. I guess these are two different subsystems. And creating a chroot directory for the former is much more straight forward. Jan 27, 2014 at 10:28
0

Restricted Shell

You need to assign a restricted shell such scponly or rssh.

When you use scp or sftp you are connecting to the remote site over ssh and then the remote shell executes a scp proccess or sftp process. What you need is a restricted shell that only allows scp or sftp to lock down the login.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .