Linux操作系统基线设置自动化脚本(Shell版)

该脚本用于自动检查并配置系统基线,主要功能有:自动禁止root远程登录、设置密码最小长度和复杂度、口令生存周期、命令行界面超时时间,检查或修改MASK设置等。

仅在Redhat/CentOS环境中通过测试,请仔细阅读说明并自行测试后再用于生产环境。

#!/bin/bash

sshconfig="/etc/ssh/sshd_config"
pamfile1="/etc/pam.d/common-password"
pamfile2="/etc/pam.d/system-auth"
pamfile3="/etc/pam.d/login"
logindef="/etc/login.defs"
sysctlcfg="/etc/sysctl.conf"
umask1="/etc/profile"
umask2="/etc/csh.cshrc"
umask3="/etc/bashrc"
prfile="/etc/profile"
basdir="/opt/baseline"
bakdir="${basdir}/bak"
bllogs="${basdir}/baseline.log"

# 检查操作系统版本
osversion=`cat /etc/redhat-release | sed 's/[^0-9]//g'`
osversion=${osversion:0:1}
[ ! -d "${basdir}" ] && mkdir ${basdir}
if [ "${osversion}" -lt 6 ] || [ -z "${osversion}" ]
then
  echo "########本脚本仅适合Redhat6/CentOS6或更新版本的操作系统########" > ${bllogs}
  exit 0
else
  echo -e "############开始执行脚本调整系统基线############\n>>>>>>>>>> `date "+%Y年%m月%d日%H时%M分%S秒"` <<<<<<<<<<" > ${bllogs}
fi

# 备份并配置基本环境
echo "# 备份并配置基本环境 #" >> ${bllogs}
if [ -d "${bakdir}" ]
then
  cd ${basdir}
  tar -czPvf bak.`date "+%Y%m%d%H%M%S"`.tar.gz ${bakdir} --remove-files
  echo "> 已经打包备份旧目录文件" >> ${bllogs}
fi
mkdir -p ${bakdir}
# 请调整需要备份的文件
for bfile in $sshconfig $pamfile1 $pamfile2 $logindef $sysctlcfg $prfile
do
  [ -e ${bfile} ] && cp ${bfile} ${bakdir} && echo "> 备份文件${bfile}" >> ${bllogs}
done

# 锁定额外的用户账号
LOCKUSER () {
echo "# 锁定无用的系统账号 #" >> ${bllogs}
for username in ${lockusers[@]}
do
  sysuser=`cat /etc/passwd | awk '{print $1}' | grep -w "${username}"`
  [ -n "${sysuser}" ] && usermod -L ${username} && echo "> 已锁定账号${username}" >> ${bllogs} || echo "> 无效的账号${username}" >> ${bllogs}
done
}

# 禁止root用户远程登录
BANROOTRLOGIN () {
echo "# 禁止root用户远程登录 #" >> ${bllogs}
# 在CentOS8或OpenSSH8版本中,已移除pam_securetty.so,好在仍然可以用
shversion=`ssh -V 2>&1 | awk -F'[_,]' '{print $2}'`
shversion=${shversion:0:1}
[ -z ${shversion} ] && shversion=0
if [ "${osversion}" -le 8 ] && [ "${shversion}" -le 8 ]
then
  pamlogin=`grep ^auth ${pamfile3} | grep -w 'pam_securetty.so'`
  if [ -z "${pamlogin}" ]
  then
    insline=`grep -n ^auth ${pamfile3} | head -n 1`
    eval sed -i '${insline}s/$/&\ pam_securetty.so' ${pamfile3}
    echo '> 已添加配置禁止root远程telnet登录' >>  ${bllogs}
  else
    echo '> 系统已禁止root远程telnet登录,无需修改' >>  ${bllogs}
  fi
fi
sshlogin=`grep ^PermitRootLogin ${sshconfig} | awk '{print $2}'`
if [ -z "${sshlogin}"  ]
then
  echo 'PermitRootLogin no' >> ${sshconfig}
  echo -e '! 已添加配置禁止root远程ssh登录\n! 请确保有其他可远程登录的账号或途径' >>  ${bllogs}
elif [ "${sshlogin}" = "yes" ]
then
  sed -i '/^PermitRootLogin/s/yes/no/g' ${sshconfig}
  echo -e '! 已修改配置禁止root远程ssh登录\n! 请确保有其他可远程登录的账号或途径' >>  ${bllogs}
else
  echo '> 系统已禁止root远程ssh登录,无需修改' >>  ${bllogs}
fi
[ ${erstsshd} -eq 1 ] && service sshd restart && echo '! 已重启sshd服务,须再三确认后方可退出' >> ${bllogs}
}

