On Sat, 11 Nov 2023, Bob Proulx wrote:> I am supporting a site that allows members to upload release files. I > have inherited this site which was previously existing. The goal is > to allow members to file transfer to and from their project area for > release distribution but not to allow general shell access and not to > allow access to other parts of the system. > > Currently rsync and old scp has been restricted using a restricted > shell configuration. But of course that does not limit sftp. And of > course sftp can be chrooted which would work okay for us. Use the > ForceCommand internal-sftp configuration to put the process in a > chroot. But then that configuration blocks rsync. > > Match ... other stuff > Match ALL > ChrootDirectory /releases > ForceCommand internal-sftp > AllowTcpForwarding no > X11Forwarding no > > I have not been able to deduce a way to set up sftp-in-a-chroot *only* > when sftp is requested and allow rsync when rsync is requested and > allow rsync to work normally when rsync is requested.You can do this using a custom setuid shell or forcecommand (it needs to be setuid because chroot requires privileges). It can look at the contents of $SSH_ORIGINAL_COMMAND and decide on whether to run rsync or chroot then run sftp-server. It is possible to do this without setuid, but the forcecommand would need to live inside the ChrootDirectory along with everything else sftp-server and rsync needs. If you're on Linux, then maybe you could cook something up using namespaces and bind mounts to simplify this. -d
On 12.11.23 03:52, Damien Miller wrote:> On Sat, 11 Nov 2023, Bob Proulx wrote: > >> I am supporting a site that allows members to upload release files. I >> have inherited this site which was previously existing. The goal is >> to allow members to file transfer to and from their project area for >> release distribution but not to allow general shell access and not to >> allow access to other parts of the system. >> >> Currently rsync and old scp has been restricted using a restricted >> shell configuration. But of course that does not limit sftp. And of >> course sftp can be chrooted which would work okay for us. Use the >> ForceCommand internal-sftp configuration to put the process in a >> chroot. But then that configuration blocks rsync. >> >> Match ... other stuff >> Match ALL >> ChrootDirectory /releases >> ForceCommand internal-sftp >> AllowTcpForwarding no >> X11Forwarding no >> >> I have not been able to deduce a way to set up sftp-in-a-chroot *only* >> when sftp is requested and allow rsync when rsync is requested and >> allow rsync to work normally when rsync is requested. > You can do this using a custom setuid shell or forcecommand (it needs > to be setuid because chroot requires privileges). It can look at > the contents of $SSH_ORIGINAL_COMMAND and decide on whether to run > rsync or chroot then run sftp-server. > > It is possible to do this without setuid, but the forcecommand would > need to live inside the ChrootDirectory along with everything else > sftp-server and rsync needs. > > If you're on Linux, then maybe you could cook something up using > namespaces and bind mounts to simplify this.A while ago I used the following bubblewrap-based login shell to implement said Linux namespace and bind mount solution to give restricted shell access to a mostly trusted user. Using bwrap saves the perilous trouble of writing a safe setuid solution yourself. Could be extended by looking at $SSH_ORIGINAL_COMMAND to get the sftp/rsync behavior you're looking for. Obviously, no guarantees about its safety. For example, a "Subsystem sftp" directive in the sshd_config will bypass the login shell, IIRC. Best regards, Carsten --- #!/bin/bash set -euo pipefail (exec bwrap \ ?? ???? --ro-bind /bin /bin \ ?? ???? --ro-bind /usr /usr \ ?? ???? --ro-bind /lib /lib \ ?? ???? --ro-bind /lib64 /lib64 \ ?? ???? --dir /home \ ?? ???? --dir /run/user/$(id -u) \ ?? ???? --dir /tmp \ ?? ???? --dir /var \ ?? ???? --symlink ../tmp var/tmp \ ?? ???? --bind /home/user /home/user \ ?? ???? --proc /proc \ ?? ???? --dev /dev \ ?? ???? --chdir /home/user \ ?? ???? --unshare-all \ ?? ???? --file 11 /etc/passwd \ ?? ???? --file 12 /etc/group \ ?? ???? --file 13 /etc/bash.bashrc \ ?? ???? --file 14 /etc/hostname \ ?? ???? --file 15 /etc/localtime \ ?? ???? --file 16 /etc/nsswitch.conf \ ?? ???? --file 17 /etc/profile \ ?? ???? /bin/bash "$@" ?? ?) \ ?? ?11< <(getent passwd $UID 65534) \ ?? ?12< <(getent group $(id -g) 65534) \ ?? ?13< <(cat /etc/bash.bashrc) \ ?? ?14< <(cat /etc/hostname) \ ?? ?15< <(cat /etc/localtime) \ ?? ?16< <(cat /etc/nsswitch.conf) \ ?? ?17< <(cat /etc/profile)
TL;DR: I'll jump down the rabbit hole of creating a ForceCommand which does the chroot selection itself or not. Thanks! Damien Miller wrote:> Bob Proulx wrote: > > Match ALL > > ChrootDirectory /releases > > ForceCommand internal-sftp > ... > You can do this using a custom setuid shell or forcecommand (it needs > to be setuid because chroot requires privileges). It can look at > the contents of $SSH_ORIGINAL_COMMAND and decide on whether to run > rsync or chroot then run sftp-server.The problem I hit with that idea is that then the chroot requires a full chroot system setup rather than the internal-sftp which works internally and does not require the full chroot environment. The shared libraries needed is not too much issue but the user accounts are kept in an SQL datbase so wiring that it seemed messy. That's the reason I was trying to deduce a method to use "ForceCommand internal-sftp" which works directly. I have entertained the idea of splitting the host into two hosts. One would have an IP address for sftp and the other would have an IP address for rsync and the two would not need to overlap. That's a possibility because the host size could be very small. If this were a *BSD system I would use a vnet jail. This is a Linux system. (Maybe this will be the motivation for me to learn Linux containers.)> It is possible to do this without setuid, but the forcecommand would > need to live inside the ChrootDirectory along with everything else > sftp-server and rsync needs.The setuid requirement itself is not a problem. The attraction of internal-sftp is that it is already there and already self-contained. The problem of needing the user account database in the chroot makes doing it without internal-sftp to be messy. Though maybe I have avoided it too quickly and should just work the problem and see. I am going to jump into this rabbit hole and see what I find there. Though I am torn between it and the brute force idea of splitting the host into separate sftp and rsync dedicated transfer ones. But then people would need to be switched from one dns name which I am sure they have coded to another that they would need to learn. I'll jump into the ForceCommand handler for a bit and see what I learn by working that side of the problem.> If you're on Linux, then maybe you could cook something up using > namespaces and bind mounts to simplify this.I neglected to say one more thing that figures into the problem. The storage space is on an NFS mount. Which honestly has more benefits than problems. There are several hosts that share the storage space. This does not prevent doing clever things. But it can make things more interesting. If possible keeping things simple and plain is my goal. Thanks! Bob