#!/bin/bash
#菜单
menu(){
cat <<END
-----------------------------------------
功能:自动创建FTP或SFTP -
-----------------------------------------
支持:centos6、centos7、centos8 -
自动测试FTP/SFTP上传是否成功 -
data或其他挂载盘 -
自动备份相关配置文件 -
-----------------------------------------
作者:ysw 20220609 version 1.2.1 -
-----------------------------------------
注意:脚本会自动关闭防火墙,selinux -
-----------------------------------------
菜单编号,请选择 -
-
1.新建FTP账号 -
2.新建SFTP账号 -
-
3.测试SFTP账号上传 -
4.退出脚本 -
-
-----------------------------------------
END
}
time=$(date "+%Y%m%d%H%M%S")
#定义输出颜色函数
green () {
printf '\033[0;32;32m[success] %b\033[0m\n' "$1";
}
red () {
printf '\033[0;32;31m[error] %b\033[0m\n' "$1";
}
info () {
printf '\033[0;32;34m[info] %b\033[0m\n' "$1";
}
#初始化环境
chattr -i /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/inittab
setenforce 0 >/dev/null 2>&1
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
check_os=`cat /etc/redhat-release|sed -r 's/.* ([0-9]+)\..*/\1/' |grep -iv base`
[[ $UID -ne 0 ]] && red "请用root用户执行该脚本" && exit 1
info "正在关闭iptables或firewalld"
if [[ $check_os == 6 ]];then
service iptables stop
chkconfig iptables off
else
systemctl stop firewalld.service
systemctl disable firewalld.service
fi
check_pkg() {
rpm -qa | grep -i vsftpd > /dev/null 2>&1
if [[ $? -ne 0 ]];then
red "请先安装vsftpd服务端包 yum install vsftpd -y"
exit 1
fi
rpm -qa | grep -w ftp > /dev/null 2>&1
if [[ $? -ne 0 ]];then
red "请先安装ftp客户端包 yum install ftp -y"
exit 1
fi
}
check_sshversion() {
min_ssh_version=4.8
ssh_version=$(ssh -V 2>&1 | awk -F \_ '{print $2}'|awk -F p '{print $1}')
if [ $(expr $ssh_version \> $min_ssh_version) -eq 0 ];then
red "请先升级ssh版本大于4.8"
exit 1
fi
}
check_user() {
if cat /etc/passwd | awk -F':' '{print$1}' | grep -w $user >/dev/null
then
red "系统中已经存在此账号,请重新设置"
exit 1
fi
}
#配置ftp
creat_ftp() {
useradd -d $home_dir/$dir -s /sbin/nologin $user
chmod 755 -R $home_dir/$dir
echo $pass | passwd $user --stdin > /dev/null 2>&1
touch /etc/vsftpd/chroot_list
cat /dev/null > /etc/vsftpd/chroot_list
sed -i 's/^[^#].*pam_shells.so*/#&/g' /etc/pam.d/vsftpd
yes | cp -p /etc/vsftpd/vsftpd.conf /tmp/vsftpd.conf_${time}
bak_name=`ls -lt /tmp/ |grep -iv total |grep -v 总|grep vsftp| head -n 1 |awk '{print $9}'`
info "旧的vsftpd配置文件已经备份,备份路径为 /tmp/$bak_name"
cat > /etc/vsftpd/vsftpd.conf <<EOF
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list
allow_writeable_chroot=YES
anon_world_readable_only=NO
anon_other_write_enable=YES
anon_upload_enable=YES
anon_mkdir_write_enable=YES
chown_uploads=YES
pasv_enable=YES
pasv_min_port=50000
pasv_max_port=60000
pasv_promiscuous=YES
listen=YES
listen_ipv6=NO
pam_service_name=vsftpd
userlist_enable=YES
pasv_promiscuous=no
max_clients=10000
max_per_ip=10000
reverse_lookup_enable=NO
EOF
}
start_ftp() {
if [[ $check_os == 6 ]];then
chkconfig vsftpd on
service vsftpd restart
if [[ $? -eq 0 ]];then
green "vsftpd服务启动成功"
else
red "vsftpd服务启动失败"
exit 1
fi
else
systemctl enable vsftpd.service
systemctl restart vsftpd.service
if [[ $? -eq 0 ]];then
green "vsftpd服务启动成功"
else
red "vsftpd服务启动失败"
exit 1
fi
fi
}
test_ftp_upload () {
info "正在生成ftp上传测试文件..."
dd if=/dev/zero of=/home/ftp_upload_test_file.txt bs=10M count=1
info "正在使用 curl 模拟ftp上传..."
curl -# -u ${user}:${pass} -T /home/ftp_upload_test_file.txt ftp://127.0.0.1/
if [ ! -f "${home_dir}/${dir}/ftp_upload_test_file.txt" ];then
red "ftp模拟上传失败,请检查 !!!"
else
green "ftp模拟上传文件成功"
rm -f ${home_dir}/${dir}/ftp_upload_test_file.txt
fi
rm -f /home/ftp_upload_test_file.txt
}
start_sftp() {
sshd -t
if [[ $? -ne 0 ]];then
red "ssh配置文件有问题,请检查"
exit 1
fi
if [[ $check_os == 6 ]];then
service sshd restart
else
/bin/systemctl restart sshd.service
sleep 2 #重启两次ssh服务
/bin/systemctl restart sshd.service
fi
green "sftp账号创建成功"
}
check_home_dir() {
test -d $home_dir
if [[ $? -ne 0 ]];then
red "目录设置错误,本机没有此目录"
exit 1
fi
dir_num=`echo $dir |grep -o "/" |wc -l`
if [[ $dir_num -gt 1 ]];then
red "目录设置错误,请重新设置,目录末尾请不要带 / 如:upload "
exit 1
fi
}
check_dir() {
dir_num=`echo $dir |grep -o "/" |wc -l`
if [[ $dir_num -ge 1 ]];then
red "目录设置错误,请重新设置,请设置目录名称而不是路径 如:upload "
exit 1
fi
}
check_old_dir() {
if [ -d "$home_dir/${dir}" ];then
red "$home_dir 下已有此目录,请重新设置"
exit 1
fi
}
check_user_null() {
if [ ! $user ]; then
red "账号未指定,请重新开始"
exit 1
fi
}
check_pass_null() {
if [ ! $pass ]; then
red "密码未指定,请重新开始"
exit 1
fi
}
check_dir_null() {
if [ ! $dir ]; then
red "目录未指定,请重新开始"
exit 1
fi
}
check_home_dir_null() {
if [ ! $home_dir ]; then
red "数据存储目录未指定,请重新开始"
exit 1
fi
}
#配置sftp
creat_sftp() {
yes|cp -p /etc/ssh/sshd_config /tmp/sshd.conf_${time}
bak_name=`ls -lt /tmp/|grep -iv total|grep -v 总|grep ssh|head -n 1|awk '{print $9}'`
info "旧的ssh配置文件已经备份,备份路径为 /tmp/$bak_name"
cat /etc/group|awk -F \: '{print $1}'| grep -w "sftp" > /dev/null 2>&1 || groupadd sftp
useradd -g sftp -s /bin/false $user
echo $pass | passwd $user --stdin > /dev/null 2>&1
mkdir -p $home_dir/sftp/$user
usermod -d $home_dir/sftp/$user $user
sed -i 's/^[^#].*sftp-server*/#&/g' /etc/ssh/sshd_config
sed -i '/Subsystem/d' /etc/ssh/sshd_config
sed -i '/Match/d' /etc/ssh/sshd_config
sed -i '/ChrootDirectory/d' /etc/ssh/sshd_config
sed -i '/ForceCommand/d' /etc/ssh/sshd_config
echo "Subsystem sftp internal-sftp" >> /etc/ssh/sshd_config
echo "Match Group sftp" >> /etc/ssh/sshd_config
echo "ChrootDirectory $home_dir/sftp/%u" >> /etc/ssh/sshd_config
echo "ForceCommand internal-sftp" >> /etc/ssh/sshd_config
chown root:sftp $home_dir/sftp/$user
chmod 755 $home_dir/sftp/$user
mkdir $home_dir/sftp/$user/upload
chown $user:sftp $home_dir/sftp/$user/upload
chmod 755 $home_dir/sftp/$user/upload
}
check_expect_pkg () {
rpm -qa | grep -w expect > /dev/null 2>&1
if [[ $? -ne 0 ]];then
red "请先安装expect包, yum install expect -y"
exit 1
fi
rpm -qa|grep -w tcl > /dev/null 2>&1
if [[ $? -ne 0 ]];then
red "请先安装tcl依赖包 yum install tcl -y"
exit 1
fi
}
check_sftp_upload () {
dd if=/dev/zero of=/home/sftp_upload_test_file.txt bs=10M count=1
sftp_port=22
sftp_ip=127.0.0.1
expect <<- EOF
spawn sftp -oPort=${sftp_port} ${sftp_user}@${sftp_ip}
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "${sftp_pass}\r" }
}
expect "sftp> "
send "cd upload\r"
expect "sftp> "
send "put /home/sftp_upload_test_file.txt\r"
expect "sftp> "
send "ls\r"
expect "sftp> "
send "exit\r"
EOF
if [ ! -f "/home/sftp/${sftp_user}/upload/sftp_upload_test_file.txt" ];then
red "sftp模拟上传失败,请检查 !!!"
else
green "sftp上传成功文件测试成功"
rm -f /home/sftp/${sftp_user}/upload/sftp_upload_test_file.txt
fi
rm -f /home/sftp_upload_test_file.txt
#清理expect进程
ps -aux | grep "expect" | grep -v "grep" | awk '{print $2}' | while read line;
do
kill -9 $line
done
}
clear
menu
read -p "请选择菜单编号 1 或 2 或 3 或 4 : " -t 20 num
if [[ $num == 1 ]];
then
info "您选择了 1 ,正在新建ftp..."
check_pkg
read -p "请指定FTP数据存储一级挂载目录 例如 /home 或 /data 或 /data1: " -t 30 home_dir
check_home_dir
check_home_dir_null
read -p "请配置要创建的FTP账号: " -t 30 user
check_user_null
check_user
read -p "请配置FTP账号的密码: " -t 30 pass
check_pass_null
read -p "请配置FTP在 $home_dir 下的目录名 例如 ftp_upload: " -t 30 dir
check_dir_null
check_dir
check_old_dir
creat_ftp
start_ftp
test_ftp_upload
info "FTP账号: $user"
info "FTP密码: $pass"
info "FTP本机目录 $home_dir/$dir"
info "FTP家目录: /"
echo ""
info "如果你想开启本机防火墙,请放开 21端口和 50000-60000 连续端口"
info "如果你不想锁定 $user 的FTP家目录,请将 $user 添加到 /etc/vsftpd/chroot_list 文件中并重启ftp服务"
echo ""
elif [[ $num == 2 ]];then
info "您选择了 2 ,正在新建sftp..."
check_sshversion
read -p "请配置SFTP数据存储一级目录 例如 /home 或 /data 或 /data1: " -t 30 home_dir
check_home_dir_null
check_home_dir
read -p "请配置要创建的SFTP账号: " -t 30 user
check_user_null
check_user
if [ $user == "sftp" ];then
red "用户名请不要设置为sftp,脚本退出,请重新设置"
exit 1
fi
read -p "请配置SFTP账号密码: " -t 30 pass
check_pass_null
creat_sftp
start_sftp
info "SFTP账号: $user"
info "SFTP密码: $pass"
info "SFTP本机目录: $home_dir/sftp/$user/upload"
info "SFTP家目录:/upload"
elif [[ $num == 3 ]];then
info "您选择了 3,正在测试SFTP上传功能..."
check_expect_pkg
read -p "请输入需要测试的sftp账号: " -t 30 sftp_user
read -p "请输入需要测试的sftp账号密码: " -t 30 sftp_pass
check_sftp_upload
elif [[ $num == 4 ]];then
info "您选择了 4 ,脚本退出"
exit 1;
else
red "输入错误或超时,脚本退出"
exit 1;
fi
网友评论