# 对IP登录的设备禁用telnet协议
REMOVETELNET () {
echo "# 对IP登录的设备禁用telnet协议 #" >> ${bllogs}
cktelnet=`rpm -qa telnet`
ckxinetd=`rpm -qa xinetd`
xinetdcfg="/etc/xinetd.d/telnet"
if [ -z "${cktelnet}" ]
then
  echo '> 本机未安装telnet,无需修改' >>  ${bllogs}
else
  if [ -z "${ckxinetd}" ]
  then
    if [ "${rmtelnet}" -eq 1 ] || [ "${osversion}" -lt 7 ]
    then
      rpm -e `rpm -qa telnet` --nodeps
      echo '> 用户选择或者系统版本太低,已经卸载telnet' >>  ${bllogs}
    else
      yum -y install xinetd
      echo 'disable = yes' > ${xinetdcfg}
      service xinetd start
      echo '> 已安装xinetd并禁用telnet协议' >>  ${bllogs}
    fi
  else
    if [ -e "${xinetdcfg}" ]
    then
      cftelnet=`grep -v '^#' ${xinetdcfg} | grep disable | sed 's/\ //g' | awk -F= '{print $2}'`
      if [ "${cftelnet}" = yes ]
      then
        echo '> 系统已经禁用telnet协议,无需修改' >>  ${bllogs}
      elif [ "${cftelnet}" = no ]
      then
        sed -i '/disable/s/no/yes/g' ${xinetdcfg}
        echo '> 已经修改配置禁用telnet协议' >>  ${bllogs}
      elif [ -z "${cftelnet}" ]
      then
        echo 'disable = yes' > ${xinetdcfg}
        service xinetd restart
        echo '> 已经添加配置禁用telnet协议' >>  ${bllogs}
      else
        echo -e "! 系统存在异常的telnet配置\n! 请检查文件${xinetdcfg}" >>  ${bllogs}
      fi
    else
      echo 'disable = yes' > ${xinetdcfg}
      service xinetd restart
      echo '> 已经创建配置禁用telnet协议' >>  ${bllogs}
    fi
  fi
fi
}

