Sftp部署及优化
1.SFTP规划
SFTP Server Port: 30022
按照项目进行分类,来创建sftp账号
命名规范:
用户名 | 权限 | sftp目录 | Chroot目录 | Group |
---|---|---|---|---|
地区+项目+用户(组或个人) | rw/r | /data/项目/项目 | /项目 | 项目+RW |
例:CHN-projectname-a | rw | /data/projectname/projectname | /projectname | projectnameRW |
CHN-projectname-b | r | /data/projectname/projectname | /projectname | 只有写权限才需要加入对应的组 |
2.配置SFTP
2.1 修改ssh配置
只用第一次修改ssh配置文件
~]# vi /etc/ssh/sshd_config
#Subsystem sftp /usr/libexec/openssh/sftp-server
Subsystem sftp internal-sftp
Match Group sftp
Match LocalPort 20912
ChrootDirectory %h #chroot到所创建用户时的家目录
ForceCommand internal-sftp
~]# systemctl restart sshd
3.创建sftp账号
下面是每次创建账号需要的操作
3.1 创建目录结构
~]# mkdir –p /data/projectname/projectname
~]# chmod 775 /data/projectname/projectname
3.2 创建sftp用户
~]# useradd -s /bin/false -d /data/projectname CHN-projectname-b
~]# useradd -s /bin/false -d /data/projectname CHN-projectname-a
3.3设置sftp用户密码
~]# echo ‘CHN-projectname-b:password1’|chpasswd
~]# echo ‘CHN-projectname-a:password2’|chpasswd
#可以使用其他方式配置密码
3.4 创建权限组
~]# groupadd projectnameRW
3.5 把需要写权限加入到权限组中
~]# usermod -aG projectnameRW CHN-projectname-b
如果CHN-projectname-a也需要写权限,加入到权限组(projectnameRW)即可
3.6 配置目录权限
~]# chown root:projectnameRW /data/projectname/projectname
3.7 配置ACL权限
#针对需要多个用户对同一个目录进行读写,需要使用到ACL权限
如果是第一次新建,比较简单,2条命令即可
~]# chmod –R g+s /data/CN-project/CN-project
~]# setfacl -Rm d:g:groupname:rwx /data/CN-project/CN-project
如果是已经在使用的sftp,并且sftp的家目录有数据,手动执行以下命令
~]# chmod -R g+s /data/CN-project/CN-project
~]# setfacl -Rm d:g:groupname:rwx /data/CN-project/CN-project
~]# chown -R :groupname /data/CN-project/CN-project
~]# chmod -R 775 /data/CN-project/CN-project
3.8重启sshd服务
~]# systemctl restart sshd
4.sftp客户端使用
4.1 Linux6
~]# sftp -oPort=30022 [email protected]
-oPort=30022:SFTP server Port
CHN-project-user:SFTP Username
10.0.0.1:SFTP Server address
4.2 Linux7
~]# sftp -P 30022 [email protected]
[email protected]'s password: <-- 输入密码
5. sftp日志审计
5.1 修改ssh配置
~]# cat /etc/ssh/sshd_config
......
Subsystem sftp internal-sftp -l VERBOSE -f AUTHPRIV
Match Group sftp
Match LocalPort 20912
ChrootDirectory %h
ForceCommand internal-sftp -l VERBOSE -f AUTHPRIV
5.2 配置日志路径
~]# cat /etc/rsyslog.conf
......
authpriv.* /var/log/sftp.log
5.3 重启生效
~]# systemctl restart sshd
~]# systemctl restart rsyslog
6. sftp日志保存周期
~]# cd /etc/logrotate.d/
~]# vi sftp
/var/log/sftp.log {
monthly #默认每月执行一次日志轮询
missingok
rotate 6 #保存6个日志文件
compress
delaycompress
dateext
create 0600 root root
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
~]# systemctl restart rsyslog
测试
~]# logrotate --dbug --verbose --force /etc/logrotate.d/sftp
7.sftp开启每个用户连接数限制
~]# cat /etc/security/limits.d/95-sftp-limit.conf
@sftpusername hard nproc 400 #限制用户连接数为200,这里配置数量为连接数*2
8.sftp打开用户认证数量限制
~]# cat /etc/ssh/sshd_config
MaxStartups 1000:30:1200
9.sftp配置每个用户最大打开文件数
~]# cat /etc/security/limits.conf
......
# End of file
* soft nofile 100000
* hard nofile 100000
10.sftp监控项
10.1 监控sftp连接数
netstat -an|grep -E '10.*:30022'|wc -l
或者
ps -ef | grep 'sshd:'|grep 'notty'|wc -l
10.2 sftp日志监控,触发连接数限制
监控sftp日志,指定sftp用户触发连接数限制,告警通知
~]# cat /var/log/sftp.log
Mar 27 14:38:28 ashblpftpa04 sshd[24409]: error: do_exec_no_pty: fork: Resource temporarily unavailable [postauth]
Mar 27 14:38:28 ashblpftpa04 sshd[24409]: subsystem request for sftp by user CHN-TMSData_PRD-esb failed, subsystem not found [postauth]
Mar 27 14:38:28 ashblpftpa04 sshd[24409]: fatal: do_exec: command already set [postauth]
11.SFTP高可用
11.1 多台sftp底层存储使用阿里云NAS
使用nas作为/data盘. acl授权命令改为nfs4_setfacl.
11.2 多台sftp创建用户时,保持UID,GID一致.
多台sftp server创建用户用此脚本创建.
#!/bin/bash
#########################################################
# Function : Add user in 2 SFTP servers #
# Version : 1.0 #
#########################################################
############ env define ############
sshuser=osadmin #多台sftp配置免密用户
workdir=/tmp
shijian=`date +%Y_%M_%d_%H_%m`
server1=10.0.0.1
server2=10.0.0.2
server3=10.0.0.3
server4=10.0.0.4
sftpport=30022
sshport=22
new_user=${1}
user_pass=${2}
############ env define ############
############ USAGE ############
if [[ $# != 2 ]];then
echo -e "\033[31;5mParameter incorrect. Please check below example: \033[0m"
echo -e "\033[33;1mfor example:\033[0m"
echo "ScriptName USER PASSWORD"
exit 1
fi
############ USAGE ############
######## Function ###############
### get /etc/passwd from each server
get_passwd_file() {
scp -q ${sshuser}@${1}:/etc/passwd ${workdir}/passwdfile_${1}_${shijian}
}
### get /etc/group from each server
get_group_file() {
scp -q ${sshuser}@${1}:/etc/group ${workdir}/groupfile_${1}_${shijian}
}
### find the maximum user id
find_max_user_id() {
awk -F':' '{ print $3 }' ${workdir}/passwdfile_${1}_${shijian} | grep -v 65534 | sort -n | tail -n 1
}
### find the maximum group id
find_max_group_id() {
awk -F':' '{ print $3 }' ${workdir}/groupfile_${1}_${shijian} | grep -v 65534 | sort -n | tail -n 1
}
### get max id among all servers
get_max_id() {
if [ $# -eq 0 ]
then
echo "No input , please check"
else
min=$1
max=$1
sum=0
for i in "$@"
do
if [ $min -gt $i ]
then
min=$i
fi
if [ $max -lt $i ]
then
max=$i
fi
sum=$[$sum+$i]
done
echo $max
fi
}
### check if all server alive
check_server_alive() {
nc -4 -w 2 -z ${1} ${2}
if [ $? -eq 0 ]
then
echo -e "\033[32;1m ${1} port ${2} alived\033[0m"
else
echo -e "\033[31;5m Server ${1} Port ${2} cannot connect , please check it manually ~! \033[0m"
exit
fi
}
### add user in 2 servers
add_user() {
for i in {1..4}
do
serverip=`eval echo '$'"server${i}"`
ssh ${sshuser}@${serverip} "sudo /sbin/groupadd -g ${next_gid} ${1}"
if [ $? -eq 0 ]
then
echo -e "\033[32;1m Group ${1} creation in ${serverip} done \033[0m"
else
echo -e "\033[31;5m Group ${1} creation in ${serverip} failed , please check it manually ~! \033[0m"
exit
fi
ssh ${sshuser}@${serverip} "sudo /sbin/useradd -s /bin/false -u ${next_uid} -g ${next_gid} ${1}"
if [ $? -eq 0 ]
then
echo -e "\033[32;1m User ${1} creation in ${serverip} done \033[0m"
else
echo -e "\033[31;5m User ${1} creation in ${serverip} failed , please check it manually ~! \033[0m"
exit
fi
ssh ${sshuser}@${serverip} "sudo /bin/passwd ${1} << eof
${user_pass}
${user_pass}
eof"
if [ $? -eq 0 ]
then
echo -e "\033[32;1m User ${1} password change in ${serverip} done \033[0m"
else
echo -e "\033[31;5m User ${1} password change in ${serverip} failed , please check it manually ~! \033[0m"
exit
fi
done
}
######## Function ###############
######## Action ###############
check_server_alive ${server1} ${sftpport}
check_server_alive ${server2} ${sftpport}
check_server_alive ${server3} ${sftpport}
check_server_alive ${server4} ${sftpport}
get_passwd_file ${server1}
get_passwd_file ${server2}
get_passwd_file ${server3}
get_passwd_file ${server4}
get_group_file ${server1}
get_group_file ${server2}
get_group_file ${server3}
get_group_file ${server4}
max_uid_server1=`find_max_user_id ${server1}`
max_uid_server2=`find_max_user_id ${server2}`
max_uid_server3=`find_max_user_id ${server3}`
max_uid_server4=`find_max_user_id ${server4}`
max_gid_server1=`find_max_group_id ${server1}`
max_gid_server2=`find_max_group_id ${server2}`
max_gid_server3=`find_max_group_id ${server3}`
max_gid_server4=`find_max_group_id ${server4}`
max_uid=`get_max_id ${max_uid_server1} ${max_uid_server2} ${max_uid_server3} ${max_uid_server4}`
max_gid=`get_max_id ${max_gid_server1} ${max_gid_server2} ${max_gid_server3} ${max_gid_server4}`
### generate next uid
if [ ${max_uid} -gt "20000" ]
then
next_uid=$(expr ${max_uid} + 1)
else
next_uid=$(expr 20001)
fi
### generate next gid
if [ ${max_gid} -gt "20000" ]
then
next_gid=$(expr ${max_gid} + 1)
else
next_gid=$(expr 20001)
fi
add_user ${new_user}
######## Action ###############
11.3 多台sftp创建用户脚本
创建sftp用户脚本:
#!/bin/bash
#----------env-------------
homedir='CN-ProjectName'
user1_name='user1'
user1_pass='password'
user1_rights='rw'
user2_name='user2'
user2_pass='password'
user2_rights='r'
#-----------sftp server---------------------
sshuser=osadmin #免密用户
server1=10.0.0.1
server2=10.0.0.2
server3=10.0.0.3
server4=10.0.0.4
#-------------Create SFTP project directory-------------------
mkdir -p /data/${homedir}/${homedir}
chmod 775 /data/${homedir}/${homedir}
chown root:root /data/${homedir}
#--------------Create sftp user-----------------------
create_sftp_user(){
sftpusername=$1
sftpuserpassword=$2
sh /home/osadmin/create_sftp_user.sh ${sftpusername} ${sftpuserpassword}
chage -M 99999 ${sftpusername}
ssh ${sshuser}@${server1} "sudo /sbin/usermod -d /data/${homedir} ${sftpusername}"
ssh ${sshuser}@${server1} "sudo chage -M 99999 ${sftpusername}"
ssh ${sshuser}@${server2} "sudo /sbin/usermod -d /data/${homedir} ${sftpusername}"
ssh ${sshuser}@${server2} "sudo chage -M 99999 ${sftpusername}"
ssh ${sshuser}@${server3} "sudo /sbin/usermod -d /data/${homedir} ${sftpusername}"
ssh ${sshuser}@${server3} "sudo chage -M 99999 ${sftpusername}"
ssh ${sshuser}@${server4} "sudo /sbin/usermod -d /data/${homedir} ${sftpusername}"
ssh ${sshuser}@${server4} "sudo chage -M 99999 ${sftpusername}"
}
create_sftp_user ${user1_name} ${user1_pass}
create_sftp_user ${user2_name} ${user2_pass}
#-------------Configure nas directory permissions------------------------
chown root:${user1_name} /data/${homedir}/${homedir}
chmod g+s /data/${homedir}/${homedir}
cd /data/${homedir}
nfs4_setfacl -a A:fdg:OWNER@: ${homedir}
nfs4_setfacl -a A:fdg:GROUP@: ${homedir}
nfs4_setfacl -a A:fdg:EVERYONE@: ${homedir}
#-------------Configure sftp user permissions------------------------
config_user_permissions(){
user_name=$1
user_rights=$2
user_id=`id -u ${user_name}`
cd /data/${homedir}
if [ ${user_rights} == 'rw' ];then
nfs4_setfacl -a A:df:${user_id}:RWX ${homedir}
elif [ ${user_rights} == 'r' ];then
nfs4_setfacl -a A:df:${user_id}:RX ${homedir}
fi
}
config_user_permissions ${user1_name} ${user1_rights}
config_user_permissions ${user2_name} ${user2_rights}
12.SFTP用户空闲超时
Subsystem sftp internal-sftp
Match Group sftp
Match LocalPort 20981
ClientAliveInterval 600
ClientAliveCountMax 0
ChrootDirectory %h
ForceCommand internal-sftp -l VERBOSE -f AUTHPRIV