1

I have a linux host with openssh that permits users to login with public key.

AuthenticationMethods publickey

But now I have some users who will need to access the host as a file drop using sftp. In addition, these users will user passwords rather than key pairs.

I make all of these users belong to the group sftp_users.

an_sftp_user@myhost.example.com:~$ id
uid=1005(an_sftp_user) gid=1007(an_sftp_user) groups=1007(an_sftp_user),1006(sftp_users)
an_sftp_user@myhost.example.com:~$ groups
an_sftp_user sftp_users
an_sftp_user@myhost.example.com:~$

Now I create the file /etc/ssh/sshd_config.d/sftp_users.conf owned by root, 0644:

Match Group sftp_users
  X11Forwarding no
  AllowTcpForwarding no
  AuthorizedKeysCommand /bin/true
  AuthenticationMethods keyboard-interactive
  PasswordAuthentication yes
  ChrootDirectory /sftp-incoming

What I want this to do is to permit users in the group sftp_users to be able to connect with password and access /sftp-incoming.

What actually happens is that I see a message server side in auth.log that says merely that the connection was closed and, client side, I see (using sftp -v) that it tries the certificates it finds in $HOME/.ssh (I've disabled my ssh-agent for these tests) but never tries password login.

Indeed, one line is this:

debug1: Authentications that can continue: publickey

So somehow my Match is not being satisfied or not being seen. But I'm unclear why.

Any suggestions where I've gone wrong?

Update

The solution from @Gogowitsch largely answers this, especially the note that sftp-internal is, well, internal to openssh and so doesn't need a binary to be available in my chroot jail. Also important was to discover that chroot requires that the chain of directories be 0755 root all the way down, so I had to sort some permissions.

His suggestion to put the config all in the one sshd_config file was also helpful. Indeed, once it was working, moving that block back to a config file and using Include to include it fails without error. The block simply isn't used. I'm using 8.2:

OpenSSH_8.2p1 Ubuntu-4ubuntu0.1, OpenSSL 1.1.1f  31 Mar 2020

which claims to support Include (present since 7.3p1 and apparently committed on 1 Feb 2020 (prior to 31 Mar 2020).

1
  • Idea: You could use a second SSH daemon running on the same host, but with a different port. One allows password-based login, the other doesn't. Then tell each user which port they should used based on their preferred authentication method.
    – Gogowitsch
    Feb 25 '21 at 20:59
2

I see these immediate issues:

  • The order of directives. Try putting the Match Group sftp_users at the very end of the file /etc/ssh/sshd_server instead of a file in the sshd_server.d. This is because the last AuthenticationMethods seems to win.
  • The AuthenticationMethods should contain password. This is apparently what allows the password login.
  • When using the ChrootDirectory directive, you also have to use the following line within your Match Group sftp_users block:
    ForceCommand internal-sftp
    
    This is because the /sftp-incoming becomes the actual root of the file system to all commands. By default, the SSH server attempts to run a binary such as /usr/lib/openssh/sftp-server. From the perspective of the chroot'ed filesystem, there probably isn't any such file.

Potentially, you'll also have to run the following command to make sure that the /sftp-incoming directory cannot be accessed by 'other' (the last digit in the octal 0750):

chmod 0750 /sftp-incoming

As an experimental setup, I used the following Dockerfile:

FROM ubuntu

RUN apt-get update && \
    apt-get install -yq openssh-sftp-server openssh-server

# Create two users, first has no password, second has the password "1".
# This will also create the home directory for the sftp user.
RUN echo | adduser only-passwordless-user && \
    echo | adduser only-with-password-user --home /sftp-incoming/only-with-password-user && \
    echo only-with-password-user:1 | chpasswd && \
    addgroup sftp_users && \
    adduser only-with-password-user sftp_users

# These are needed so that sshd is happy. Otherwise,
# it likes to say “bad ownership or modes for chroot directory”
RUN mkdir -p -m0755 /var/run/sshd && \
    chown root:root /sftp-incoming && \
    chmod 0750 /sftp-incoming

RUN echo AuthenticationMethods publickey >> /etc/ssh/sshd_config && \
    printf "Match Group sftp_users                                \n\
            ForceCommand internal-sftp                            \n\
            X11Forwarding no                                      \n\
            AllowTcpForwarding no                                 \n\
            AuthorizedKeysCommand /bin/true                       \n\
            AuthenticationMethods keyboard-interactive password   \n\
            PasswordAuthentication yes                            \n\
            ChrootDirectory /sftp-incoming                        \n\
           " >> /etc/ssh/sshd_config  # cannot be ".d/sftp_users.conf"

# Start a single-connection debug server.
# Remove the -d parameter to make it long-lived but quiet.
ENTRYPOINT /usr/sbin/sshd -d

You can start a sshd running on port 2200 using this command:

docker build . -t ssh-test && docker run -it --name ssh-test -p2200:22 --rm ssh-test bash

To connect to it using sftp, run this:

sshpass -p1 sftp -P 2200 only-with-password-user@127.0.0.1
1
  • Thanks, that largely got me out of this. The odd thing is that putting the (revised) block in sshd_config works, but using Include does not.
    – jma
    Feb 26 '21 at 20:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.