# 设置口令最小长度
SETPWDMINLEN () {
echo "# 设置口令最小长度 #" >> ${bllogs}
if [ -e ${pamfile1} ]
then
  pamcompwd=`grep '^password' ${pamfile1} | grep required | grep pam_cracklib.so | grep minlen`
  if [ -n "${pamcompwd}" ]
  then
    pwdminlen=`echo "${pamcompwd}" | awk -F'=' '{print $2}'`
    if [ ${pwdminlen} -ge ${pwdminlennew} ]
    then
      echo '> 当前口令最小长度符合要求,无需修改' >>  ${bllogs}
    else
      eval sed -i '/minlen/s/${pwdminlen}/${pwdminlennew}/g' ${pamfile1}
      echo "> 已经将参数minlen的值由${pwdminlen}修改为${pwdminlennew}" >>  ${bllogs}
    fi
  else
    pamcompwd=`grep '^password' ${pamfile1} | grep required | grep pam_cracklib.so`
    if [ -z "${pamcompwd}" ]
    then
      insline=`grep -n ^password ${pamfile1} | awk -F: '{print $1}' | tail -n 1`
      eval sed -i '${insline}a\password\ \ \ \ required\ \ \ \ \ \ pam_cracklib.so\ minlen=${pwdminlennew}' ${pamfile1}
      echo "> 已添加参数pam_cracklib.so minlen=${pwdminlennew}" >>  ${bllogs}
    else
      eval sed -i '/pam_cracklib.so/s/$/&\ minlen=${pwdminlennew}/g' ${pamfile1}
      echo "> 已追加参数minlen=${pwdminlennew}" >>  ${bllogs}
    fi
  fi
else
  echo "> 找不到文件${pamfile1}" >>  ${bllogs}
fi
if [ -e ${pamfile2} ]
then
  pamcompwd=`grep '^password' ${pamfile2} | grep required | grep pam_cracklib.so | grep minlen`
  if [ -n "${pamcompwd}" ]
  then
    pwdminlen=`echo "${pamcompwd}" | awk -F'=' '{print $2}' | awk '{print $1}'`
    if [ ${pwdminlen} -ge ${pwdminlennew} ]
    then
      echo '> 当前口令最小长度符合要求,无需修改' >>  ${bllogs}
    else
      eval sed -i '/minlen/s/${pwdminlen}/${pwdminlennew}/g' ${pamfile2}
      echo "> 已经将参数minlen的值由${pwdminlen}修改为${pwdminlennew}" >>  ${bllogs}
    fi
  else
    pamcompwd=`grep '^password' ${pamfile2} | grep required | grep pam_cracklib.so`
    if [ -z "${pamcompwd}" ]
    then
      insline=`grep -n ^password ${pamfile2} | awk -F: '{print $1}' | tail -n 1`
      eval sed -i '${insline}a\password\ \ \ \ required\ \ \ \ \ \ pam_cracklib.so\ minlen=${pwdminlennew}' ${pamfile2}
      echo "> 已添加参数pam_cracklib.so minlen=${pwdminlennew}" >>  ${bllogs}
    else
      eval sed -i '/pam_cracklib.so/s/$/&\ minlen=${pwdminlennew}/g' ${pamfile2}
      echo "> 已追加参数minlen=${pwdminlennew}" >>  ${bllogs}
    fi
  fi
else
  echo "> 找不到文件${pamfile2}" >>  ${bllogs}
fi
if [ -e ${logindef} ]
then
  pamcompwd=`grep '^PASS_MIN_LEN' ${logindef} | awk '{print $2}'`
  if [ ${pamcompwd} -ge ${pwdminlennew} ]
  then
    echo '> 密码长度配置正确,无需修改' >>  ${bllogs}
  else
    eval sed -i '/^PASS_MIN_LEN/s/${pamcompwd}/${pwdminlennew}/g' ${logindef}
    echo "> 已修改密码最小长度为${pwdminlennew}" >>  ${bllogs}
  fi
else
  echo "> 找不到文件${logindef}" >>  ${bllogs}
fi
}

# 设置密码复杂度
SETPWDCOMPLEX () {
echo "# 设置密码复杂度 #" >> ${bllogs}
if [ -e ${pamfile2} ]
then
  pwdcpxlen=`egrep 'ucredit|lcredit|dcredit|ocredit' ${pamfile2} | tr " " "\n" | egrep 'ucredit|lcredit|dcredit|ocredit' | awk 'END{print NR}'`
  if [ -z ${pwdcpxlen} ] || [ ${pwdcpxlen} -eq 0 ]
  then
   sed -i '/pam_cracklib.so/s/$/&\ ucredit=-1\ lcredit=-1\ dcredit=-1/g' ${pamfile2}
   echo '> 已添加参数 ucredit=-1 lcredit=-1 dcredit=-1' >>  ${bllogs}
  elif [ ${pwdcpxlen} -ge 3 ]
  then
    echo '> 当前密码复杂度符合要求,无需修改' >>  ${bllogs}
  else
    echo -e "! 当前密码复杂度不符合要求\n! 请修改${pamfile2}\n! 添加以下参数中的至少3种:\n! ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1" >>  ${bllogs}
  fi
else
  echo "> 找不到文件${pamfile2}" >>  ${bllogs}
fi
}

# 设置口令生存周期
SETPWDLIFE () {
echo "# 设置口令生存周期 #" >> ${bllogs}
if [ -e ${logindef} ]
then
  pwdlife=`grep '^PASS_MAX_DAYS' ${logindef} | awk '{print $2}'`
  if [ ${pwdlife} -le ${pwdlifenew} ]
  then
    echo '> 密码生存周期配置正确,无需修改' >>  ${bllogs}
  else
    eval sed -i '/^PASS_MAX_DAYS/s/${pwdlife}/${pwdlifenew}/g' ${logindef}
    echo "> 已修改密码生存周期为${pwdlifenew}" >>  ${bllogs}
  fi
else
  echo "> 找不到文件${logindef}" >>  ${bllogs}
fi
}

