Sftp部署及最佳化

彬彬l發表於2024-10-08

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 CHN-project-user@10.0.0.1
-oPort=30022:SFTP server Port
CHN-project-user:SFTP Username
10.0.0.1:SFTP Server address

4.2 Linux7

~]# sftp -P 30022 CHN-project-user@10.0.0.1
CHN-project-user@10.0.0.1'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


13.SFTP Server遷移

參考:https://www.landui.com/help/show-3462

相關文章