SFTP用户权限配置
2023年9月20日大约 14 分钟
SFTP用户权限配置
新增用户组及用户
进入root用户权限下进行操作
mkdir -pv /www/wwwtest/{admin,user1,user2}
#新增用户组
groupadd sftpadmins
groupadd sftpusers
#查看所有群组
cat /etc/group
#查看群组下用户
groups sftpadmins
#删除群组
groupdel sftpadmins
#[useradd]新增用户admin,属于用户组sftpadmins
#账号的shell使用 /sbin/nologin ,此时无法SSH登陆系统
#如果需要ssh登录 则设置为 /bin/bash
useradd -g sftpadmins -s /sbin/nologin -d /www/wwwtest/admin admin
passwd admin
admin
##新增用户user1、user2,属于用户组sftpusers
useradd -g sftpusers -s /sbin/nologin -d /www/wwwtest/user1 user1
passwd user1
user1
useradd -g sftpusers -s /sbin/nologin -d /www/wwwtest/user2 user2
passwd user2
user2
#查看所有用户
cat /etc/passwd
配置sshd_config
# 编辑配置文件
vi /etc/ssh/sshd_config
Port 35021 #默认ssh端口号为22,生产环境中建议改成五位数的端口
Subsystem sftp internal-sftp #指定使用sftp服务使用系统自带的internal-sftp
# 如果用户需要ssh登录无需设置下面配置,并且用户shell需要设置为/bin/bash
#配置用户组sftpadmins
Match Group sftpadmins
#ChrootDirectory /www/wwwtest
ChrootDirectory %h #用户通过sftp登录后就把根目录切换到它自己的家目录
ForceCommand internal-sftp #指定sftp流程,此方法性能更优
AllowTcpForwarding no #禁止[TCP](https://www.cnblogs.com/zqifa/p/ssh-2.html)转发
X11Forwarding no #禁止X11转发
#配置用户组sftpusers
Match Group sftpusers
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
更改配置后重启sshd服务
service sshd restart
测试:用户只能sftp登录,不能ssh
#sftp登录成功
root@local:~# sftp -oPort=35021 admin@10.211.55.252
admin@10.211.55.252's password:
Connected to 10.211.55.252.
root@local:~# sftp -oPort=35021 user1@10.211.55.252
user1@10.211.55.252's password:
Connected to 10.211.55.252.
root@local:~# sftp -oPort=35021 user2@10.211.55.252
user2@10.211.55.252's password:
Connected to 10.211.55.252.
# ssh登录失败
root@local:~# ssh -oPort=35021 admin@10.211.55.252
admin@10.211.55.252's password:
This service allows sftp connections only.
Connection to 10.211.55.252 closed.
root@local:~# ssh -oPort=35021 user1@10.211.55.252
user1@10.211.55.252's password:
This service allows sftp connections only.
Connection to 10.211.55.252 closed.
root@local:~# ssh -oPort=35021 user2@10.211.55.252
user2@10.211.55.252's password:
This service allows sftp connections only.
Connection to 10.211.55.252 closed.
修改用户权限
# 建议设置为700 一开始就设置好,后期修改,会导致后面命令需要重新设置
chown -R admin:sftpadmins /www/wwwtest/admin
chmod 700 /www/wwwtest/admin #只能自己访问所属目录
chown -R user1:sftpusers /www/wwwtest/user1
chmod 750 /www/wwwtest/user1 #同组也能访问,但不能写
chown -R user2:sftpusers /www/wwwtest/user2
chmod 755 /www/wwwtest/user2 #不同组也可访问,但不能写
测试:admin用户功能
root@local:~# sftp -oPort=35021 admin@10.211.55.252
admin@10.211.55.252's password:
Connected to 10.211.55.252.
sftp> cd admin
sftp> ls
admin.txt
#在所属目录下测试文件上传
sftp> put -r /local/upload.txt /admin
Uploading /local/upload.txt to /admin/upload.txt
/local/upload.txt 100% 21 0.0KB/s 00:00
sftp> ls
admin.txt upload.txt
#在所属目录下测试文件下载
sftp> get admin.txt /local
Fetching /admin/admin.txt to /local/admin.txt
/admin/admin.txt 100% 15 0.0KB/s 00:00
#访问user1文件夹,无读写权限
sftp> cd ../user1
sftp> ls
remote readdir("/user1"): Permission denied
#访问user2并测试文件上传、下载
#只能读不能写
sftp> cd ../user2
sftp> ls
user2.txt
sftp> put -r /www/wwwtest/upload.txt /user2
Uploading /www/wwwtest/upload.txt to /user2/upload.txt
remote open("/user2/upload.txt"): Permission denied
sftp> get user2.txt /local
Fetching /user2/user2.txt to /local/user2.txt
/user2/user2.txt 100% 15 0.0KB/s 00:00
测试:user2用户功能
root@local:~# sftp -oPort=35021 user2@10.211.55.252
user2@10.211.55.252's password:
Connected to 10.211.55.252.
#访问admin,没有读写权限
sftp> cd ../admin
sftp> ls
remote readdir("/admin"): Permission denied
#访问user1并测试文件上传、下载
#只能读不能写
sftp> put -r /www/wwwtest/user2/user2.txt /user1
Uploading /www/wwwtest/user2/user2.txt to /user1/user2.txt
remote open("/user1/user2.txt"): Permission denied
sftp> get user1.txt /user2.txt
Fetching /user1/user1.txt to /user2.txt
/user1/user1.txt 100% 13 0.0KB/s 00:00
需求:实现以下功能
模仿系统管理员和普通用户:admin和user两个用户组,能否实现admin组用户可以读写sftp根目录下所有文件,而user组用户只能对自己的目录只读。
分析:涉及到多个文件隶属于一个用户组,需要使用ACL命令
首先chmod给出基本权限
chmod 770 /www/wwwtest/admin #只能自己读写所属目录
chmod 500 /www/wwwtest/user1 #只能自己读所属目录
chmod 500 /www/wwwtest/admin #只能自己读所属目录
查看当前文件所属及权限
root@local:/www/wwwtest# ll
总用量 20
drwxr-xr-x 5 root root 4096 9月 5 09:12 ./
drwxr-xr-x 3 root root 4096 9月 5 08:31 ../
drwxrwx--- 2 admin sftpadmins 4096 9月 5 20:12 admin/
dr-x------ 2 user1 sftpusers 4096 9月 5 19:57 user1/
dr-x------ 2 user2 sftpusers 4096 9月 5 19:58 user2/
接下来进行ACL权限管理,使用setfacl命令
可以对每一个文件或目录设置更精确的文件权限
setfacl用法
#用法: setfacl [-bkndRLP] { -m|-M|-x|-X ... } file ...
-m, --modify-acl #更改文件的访问控制列表
-M, --modify-file=file #从文件读取访问控制列表条目更改
-x, --remove=acl #根据文件中访问控制列表移除条目
-X, --remove-file=file #从文件读取访问控制列表条目并删除
-b, --remove-all #删除所有扩展访问控制列表条目
-k, --remove-default #移除默认访问控制列表
--set=acl #设定替换当前的文件访问控制列表
--set-file=file #从文件中读取访问控制列表条目设定
--mask #重新计算有效权限掩码
-n, --no-mask #不重新计算有效权限掩码
-d, --default #应用到默认访问控制列表的操作
-R, --recursive #递归操作子目录
-L, --logical #依照系统逻辑,跟随符号链接
-P, --physical #依照自然逻辑,不跟随符号链接
--restore=file #恢复访问控制列表,和“getfacl -R”作用相反
--test #测试模式,并不真正修改访问控制列表属性
-v, --version #显示版本并退出
-h, --help #显示本帮助信息
#临时开启根分区 ACL 权限
mount -o remount,acl /
#设置sftpadmins组在admin,user1、user2的权限为rwx
setfacl -m g:sftpadmins:rwx /www/wwwtest/admin
setfacl -m g:sftpadmins:rwx /www/wwwtest/user1
setfacl -m g:sftpadmins:rwx /www/wwwtest/user2
#让其他用户组对某个用户的目录有读写权限
setfacl -R -m g:sftpusers:rwx /www/wwwtest/user1
#让用户对自己的目录有读写权限
setfacl -R -m u:admin:rwx /www/wwwtest/admin
setfacl -R -m u:user1:rwx /www/wwwtest/user1
setfacl -R -m u:user2:rwx /www/wwwtest/user2
#让nginx可以读写,对网站进行部署
setfacl -R -m u:www:rwx /www/wwwtest/user1
#使用getfacl命令查看目录的acl权限
root@local:/# getfacl /www/wwwtest/user1
getfacl: 从绝对路径名尾部去除" / "字符。
# file: www/wwwtest/user1 #这三行为所属组信息
# owner: user1
# group: sftpusers
user::r-x #这六行为相应acl权限信息
user:admin:rwx
group::---
group:sftpadmins:rwx
mask::rwx
other::---
取消 ACL 权限
- 取消特定用户或组的 ACL 权限:
setfacl -x u:user2 /www/wwwtest/user1
setfacl -x g:sftpusers /www/wwwtest/user1
setfacl -x g:sftpadmins /www/wwwtest/user1
- 取消所有用户和组的 ACL 权限:
setfacl -b /www/wwwtest/user1
测试功能
#admin可访问user1、user2
root@local:/# sftp -oPort=35021 admin@10.211.55.252
admin@10.211.55.252's password:
Connected to 10.211.55.252.
sftp> cd user1
sftp> ls
user1.txt
sftp> cd ../user2
sftp> ls
user2.txt
#user2不可以访问admin、user1
root@local:/# sftp -oPort=35021 user2@10.211.55.252
user2@10.211.55.252's password:
Connected to 10.211.55.252.
sftp> cd ../user1
sftp> ls
remote readdir("/user1"): Permission denied
sftp> cd ../user1
sftp> ls
remote readdir("/user1"): Permission denied
限制SSH用户访问特定目录
方法1:
mkdir -p /www/wwwtest/user3
#创建用户
useradd -s /sbin/nologin -d /www/wwwtest/user3 user3
passwd user3
#配置sshd_config
vi /etc/ssh/sshd_config
Port 35021 #默认ssh端口号为22,生产环境中建议改成五位数的端口
Subsystem sftp internal-sftp #指定使用sftp服务使用系统自带的internal-sftp
#配置用户组sftpadmins
Match User user3
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
# 目录授权
chown -R root:root /www/wwwtest/user3
chmod 755 /www/wwwtest/user3
# 创建一个可读写根目录
mkdir -p /www/wwwtest/user3/www
chown -R user3:user3 /www/wwwtest/user3/www
chmod -R 755 /www/wwwtest/user3/www
#让用户对自己的目录有读写权限
setfacl -R -m u:user3:rwx /www/wwwtest/user3/www
# 重启服务
service sshd restart
# 登录之后 只能看见www目录
sftp -oPort=35021 user3@10.211.55.252
方法2:
创建shell文件sshd_chroot_jail.sh
#!/bin/sh
# first Release: 2004-07-30
RELEASE="2020-05-07"
# path to sshd's config file: needed for automatic detection of the locaten of
# the sftp-server binary
SSHD_CONFIG="/etc/ssh/sshd_config"
APPS=""
action=add
SHELL=/bin/bash
JAILPATH=/www/wwwjail
LINK=cp
PAM=nocopy
# Show HELP message
usage () {
echo
echo "USAGE: $0 < -u username [options]... | --update [options]... | -h >"
echo
echo " -u, --user username Set the name of new or exist user"
echo " --update Update files (not user) inside of jail"
echo " -h, --help Show this message"
echo
echo " Options:"
echo " -a --apps \"/path/app1 /p/to/app2\" Add your apps to be avaliable inside of Jail."
echo " Space-separated quoted list of paths"
echo " -c --config /path/to/sshd_config Set path to sshd_config. (\$SSHD_CONFIG)"
echo " Default:/etc/ssh/sshd_config"
echo " -j, --jail /path/to/jail Set the root of jail."
echo " Default:/chroot"
echo " -l, --link Set hard link mode."
echo " -p, --pam Provide PAM libs in the Jail."
echo " Default: PAM will not be provided"
echo " -s, --shell /path/to/chroot-shell Set shell for Jail'ed user. "
echo " Default:/bin/bash"
echo
echo "-------------------------------------------------------------"
echo
echo "Create new chrooted account or"
echo "add existing User to chroot-jail:"
echo "-> $0 -u username"
echo
echo "or specify the chroot-shell file, path where the jail should be located:"
echo "-> $0 -u username -s /path/to/chroot-shell -j /path/to/jail"
echo "-------------------------------------------------------------"
echo
echo "You can specify [--link] option, if files in the chroot are "
echo "on the same file system as the original files."
echo "It creates hard links instead of copy files."
echo "By default, script copies files."
echo "-------------------------------------------------------------"
echo
echo "You can specify [--pam] option, in case you want to use the PAM inside the jail."
echo "-------------------------------------------------------------"
echo
echo "or update files in the chroot-jail:"
echo "-> $0 --update -s /path/to/chroot-shell -j /path/to/jail"
echo "-------------------------------------------------------------"
echo
echo "You can include your application to the chroot by modification of \$APPS variable"
echo "-------------------------------------------------------------"
echo
echo "To uninstall:"
echo " # userdel \$USER"
echo " # rm -rf /chroot"
echo " (this deletes all Users' files!)"
}
copy_or_link () {
if [ $LINK = "ln" ]; then
if [ "$1" = "-p" ]; then shift ; fi
# prevent create Link for recurcive copy
if [ "$1" != "-r" ]; then
for dst in $@; do :; done # get the latest CLI argument = destination
until [ "$1" = "$dst" ]; do
if [ -d $dst ]; then
# echo "current link to DIR will be ln -v --force $( readlink -nf $1 ) $dst/$( basename -z $1 )"
ln --force $( readlink -nf $1 ) $dst/$( basename -z $1 )
shift
else
ln --force $( readlink -nf $1 ) $dst
shift
fi
done
else
# echo "Start Copy files Recucively"
/bin/cp $*
fi
else
#echo "Start Copy files"
/bin/cp $*
fi
} # This replace of cp command to make hard links of just copy
##### Main
if [ $# -eq 0 ] ; then
echo
echo "USAGE: $0 < -u username [options]... | --update [options]... | -h >"
echo
exit 1
fi
while [ "$1" != "" ]; do
case $1 in
-a | --apps ) shift
APPS="$1"
;;
--update ) action=update
;;
-u | -user ) shift
CHROOT_USERNAME=$1
;;
-s | --shell ) shift
SHELL=$1
;;
-j | --jail ) shift
JAILPATH=$1
;;
-l | --link ) LINK=ln
;;
-n| --pam ) PAM=copy
;;
-c | --config ) shift
SSHD_CONFIG=$1
;;
-h | -? | --help ) usage
exit
;;
* ) usage
exit 1
esac
shift
done
echo
if [ $action = "update" ]; then
echo "!!! You are going to <$action> all files (hard links) inside of Jail <$JAILPATH>."
else
echo "!!! You are going to <$action> the user <$CHROOT_USERNAME> into the Jail <$JAILPATH>."
fi
echo "Shell for Jail'ed user is <$SHELL>. Files will be <${LINK}>'ed."
echo "Config of SSHd is <$SSHD_CONFIG>. PAM modules will be <$PAM>'ed."
echo "List of additional application into the Jail are <$APPS>."
echo "
-----------------------------
Is it correct?"
read -p "(yes/no) -> " CORRECT
if [ "$CORRECT" != "yes" ]; then
echo "
Not entered yes. Exiting...."
exit 1
fi
if [ -z "$PATH" ] ; then
PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin
fi
echo
echo $0 Release: $RELEASE
echo
if [ "$(whoami &2>/dev/null)" != "root" ] && [ "$(id -un &2>/dev/null)" != "root" ] ; then
echo "Error: You must be root to run this script."
exit 1
fi
# Check existence of necessary files
echo "Checking distribution... "
if [ -f /etc/debian_version ];
then echo -n " Supported Distribution found:"
echo " System is running Debian Linux"
DISTRO=DEBIAN;
elif [ -f /etc/SuSE-release ];
then echo -n " Supported Distribution found^"
echo " System is running SuSE Linux"
DISTRO=SUSE;
elif [ -f /etc/fedora-release ];
then echo -n " Supported Distribution found:"
echo " System is running Fedora Linux"
DISTRO=FEDORA;
elif [ -f /etc/redhat-release ];
then echo -n " Supported Distribution found:"
echo " System is running Red Hat Linux"
DISTRO=REDHAT;
else echo -e " failed...........\nThis script works best on Debian, Red Hat, Fedora and SuSE Linux!\nLet's try it nevertheless....\nIf some program files cannot be found adjust the respective path in line 98\n"
#exit 1
fi
# Specify the apps you want to copy to the jail
if [ "$DISTRO" = SUSE ]; then
APPS="${APPS} /bin/bash /usr/bin/dircolors /usr/bin/groups /usr/bin/id /bin/cp /bin/ls /bin/mkdir /bin/nginx /bin/mv /bin/rm /bin/rmdir /bin/sh /usr/bin/ssh /usr/bin/scp"
elif [ "$DISTRO" = FEDORA ]; then
APPS="${APPS} /bin/bash /usr/bin/dircolors /usr/bin/groups /usr/bin/id /bin/cp /bin/ls /bin/mkdir /bin/nginx /bin/mv /bin/rm /bin/rmdir /bin/sh /usr/bin/ssh /usr/bin/scp"
elif [ "$DISTRO" = REDHAT ]; then
APPS="${APPS} /bin/bash /usr/bin/dircolors /usr/bin/groups /usr/bin/id /bin/cp /bin/ls /bin/mkdir /bin/nginx /bin/mv /bin/rm /bin/rmdir /bin/sh /usr/bin/ssh /usr/bin/scp"
elif [ "$DISTRO" = DEBIAN ]; then
APPS="${APPS} /bin/bash /usr/bin/dircolors /usr/bin/groups /usr/bin/id /bin/cp /bin/ls /bin/mkdir /bin/nginx /bin/mv /bin/rm /bin/rmdir /bin/sh /usr/bin/ssh /usr/bin/scp"
else
APPS="${APPS} /bin/bash /usr/bin/dircolors /usr/bin/groups /usr/bin/id /bin/cp /bin/ls /bin/mkdir /bin/nginx /bin/mv /bin/rm /bin/rmdir /bin/sh /usr/bin/ssh /usr/bin/scp"
fi
# Check existence of necessary files
echo -n "Checking for which... "
if ( test -f /usr/bin/which ) || ( test -f /bin/which ) || ( test -f /sbin/which ) || ( test -f /usr/sbin/which );
then echo " OK";
else echo " failed
Please install which-binary!
You can try to find it by:
yum whatprovides */which # on RHEL
apt-file search /which | grep /which$ # on Deb-based
zypper search --provides which # on SUSE
"
exit 1
fi
echo -n "Checking for dirname..."
if [ `which dirname` ]; then
echo " OK";
else
echo " failed
dirname not found!
Please install dirname-binary (to be found eg in the package coreutils)!
You can try to find it by:
yum whatprovides */dirname # on RHEL
apt-file search /dirname | grep /dirname$ # on Deb-based
zypper search --provides dirname # on SUSE
"
exit 1
fi
echo -n "Checking for readlink..."
if [ `which readlink` ]; then
echo " OK";
else
echo " failed
readlink not found!
Please install readlink-binary (to be found eg in the package coreutils)!
You can try to find it by:
yum whatprovides */readlink # on RHEL
apt-file search /readlink | grep /readlink$ # on Deb-based
zypper search --provides readlink # on SUSE
"
exit 1
fi
echo -n "Checking for awk..."
if [ `which awk` ]; then
echo " OK
";
else
echo " failed
awk not found!
Please install (g)awk-package/binary! (named like gawk)
You can try to find it by:
yum whatprovides */awk # on RHEL
apt-file search awk | grep awk$ # on Deb-based
zypper search --provides awk # on SUSE
"
exit 1
fi
if [ ! -f ${SSHD_CONFIG} ]
then
echo "File ${SSHD_CONFIG} not found."
echo "Not checking for path to sftp-server."
echo "Please adjust the global \$SSHD_CONFIG variable"
else
if !(grep -v "^#" ${SSHD_CONFIG} | grep -i sftp-server &> /dev/null); then
echo "Obviously no external sftp-server is running on this system.
";
else SFTP_SERVER=$(grep -v "^#" ${SSHD_CONFIG} | grep -i sftp-server | awk '{ print $3}')
fi
fi
APPS="$APPS $SFTP_SERVER"
# Check if user already exists and ask for confirmation
# we have to trust that root knows what she is doing when saying 'yes'
if ( test "$CHROOT_USERNAME" != "" && id $CHROOT_USERNAME > /dev/null 2>&1 ) ; then {
echo -n "User $CHROOT_USERNAME exists."
if [ -d /home/$CHROOT_USERNAME ] && [ -d $JAILPATH/home/$CHROOT_USERNAME ] ; then
echo "Already jailed. Exiting...."
exit 1
fi
echo "Adding the user to jail."
MODIFYUSER="yes"
}
else
CREATEUSER="yes"
fi
# make common jail for everybody if inexistent
if [ ! -d ${JAILPATH} ] ; then
mkdir -p ${JAILPATH}
echo "Creating ${JAILPATH}"
fi
cd ${JAILPATH}
# Create directories in jail that do not exist yet
JAILDIRS="dev etc lib etc/pam.d bin home sbin usr usr/bin usr/lib"
for directory in $JAILDIRS ; do
if [ ! -d "$JAILPATH/$directory" ] ; then
mkdir $JAILPATH/"$directory"
echo "Creating $JAILPATH/$directory"
fi
done
echo
# Creating necessary devices
[ -r $JAILPATH/dev/urandom ] || mknod $JAILPATH/dev/urandom c 1 9
[ -r $JAILPATH/dev/null ] || mknod -m 666 $JAILPATH/dev/null c 1 3
[ -r $JAILPATH/dev/zero ] || mknod -m 666 $JAILPATH/dev/zero c 1 5
[ -r $JAILPATH/dev/tty ] || mknod -m 666 $JAILPATH/dev/tty c 5 0
# if we only want to update the files in the jail
# skip the creation of the new account
if [ $action != "update" ]; then
# Define HomeDir for simple referencing
HOMEDIR="/home/$CHROOT_USERNAME"
# Create new account, setting $SHELL to the above created script and
# $HOME to $JAILPATH/home/*
if [ "$CREATEUSER" != "yes" ] ; then
echo " Not creating new User account
Modifying User \"$CHROOT_USERNAME\"
Copying files in $CHROOT_USERNAME's \$HOME to \"$HOMEDIR\"
"
usermod -d "$HOMEDIR" -m -s "$SHELL" $CHROOT_USERNAME && chmod 777 "$HOMEDIR"
if [ ! -d "${JAILPATH}${HOMEDIR}" ] ; then # Make copy of HOMEDIR in the Jail
mkdir ${JAILPATH}${HOMEDIR}
cp -p -r $HOMEDIR ${JAILPATH}${HOMEDIR}
fi
fi # endif usermod
if [ "$CREATEUSER" = "yes" ] ; then {
echo "Adding User \"$CHROOT_USERNAME\" to system (no password)"
useradd -m -d "$HOMEDIR" -s "$SHELL" $CHROOT_USERNAME && chmod 777 "$HOMEDIR"
cp -p -r $HOMEDIR ${JAILPATH}${HOMEDIR}
# Enter password for new account - TODO for interactive mode
if !(passwd $CHROOT_USERNAME);
then echo "Passwords are probably not the same, try again."
exit 1;
fi
echo
}
fi # endif useradd
# Add users to etc/passwd
#
# check if file exists (ie we are not called for the first time)
# if yes skip root's entry and do not overwrite the file
if [ ! -f etc/passwd ] ; then
grep /etc/passwd -e "^root" > ${JAILPATH}/etc/passwd
fi
if [ ! -f etc/group ] ; then
grep /etc/group -e "^root" > ${JAILPATH}/etc/group
# add the group for all users to etc/group (otherwise there is a nasty error
# message and probably because of that changing directories doesn't work with
# winSCP)
grep /etc/group -e "^users" >> ${JAILPATH}/etc/group
fi
# grep the username which was given to us from /etc/passwd and add it
# to ./etc/passwd replacing the $HOME with the directory as it will then
# appear in the jail
echo "Adding User $CHROOT_USERNAME to jail"
grep -e "^$CHROOT_USERNAME:" /etc/passwd | \
sed -e "s#$JAILPATH##" \
-e "s#$SHELL#/bin/bash#" >> ${JAILPATH}/etc/passwd
# if the system uses one account/one group we write the
# account's group to etc/group
grep -e "^$CHROOT_USERNAME:" /etc/group >> ${JAILPATH}/etc/group
## write the user's line from /etc/shadow to /home/jail/etc/shadow
#grep -e "^$CHROOT_USERNAME:" /etc/shadow >> ${JAILPATH}/etc/shadow
#chmod 600 ${JAILPATH}/etc/shadow
echo "
Please, add the next lines to the end of <${SSHD_CONFIG}>
-------------------------------------
Match User $CHROOT_USERNAME
ChrootDirectory ${JAILPATH}
------------------------------------
"
# endif for =! update
fi
# Copy the apps and the related libs
echo "Copying necessary library-files to jail (may take some time)"
# Don't know why, but redirection operator "&>/dev/null" is not working on Debian 9
# (where /bin/sh -> /bin/dash), so, I've replaced it to the ">/dev/null 2>&1".
TMPFILE1=`mktemp -q` >/dev/null 2>&1 || TMPFILE1="${HOME}/ldlist"; if [ -x ${TMPFILE1} ]; then mv -v ${TMPFILE1} ${TMPFILE1}.bak;fi
TMPFILE2=`mktemp -q` >/dev/null 2>&1 || TMPFILE2="${HOME}/ldlist2"; if [ -x ${TMPFILE2} ]; then mv -v ${TMPFILE2} ${TMPFILE2}.bak;fi
for app in $APPS; do
# First of all, check that this application exists
if [ -x $app ]; then
# Check that the directory exists; create it if not.
# app_path=`echo $app | sed -e 's#\(.\+\)/[^/]\+#\1#'`
app_path=`dirname $app`
if ! [ -d .$app_path ]; then
mkdir -p .$app_path
fi
# If the files in the chroot are on the same file system as the
# original files you should be able to use hard links instead of
# copying the files, too. Symbolic links cannot be used, because the
# original files are outside the chroot.
copy_or_link -p $app .$app
# get list of necessary libraries
ldd $app >> ${TMPFILE1}
fi
done
# Clear out any old temporary file before we start
for libs in `cat ${TMPFILE1}`; do
frst_char="`echo $libs | cut -c1`"
if [ "\"$frst_char\"" = "\"/\"" ]; then
# if [ "$frst_char" = "/" ]; then
echo "$libs" >> ${TMPFILE2}
fi
done
for lib in `cat ${TMPFILE2}`; do
mkdir -p .`dirname $lib` > /dev/null 2>&1
# If the files in the chroot are on the same file system as the original
# files you should be able to use hard links instead of copying the files,
# too. Symbolic links cannot be used, because the original files are
# outside the chroot.
copy_or_link $lib .$lib
done
#
# Now, cleanup the 2 files we created for the library list
#
#/bin/rm -f ${HOME}/ldlist
#/bin/rm -f ${HOME}/ldlist2
/bin/rm -f ${TMPFILE1}
/bin/rm -f ${TMPFILE2}
# Necessary files that are not listed by ldd.
#
# There might be errors because of files that do not exist but in the end it
# may work nevertheless (I added new file names at the end without deleting old
# ones for reasons of backward compatibility).
# So please test ssh/scp before reporting a bug.
if [ "$DISTRO" = SUSE ]; then
copy_or_link /lib/libnss_compat.so.2 /lib/libnss_files.so.2 /lib/libnss_dns.so.2 /lib/libxcrypt.so.1 ${JAILPATH}/lib/
elif [ "$DISTRO" = FEDORA ]; then
copy_or_link /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/ld-linux.so.2 /lib/ld-ldb.so.3 /lib/ld-lsb.so.3 /lib/libnss_dns.so.2 /lib/libxcrypt.so.1 ${JAILPATH}/lib/
copy_or_link /lib/*.* ${JAILPATH}/lib/
copy_or_link /usr/lib/libcrack.so.2 ${JAILPATH}/usr/lib/
elif [ "$DISTRO" = REDHAT ]; then
copy_or_link /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/ld-linux.so.2 /lib/ld-lsb.so.1 /lib/libnss_dns.so.2 /lib/libxcrypt.so.1 ${JAILPATH}/lib/
# needed for scp on RHEL
echo "export LD_LIBRARY_PATH=/usr/kerberos/lib" >> ${JAILPATH}/etc/profile
elif [ "$DISTRO" = DEBIAN ]; then
if [ -d /lib/x86_64-linux-gnu/ ]; then
copy_or_link /lib/x86_64-linux-gnu/libnss_compat.so.2 /lib/x86_64-linux-gnu/libnsl.so.1 /lib/x86_64-linux-gnu/libnss_files.so.2 /lib/x86_64-linux-gnu/libcap.so.2 /lib/x86_64-linux-gnu/libnss_dns.so.2 ${JAILPATH}/lib/
else
copy_or_link /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/libcap.so.1 /lib/libnss_dns.so.2 ${JAILPATH}/lib/
fi
else
copy_or_link /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/libcap.so.1 /lib/libnss_dns.so.2 ${JAILPATH}/lib/
fi
if [ $PAM = "copy" ]; then
# if you are using PAM you need stuff from /etc/pam.d/ in the jail,
echo "Copying files from /etc/pam.d/ to jail"
copy_or_link /etc/pam.d/* ${JAILPATH}/etc/pam.d/
# ...and of course the PAM-modules...
echo "Copying PAM-Modules to jail"
if [ -d /lib/security ]; then
copy_or_link /lib/security/* ${JAILPATH}/lib/
fi
if [ -d /lib/x86_64-linux-gnu/security ]; then
copy_or_link -r /lib/x86_64-linux-gnu/security ${JAILPATH}/lib/
fi
# ...and something else useful for PAM
copy_or_link -r /etc/security ${JAILPATH}/etc/
copy_or_link /etc/login.defs ${JAILPATH}/etc/
if [ -f /etc/DIR_COLORS ] ; then
copy_or_link /etc/DIR_COLORS ${JAILPATH}/etc/
fi
fi # endif for checking $PAM
# Don't give more permissions than necessary
if [ $LINK != "ln" ]; then
chown root.root ${JAILPATH}/bin/su
chmod 700 ${JAILPATH}/bin/su
fi
exit
# 配置路径
JAILPATH=/www/wwwjail
#执行 -u username
sh ./sshd_chroot_jail.sh -u xxx1
sh ./sshd_chroot_jail.sh -u xxx2
sh ./sshd_chroot_jail.sh -u xxx3
# 修改/etc/ssh/sshd_config文件
Match User xxx1,xxx2,xxx3
ChrootDirectory /www/wwwjail
# 重启ssh
service sshd restart
systemctl restart sshd.service
卸载
# To uninstall:
userdel xxx1
rm -rf /www/wwwjail
将用户的Web服务器(DocumentRoot)映射到/www/wwwjail/目录
# 挂载
mkdir /www/wwwjail/home/tom/we
mount --bind /home/httpd/tom_web /www/wwwjail/home/tom/web
echo "/home/httpd/tom_web /www/wwwjail/home/tom/web none bind" >> /etc/fstab
# 取消挂载
# 譬如 /home/httpd/tom_web 已经挂载在/www/wwwjail/home/tom/web上,用一下三条命令均可卸载挂载的文件系统
umount /home/httpd/tom_web
umount /www/wwwjail/home/tom/web
umount /home/httpd/tom_web /www/wwwjail/home/tom/web
注意
ssh登录时报错
acket_write_wait: Connection to xxx port 22: Broken pipe
tail /var/log/secure -n 20 # 可以只查看最近20条ssh记录
fatal: bad ownership or modes for chroot directory component "/" [postauth]
注意:chroot目录的权限设定原则:
1、由ChrootDirectory指定的目录到根目录只能是root
2、由ChrootDirectory指定的目录到根目录为止都不可以具有群组写入权限