# 配置命令行界面超时时间
AUTOLOGOUT () {
echo "# 设置命令行界面超时时间 #" >> ${bllogs}
prflogout=`grep export ${prfile} | grep TMOUT`
if [ -z "${prflogout}" ]
then
  insline=`grep -n ^export ${prfile} | awk -F: '{print $1}' | tail -n 1`
  eval sed -i '${insline}a\export\ TMOUT=${logoutimenew}' ${prfile}
  source ${prfile}
  echo "> 已添加命令行界面超时时间为${logoutimenew}秒" >>  ${bllogs}
else
  logoutime=`grep ^export ${prfile} | grep TMOUT | awk -F'=' '{print $2}' | sed 's/\ //g'`
  if [ ${logoutime} -ge ${logoutimenew} ]
  then
    eval sed -i '/TMOUT/s/${logoutime}/${logoutimenew}/g' ${prfile}
    source ${prfile}
    echo "> 已经修改自动退出时间为${logoutimenew}秒" >>  ${bllogs}
  else
    echo '> 系统自动退出时间符合要求,无需修改' >>  ${bllogs}
  fi
fi
}

# 修改MASK设置
CHECKMASK () {
echo "# 检查MASK设置 #" >> ${bllogs}
for file in ${umask1} ${umask2} ${umask3}
do
  umaskvs=`egrep -v "^* #|^#" ${file} | grep umask | awk '{print $2}' | sed 's/[^0-9]//g' | awk 'END{print NR}'`
  if [ ${umaskvs} -eq 2 ]
  then
    umaskv1=`egrep -vn "^* #|^#" ${file} | grep umask | sed 's/[^0-9:]//g' | head -n 1 | awk -F':' '{print $2}'`
    umaskv2=`egrep -vn "^* #|^#" ${file} | grep umask | sed 's/[^0-9:]//g' | tail -n 1 | awk -F':' '{print $2}'`
    if [ "${umaskv1}" -ge "${unoroot}" ]
    then
      echo "> 文件${file}中所设置的umask为${umaskv1},无需调整" >>  ${bllogs}
    else
      if [ ${autormask} -eq 1 ]
      then
        insline=`egrep -vn "^* #|^#" ${file} | grep umask | sed 's/[^0-9:]//g' | head -n 1 | awk -F':' '{print $1}'`
        eval sed -i '${insline}s/${umaskv1}/${unoroot}/g' ${file}
        echo -e "! 文件${file}中的umask已经由${umaskv1}改为${unoroot}" >> ${bllogs}
      else
        echo -e "! 文件${file}中的umask为${umaskv1},不符合要求\n! 请修改为安全的MASK值,建议${unoroot}" >>  ${bllogs}
      fi
    fi
    if [ "$umaskv2" -ge "${uisroot}" ]
    then
      echo "> 文件${file}中所设置的umask为${umaskv2},无需调整" >>  ${bllogs}
    else
      if [ ${autormask} -eq 1 ]
      then
        insline=`egrep -vn "^* #|^#" ${file} | grep umask | sed 's/[^0-9:]//g' | tail -n 1 | awk -F':' '{print $1}'`
        eval sed -i '${insline}s/${umaskv2}/${uisroot}/g' ${file}
        echo -e "! 文件${file}中的umask已经由${umaskv2}改为${uisroot}" >> ${bllogs}
      else
        echo -e "! 文件${file}中的umask为${umaskv2},不符合要求\n! 请修改为安全的MASK值,建议${uisroot}" >>  ${bllogs}
      fi
    fi
  elif [ ${umaskvs} -eq 3 -o ${umaskvs} -eq 1 ]
  then
    umaskv3=`egrep -vn "^* #|^#" ${file} | grep umask | sed 's/[^0-9:]//g' | tail -n 1 | awk -F':' '{print $2}'`
    if [ "${umaskv3}" -ge "${stdmask}" ]
    then
      echo "> 文件${file}中自设的全局umask为${umaskv3},无需调整" >> ${bllogs}
    else
      if [ ${autormask} -eq 1 ]
      then
        insline=`egrep -vn "^* #|^#" ${file} | grep umask | sed 's/[^0-9:]//g' | tail -n 1 | awk -F':' '{print $1}'`
        eval sed -i '${insline}s/${umaskv3}/${stdmask}/g' ${file}
        echo -e "! 文件${file}中的umask已经由${umaskv1}改为${unoroot}" >> ${bllogs}
      else
        echo -e "! 文件${file}中自设的全局umask为${umaskv3},不符合要求\n! 请修改为安全的MASK值,建议${unoroot}" >>  ${bllogs}
      fi
    fi
  else
    echo -e "! 文件${file}已被重度修改\n! 请手动检查并修改umask的设置" >> ${bllogs}
  fi
done
}

