前言
在某些情况下,允许指定用户可以传输文件到linux系统中,但是不允许使用SSH,要实现这一目的我们可以使用SFTP,并构建chroot环境.
一般只要服务器开启了SSH服务默认就可以使用SFTP服务,只要设置一下权限即可,比如将用户限制到某个目录下.
环境
root@tianshl:~# uname -a
Linux tianshl 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
root@tianshl:~# ssh -V
OpenSSH_7.2p2 Ubuntu-4ubuntu2.2, OpenSSL 1.0.2g 1 Mar 2016
# ssh需要OpenSSH4.8p1以后的版本.因为要使用chroot设置根目录
sftp服务搭建及基础配置
创建根目录和组
# 创建根目录
root@tianshl:~# mkdir /sftp
# 设置属主及权限
root@tianshl:~# chown root:root /sftp
root@tianshl:~# chmod 755 /sftp
# 创建用户组
root@tianshl:~# groupadd sftp
设置SFTP服务用户目录权限
# 备份配置文件
root@tianshl:~# cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
# 修改配置文件
root@tianshl:~# vim /etc/ssh/sshd_config
# 修改内容如下:
# 注释掉
# Subsystem sftp /usr/lib/openssh/sftp-server
# 使用系统默认的sftp服务
Subsystem sftp internal-sftp
# 匹配组名 sftp
Match Group sftp
# 指定活动目录
ChrootDirectory /sftp/%u
# 由ChrootDirectory指定的目录开始一直往上到系统根目录的目录属主都是root.
# 由ChrootDirectory指定的目录开始一直往上到系统根目录都不可以具有群组写入权限.
# 禁用端口转发
AllowTcpForwarding no
X11Forwarding no
# 强制执行内部SFTP,并忽略任何~/.ssh/rc中的命令
ForceCommand internal-sftp
重启sshd
root@tianshl:~# service sshd restart
用户组权限配置结束
sftp用户可以登录和读取自己的home目录,并且没有写入权限
创建用户
# 创建用户user2
# -d: 家目录
# -m: 创建家目录
# -g: 组
# -s: shell
root@tianshl:~# useradd -d /sftp/user2 -m -g sftp -s /bin/false user2
# 生成密码
root@tianshl:~# mkpasswd user2
# 设置密码
root@tianshl:~# passwd user2
# 设置属主
root@tianshl:~# chown root:sftp /sftp/user2
# 创建数据目录
root@tianshl:~# mkdir /sftp/user2/user
root@tianshl:~# mkdir /sftp/user2/event
# 设置数据目录权限
root@tianshl:~# chown user2:sftp /sftp/user2/*
用户权限配置结束
创建了用户user2,
家目录: user2 读权限
数据目录: user | event 读写权限
目录结构
root@tianshl:/sftp# tree
.
├── user1
│ ├── event
│ └── user
└── user2
├── event
└── user
主账号
1. 程序使用主账号(admin)操作所有sftp用户家目录下的所有数据文件.
2. 每个sftp用户的权限不变.
暴露出的问题
每个客户的家目录及父目录的所有者及权限就会不满足chroot的要求,
解决方案
# 通过软连接的方式为admin创建家目录
root@tianshl:~# ln -s /sftp /sftp/admin
目录权限
1. 每个用户的家目录必须是 root:root (chroot规则,否则用户无法登录)
2. 家目录中数据文件夹需要是 当前用户: sftp, 权限是777 (admin需要操作)
目录结构
root@tianshl:/sftp# tree
.
├── admin -> /sftp
├── user1
│ ├── event
│ └── user
└── user2
├── event
└── user
创建主账号
root@tianshl:/sftp# password=`mkpasswd admin`;useradd -b /sftp/admin admin;echo "admin:$password" | chpasswd;echo $password
献上创建用户的脚本
创建脚本
root@tianshl:/sftp# vim addsftpuser.sh
脚本内容
#! /bin/bash
if [ -n "$1" ];then
user=$1
else
echo "缺少用户名"
exit;
fi
# 家目录
home=/sftp/$user
# 创建sftp用户
echo "创建用户 $user"
useradd -d $home -m -g sftp -s /bin/false $user
if [ $? -eq 0 ];then
echo " 创建成功"
else
echo " 创建失败"
exit 1
fi
# 生成密码
echo "生成密码"
password=`mkpasswd $user`
if [ $? -eq 0 ];then
echo " 生成成功"
# 设置用户密码
echo "设置用户密码 $password"
echo "$user:$password" | chpasswd
if [ $? -eq 0 ];then
echo " 设置成功"
else
echo " 设置失败"
fi
else
echo " 生成失败, 需要手动设置密码"
exit 1
fi
# 设置家目录属主
echo "设置家目录属主 root:sftp"
chown root:sftp $user
if [ $? -eq 0 ];then
echo " 设置成功"
else
echo " 设置失败"
fi
# 设置家目录权限
echo "设置家目录权限 755"
chmod 755 $user
if [ $? -eq 0 ];then
echo " 设置成功"
else
echo " 设置失败"
fi
# 创建数据目录
echo "创建数据目录 user|event"
mkdir /$home/{user,event}
if [ $? -eq 0 ];then
echo " 创建成功"
else
echo " 创建失败"
fi
# 设置数据目录属主
echo "设置数据目录属主 $user:sftp"
chown ${user}:sftp /$home/*
if [ $? -eq 0 ];then
echo " 设置成功"
else
echo " 设置失败"
fi
# 设置数据目录权限
echo "设置数据目录权限 $user:sftp"
chmod 777 /$home/*
if [ $? -eq 0 ];then
echo " 设置成功"
else
echo " 设置失败"
fi
echo
echo "----- 账号 + 密码 -----"
echo -e "${user}\n${password}"
echo "-----------------------"
运行脚本
root@tianshl:/sftp# ./addsftpuser.sh user3
创建用户 user3
创建成功
生成密码
生成成功
设置用户密码 F4y9zRI/Thims
设置成功
设置家目录属主 root:sftp
设置成功
设置家目录权限 755
设置成功
创建数据目录 user|event
创建成功
设置数据目录属主 user3:sftp
设置成功
设置数据目录权限 user3:sftp
设置成功
-------------------
user3
F4y9zRI/Thims
-------------------
目录结构
root@tianshl:/sftp# tree
.
├── addsftpuser.sh
├── admin -> /sftp
├── user1
│ ├── event
│ └── user
├── user2
│ ├── event
│ └── user
└── user3
├── event
└── user