# 修改SNMP默认团体字
SETSNMPPUB () {
echo "# 修改SNMP默认团体字 #" >> ${bllogs}
snmprpm=`rpm -qa net-snmp`
snmpcfg="/etc/snmp/snmpd.conf"
if [ -e "${snmpcfg}" ]
then
  comname=`grep ^com2sec ${snmpcfg} | grep public`
  if [ -n "${comname}" ]
  then
    eval sed -i '/^com2sec/s/public/${comnamenew}/g' ${snmpcfg}
    echo "> 已经修改默认团体名为${comnamenew}" >>  ${bllogs}
  else
    echo '> 默认团体字不是public,无需修改' >>  ${bllogs}
  fi
else
  [ -n "${snmprpm}" ] && echo '! 系统已安装SNMP,但未找到配置文件' >>  ${bllogs} || echo '> 系统未安装SNMP,无需修改' >>  ${bllogs}
fi
}

# 禁止UID为0的用户
BANUID () {
echo "# 禁止UID为0的用户 #" >> ${bllogs}
userids=`grep -v root /etc/passwd | awk -F: '{print $1" "$3}' | grep -w 0 | awk '{print $1}'`
if [ -n "${userids}" ]
then
  for username in ${userids[@]}
  do
    usermod -L ${username}
    echo "> 已锁定UID为0的账号${username}" >> ${bllogs}
  done
else
  echo "> 不存在UID为0的账号" >> ${bllogs}
fi
}

# 禁用Ctrl+Alt+Del组合键
BANKEYCAD () {
echo "# 禁用Ctrl+Alt+Del组合键 #" >> ${bllogs}
cadtarget="/usr/lib/systemd/system/ctrl-alt-del.target"
if [ -e "${cadtarget}" ]
then
  rm -f ${cadtarget}
  init q
  echo "> 已删除文件并禁用ctrl+alt+del组合键" >> ${bllogs}
else
  echo "> 系统已禁用禁用ctrl+alt+del组合键,无需修改" >> ${bllogs}
fi
}

# 配置用户所需最小权限
SETUSERLMT () {
echo "# 配置用户所需最小权限 #" >> ${bllogs}
chmod ${modpwdgrp} /etc/group
echo "> 修改文件/etc/group属性为${modpwdgrp}" >> ${bllogs}
chmod ${modpwdgrp} /etc/passwd
echo "> 修改文件/etc/passwd属性为${modpwdgrp}" >> ${bllogs}
chmod ${modshadow} /etc/shadow
echo "> 修改文件/etc/shadow属性为${modshadow}" >> ${bllogs}
}

# 配置密码重复使用次数限制
PWDREUTIME () {
echo "# 配置密码重复使用次数限制 #" >> ${bllogs}
if [ -e ${pamfile2} ]
then
  pwdreuse=`grep ^password ${pamfile2} | grep sufficient | grep remember | awk -F'=' '{print $2}' | awk '{print $1}'`
  if [ -z ${pwdreuse} ]
  then
    insline=`grep -n ^password ${pamfile2} | grep sufficient | awk -F: '{print $1}' | tail -n 1`
    eval sed -i '${insline}s/$/\&\ remember=${pwdreusnew}/g' ${pamfile2}
    echo "> 已添加参数 remember=${pwdreusnew}" >>  ${bllogs}
  elif [ ${pwdreuse} -le ${pwdreusnew} ]
  then
    echo '> 密码重复使用次数限制符合要求,无需修改' >>  ${bllogs}
  else
    insline=`grep -n ^password ${pamfile2} | grep sufficient | awk -F: '{print $1}' | tail -n 1`
    eval sed -i '${insline}s/${pwdreuse}/${pwdreusnew}/g' ${pamfile2}
    echo "> 已将参数remember的值由${pwdreuse}修改为${pwdreusnew}" >>  ${bllogs}
  fi
else
  echo "> 找不到文件${pamfile2}" >>  ${bllogs}
fi
}

# 禁止ICMP重定向和源路由
BANICMPR () {
echo "# 禁止ICMP重定向和源路由 #" >> ${bllogs}
icmpredrct=`grep ^net.ipv4.conf.all.accept_redirects ${sysctlcfg} | awk -F= '{print $2}' | sed 's/[^0-9]//g'`
if [ -z ${icmpredrct} ]
then
  echo 'net.ipv4.conf.all.accept_redirects=0' >> ${sysctlcfg}
  echo '> 已添加ICMP重定向配置' >> ${bllogs}
elif [ ${icmpredrct} -eq 0 ]
then
  echo '> 系统已配置ICMP重定向,无需修改' >>  ${bllogs}
else
  eval sed -i '/^net.ipv4.conf.all.accept_redirects/s/${icmpredrct}/0/g' ${sysctlcfg}
  echo '> 已修改ICMP重定向配置' >>  ${bllogs}
fi
icmpsrcrut=`grep ^net.ipv4.conf.all.accept_source_route ${sysctlcfg} | awk -F= '{print $2}' | sed 's/[^0-9]//g'`
if [ -z ${icmpsrcrut} ]
then
  echo 'net.ipv4.conf.all.accept_source_route=0' >> ${sysctlcfg}
  echo '> 已添加ICMP源路由配置' >> ${bllogs}
elif [ ${icmpsrcrut} -eq 0 ]
then
  echo '> 系统已配置ICMP源路由,无需修改' >>  ${bllogs}
else
  eval sed -i '/^net.ipv4.conf.all.accept_source_route/s/${icmpsrcrut}/0/g' ${sysctlcfg}
  echo '> 已修改ICMP源路由配置' >>  ${bllogs}
fi
if [ -z ${icmpredrct} ] || [ -z ${icmpsrcrut} ] || [ ${icmpredrct} -ne 0 ] || [ ${icmpsrcrut} -ne 0 ]
then
  sysctl -p
fi
}

##### 开始调整系统基线 #####
# 锁定额外系统用户
# 请修改需要锁定的账号
lockusers=(bin daemon adm uucp mail)
LOCKUSER
# 禁止root远程登录
# 立即重启sshd请将erstsshd修改为1
erstsshd=0
BANROOTRLOGIN
# 配置telnet服务
# 默认Linux6系统将卸载telnet
# 若不卸载请修改rmtelnet为0
rmtelnet=1
REMOVETELNET
# 设置密码最小长度
# 请修改密码最小长度
pwdminlennew=6
SETPWDMINLEN
# 设置密码复杂度(须先配置密码最小长度)
SETPWDCOMPLEX
# 设置口令生存周期
# 请修改口令生存周期
pwdlifenew=90
SETPWDLIFE
# 配置命令行界面超时时间
logoutimenew=180
AUTOLOGOUT
# 修改MASK设置
# 请修改MASK标准建议值
unoroot=027
uisroot=077
# 请修改已自设的全局MASK建议值
stdmask=027
# 如果需要自动修改MASK为建议值
# 将autormask的值改为1
autormask=0
CHECKMASK
# 修改SNMP默认团体字(更新使用方配置的团体名)
# 请修改默认团体字名称
comnamenew="mycomname"
SETSNMPPUB
# 禁止UID为0的用户
BANUID
# 禁用Ctrl+Alt+Del组合键
BANKEYCAD
# 配置用户所需最小权限
# 请修改文件属性值
modpwdgrp=644
modshadow=600
SETUSERLMT
# 检查密码重复使用次数限制
# 请设置密码重复使用次数
pwdreusnew=5
PWDREUTIME
# 禁止ICMP重定向和源路由
BANICMPR

grep '^!' ${bllogs}

原创文章禁止转载:技术学堂 » Linux操作系统基线设置自动化脚本(Shell版)

精彩评论

4+8=

感谢您的支持与鼓励

支付宝扫一扫打赏

微信扫一扫打赏