7 Commits

View File

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/sh
set -e
########## 一些配置 ########## ########## 一些配置 ##########
@ -11,106 +12,240 @@ script_url="{{ SCRIPT_URL }}"
############ 脚本区 ########## ############ 脚本区 ##########
script_params=$* # 初始化参数变量
has_param() { arg_help="false"
for param in $script_params; do arg_cron="false"
for tParam in $@; do arg_cron_val=""
if [ "$tParam" == "$param" ]; then arg_only_update_keys="false"
echo "true" arg_update_self="false"
return arg_uninstall="false"
fi arg_no_install_sshd="false"
done arg_allow_root_passwd="false"
done arg_allow_root_passwd_val=""
echo "false"
}
get_param_value() { # 解析参数
local find=false while [ $# -gt 0 ]; do
for param in $script_params; do case "$1" in
if [ "$find" == "true" ]; then -h|--help)
if [[ $param == -* ]]; then arg_help="true"
return shift
fi ;;
echo $param -c|--cron)
return arg_cron="true"
fi arg_cron_val="$2"
for tParam in $@; do shift 2
if [ "$tParam" == "$param" ]; then ;;
find=true -o|--only-update-keys)
break arg_only_update_keys="true"
fi shift
done ;;
done -u|--update-self)
} arg_update_self="true"
shift
;;
--uninstall)
arg_uninstall="true"
shift
;;
-n|--no-install-sshd)
arg_no_install_sshd="true"
shift
;;
-p|--allow-root-passwd)
arg_allow_root_passwd="true"
arg_allow_root_passwd_val="$2"
shift 2
;;
*)
shift
;;
esac
done
# 帮助信息. # 帮助信息.
if [ $(has_param "-h" "--help") == "true" ]; then if [ "$arg_help" = "true" ]; then
echo "Usage: $0 [options]" echo "Usage: $0 [options]"
echo "Options:" echo "Options:"
echo " -h, --help Print this help message." echo " -h, --help Print this help message."
echo "" echo ""
echo "Available to any user: " echo "Available to any user: "
echo " -c, --cron [cron | false] Configure Crontab to automatically update ssh keys," echo " -c, --cron \"<cron> | false\" Configure Crontab to automatically update ssh keys."
echo " Cron expression can be specified, If false is specified, " echo " Cron expression MUST be quoted (e.g., \"* 0 * * *\")."
echo " Crontab settings will be deleted automatically." echo " If 'false' is specified, Crontab settings will be deleted."
echo "" echo ""
echo " -o, --only-update-keys Only update SSH keys, do not configure ssh server." echo " -o, --only-update-keys Only update SSH keys, do not configure ssh server."
echo " -u, --update-self Update this script to the latest version." echo " -u, --update-self Update this script to the latest version."
echo " --uninstall Uninstall this script (remove cron and local files)."
echo "" echo ""
echo "only available when the script is executed as root:" echo "only available when the script is executed as root:"
echo " -n, --no-install-sshd Do not install SSH Server." echo " -n, --no-install-sshd Do not install SSH Server."
echo " -p, --allow-root-passwd <yes | no> Allow Root to log in with a password." echo " -p, --allow-root-passwd <yes | no> Allow Root to log in with a password."
echo "" echo ""
exit 0 exit 0
fi fi
update_sshkeys() { reload_sshd_service() {
if [ "$sshkey_url" == "" ]; then if command -v systemctl >/dev/null 2>&1; then
echo "Please specify the URL of the SSH public key." systemctl reload sshd
exit 1 elif command -v service >/dev/null 2>&1; then
service sshd reload || service ssh reload
elif [ -f /etc/init.d/sshd ]; then
/etc/init.d/sshd reload
elif [ -f /etc/init.d/ssh ]; then
/etc/init.d/ssh reload
else
return 1
fi fi
echo "Downloading SSH public key from '$sshkey_url'"
mkdir -p ~/.ssh
local ssh_keys=$(curl -s $sshkey_url)
if [ $? -ne 0 ] || [ "$ssh_keys" == "" ]; then
echo "Failed to download SSH public key at $(date '+%Y-%m-%d %H:%M:%S')"
exit 1
fi
echo "-------------------- SSH Keys --------------------"
echo "$ssh_keys"
echo "--------------------------------------------------"
echo "$ssh_keys" > ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# 输出更新成功,需要附带时间日期
echo "SSH public key updated successfully at $(date '+%Y-%m-%d %H:%M:%S')"
} }
update_sshkeys() {
case "$sshkey_url" in
""|"{{"*)
echo "ERROR: sshkey_url is not configured."
exit 1
;;
esac
echo "Downloading SSH public key from '$sshkey_url'"
mkdir -p ~/.ssh
chmod 700 ~/.ssh
dl_tmp_file="$HOME/.ssh/authorized_keys.dl.tmp"
if ! curl -sL "$sshkey_url" -o "$dl_tmp_file"; then
echo "Failed to download SSH public key at $(date '+%Y-%m-%d %H:%M:%S')"
rm -f "$dl_tmp_file"
exit 1
fi
if [ ! -s "$dl_tmp_file" ] || ! grep -qE "(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp)" "$dl_tmp_file"; then
echo "Downloaded file is empty or does not contain valid SSH key types at $(date '+%Y-m-d %H:%M:%S')"
echo "Aborting update to prevent lockout."
rm -f "$dl_tmp_file"
exit 1
fi
echo "-------------------- SSH Keys --------------------"
cat "$dl_tmp_file"
echo "--------------------------------------------------"
auth_file="$HOME/.ssh/authorized_keys"
new_auth_file="$HOME/.ssh/authorized_keys.new.tmp"
# 受管理文本块标记
begin_marker="# --- BEGIN MANAGED BY CONF-SSHD SCRIPT ---"
end_marker="# --- END MANAGED BY CONF-SSHD SCRIPT ---"
managed_block_found="false"
inside_managed_block="false"
touch "$auth_file"
: > "$new_auth_file"
while IFS= read -r line || [ -n "$line" ]; do
if [ "$line" = "$begin_marker" ]; then
managed_block_found="true"
inside_managed_block="true"
{
echo "$begin_marker"
cat "$dl_tmp_file"
echo "$end_marker"
} >> "$new_auth_file"
elif [ "$line" = "$end_marker" ]; then
inside_managed_block="false"
elif [ "$inside_managed_block" = "false" ]; then
echo "$line" >> "$new_auth_file"
fi
done < "$auth_file"
if [ "$managed_block_found" = "false" ]; then
if [ -s "$new_auth_file" ]; then
if [ "$(tail -c 1 "$new_auth_file")" != "" ]; then
# 最后一个字符不是换行符,添加一个
echo "" >> "$new_auth_file"
fi
fi
{
echo "$begin_marker"
cat "$dl_tmp_file"
echo "$end_marker"
} >> "$new_auth_file"
fi
mv "$new_auth_file" "$auth_file"
rm -f "$dl_tmp_file"
chmod 600 "$auth_file"
echo "SSH public key updated successfully (managed block only) at $(date '+%Y-%m-%d %H:%M:%S')"
}
# 检查是否指定了 --uninstall
if [ "$arg_uninstall" = "true" ]; then
echo "Uninstalling conf-sshd (disabling auto-updates)..."
if [ "$(command -v crontab)" != "" ]; then
echo "Removing Crontab entry..."
( (crontab -l 2>/dev/null || true) | grep -F -v "conf-sshd.sh") | crontab -
else
echo "Crontab utility not found, skipping Crontab removal."
fi
script_dir="$HOME/.conf-sshd"
if [ -d "$script_dir" ]; then
echo "Removing script files from $script_dir..."
rm -rf "$script_dir"
else
echo "Script directory $script_dir not found, skipping removal."
fi
echo "Uninstall complete."
echo "Note: authorized_keys managed block and sshd_config were NOT affected."
exit 0
fi
# 检查是否只更新密钥. # 检查是否只更新密钥.
if [ $(has_param "-o" "--only-update-keys") == "true" ]; then if [ "$arg_only_update_keys" = "true" ]; then
update_sshkeys update_sshkeys
exit 0 exit 0
fi fi
# 检查是否指定了 --update-self # 检查是否指定了 --update-self
if [ $(has_param "-u" "--update-self") == "true" ]; then if [ "$arg_update_self" = "true" ]; then
echo "Updating conf-sshd script..." echo "Updating conf-sshd script..."
cp $0 ~/.conf-sshd/conf-sshd.sh.bak mkdir -p ~/.conf-sshd
curl -s $script_url > $0 || cp ~/.conf-sshd/conf-sshd.sh.bak $0 && echo "Script update failed at $(date '+%Y-%m-%d %H:%M:%S')" && exit 1 target_script="$HOME/.conf-sshd/conf-sshd.sh"
chmod +x ~/.conf-sshd/conf-sshd.sh
if [ -f "$target_script" ]; then
cp "$target_script" "$target_script.bak"
fi
# 下载到临时文件
if ! curl -sL "$script_url" -o "$target_script.tmp"; then
echo "Script download failed at $(date '+%Y-%m-%d %H:%M:%S')"
rm -f "$target_script.tmp"
exit 1
fi
mv "$target_script.tmp" "$target_script"
chmod +x "$target_script"
echo "Script updated successfully at $(date '+%Y-%m-%d %H:%M:%S')" echo "Script updated successfully at $(date '+%Y-%m-%d %H:%M:%S')"
exit 0 exit 0
fi fi
# 检查 /usr/sbin/sshd 是否存在,且 /usr/sbin/sshd 执行后退出代码为 0 # 检查 SSHD 是否安装.
/usr/sbin/sshd -T > /dev/null if ! command -v sshd >/dev/null 2>&1 && [ ! -x /usr/sbin/sshd ] && [ "$arg_no_install_sshd" = "false" ]; then
if [ $? -ne 0 ] && [ $(has_param "-n" "--no-install-sshd") == "false" ]; then if [ "$(id -u)" -eq 0 ]; then
if [ $(id -u) -eq 0 ]; then
echo "The ssh server is not installed, and the script is executed as root, so it will be installed." echo "The ssh server is not installed, and the script is executed as root, so it will be installed."
if [ -f /etc/redhat-release ]; then if [ -f /etc/redhat-release ]; then
yum install -y openssh-server yum install -y openssh-server
elif [ -f /etc/debian_version ]; then elif [ -f /etc/debian_version ]; then
apt-get update apt-get update
apt-get install -y openssh-server apt-get install -y openssh-server
elif [ -f /etc/alpine-release ]; then
apk add openssh
fi fi
echo "The ssh server has been installed." echo "The ssh server has been installed."
else else
@ -122,23 +257,40 @@ else
fi fi
# 检查是否指定了 --allow-root-passwd # 检查是否指定了 --allow-root-passwd
if [ $(has_param "-p" "--allow-root-passwd") == "true" ]; then if [ "$arg_allow_root_passwd" = "true" ]; then
# 检查当前用户是否为 root # 检查当前用户是否为 root
if [ $(id -u) -eq 0 ]; then if [ "$(id -u)" -eq 0 ]; then
# 获取参数值 allow_root_passwd=$(echo "$arg_allow_root_passwd_val" | tr '[:upper:]' '[:lower:]')
allow_root_passwd=$(get_param_value "-p" "--allow-root-passwd" | tr '[:upper:]' '[:lower:]')
if [ "$allow_root_passwd" == "yes" ]; then sshd_config_file="/etc/ssh/sshd_config"
# 设置允许 root 使用密码登录 new_sshd_permit_root_login_setting=""
sed -i 's/^#?PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config
echo "Root user is allowed to log in with password." if [ "$allow_root_passwd" = "yes" ]; then
elif [ "$allow_root_passwd" == "no" ]; then new_sshd_permit_root_login_setting="PermitRootLogin yes"
# 设置禁止 root 使用密码登录 echo "Setting: Root user is allowed to log in with password."
sed -i 's/^#?PermitRootLogin.*/PermitRootLogin prohibit-password/g' /etc/ssh/sshd_config elif [ "$allow_root_passwd" = "no" ]; then
echo "Root user is prohibited from logging in with password." new_sshd_permit_root_login_setting="PermitRootLogin prohibit-password"
echo "Setting: Root user is prohibited from logging in with password."
else else
echo "Please specify whether to allow root to log in with a password." echo "Please specify 'yes' or 'no' for --allow-root-passwd."
exit 1 exit 1
fi fi
if grep -qE '^#?PermitRootLogin' "$sshd_config_file"; then
sed "s@^#\?PermitRootLogin.*@$new_sshd_permit_root_login_setting@g" "$sshd_config_file" > "$sshd_config_file.tmp" && mv "$sshd_config_file.tmp" "$sshd_config_file"
else
echo "$new_sshd_permit_root_login_setting" >> "$sshd_config_file"
fi
if ! reload_sshd_service; then
echo "----------------------------------------------------"
echo "WARNING: Failed to reload sshd service!"
echo "Please check service status manually."
echo "----------------------------------------------------"
else
echo "SSHD config updated. Now you can use password to login root user."
fi
else else
echo "The script is executed as a non-root user and cannot set whether to allow root to log in with a password." echo "The script is executed as a non-root user and cannot set whether to allow root to log in with a password."
exit 1 exit 1
@ -149,16 +301,18 @@ fi
update_sshkeys update_sshkeys
# 检查是否指定了 --cron # 检查是否指定了 --cron
if [ $(has_param "-c" "--cron") == "true" ]; then if [ "$arg_cron" = "true" ]; then
# 检查 Crontab 是否已安装 # 检查 Crontab 是否已安装
if [ "$(command -v crontab)" == "" ]; then if [ "$(command -v crontab)" = "" ]; then
if [ $(id -u) -eq 0 ]; then if [ "$(id -u)" -eq 0 ]; then
echo "The crontab is not installed, and the script is executed as a root user, so it will be installed." echo "The crontab is not installed, and the script is executed as a root user, so it will be installed."
if [ -f /etc/redhat-release ]; then if [ -f /etc/redhat-release ]; then
yum install -y crontabs yum install -y crontabs
elif [ -f /etc/debian_version ]; then elif [ -f /etc/debian_version ]; then
apt-get update apt-get update
apt-get install -y cron apt-get install -y cron
elif [ -f /etc/alpine-release ]; then
apk add cron
fi fi
echo "The crontab has been installed." echo "The crontab has been installed."
else else
@ -168,38 +322,46 @@ if [ $(has_param "-c" "--cron") == "true" ]; then
else else
echo "The crontab is already installed." echo "The crontab is already installed."
fi fi
cron=$(get_param_value "-c" "--cron" | tr '[:upper:]' '[:lower:]') cron=$(echo "$arg_cron_val" | tr '[:upper:]' '[:lower:]')
if [ "$cron" == "false" ]; then if [ "$cron" = "false" ]; then
# 检查 Crontab 是否已经设置 # 检查 Crontab 是否已经设置
if [ "$(crontab -l | grep "conf-sshd.sh")" == "" ]; then if [ "$( (crontab -l 2>/dev/null || true) | grep -F -c "conf-sshd.sh" )" -eq 0 ]; then
echo "Crontab will not be configured." echo "Crontab already clean. Will not be configured."
exit 0 exit 0
else else
crontab -l | grep -v "conf-sshd.sh" | crontab - (crontab -l 2>/dev/null || true) | grep -F -v "conf-sshd.sh" | crontab -
echo "Crontab has been removed." echo "Crontab has been removed."
exit 0 exit 0
fi fi
else else
if [ "$cron" == "" ]; then if [ "$cron" = "" ]; then
cron=$default_cron cron=$default_cron
fi fi
# 将当前脚本移动到 ~/.conf-sshd/conf-sshd.sh 中. # 将当前脚本移动到 ~/.conf-sshd/conf-sshd.sh 中.
mkdir -p ~/.conf-sshd mkdir -p ~/.conf-sshd
# 检查当前脚本是否为文件 target_script="$HOME/.conf-sshd/conf-sshd.sh"
if [ ! -f $0 ]; then if [ ! -f "$0" ]; then
echo "Downloading conf-sshd script..." echo "Downloading conf-sshd script..."
curl -o ~/.conf-sshd/conf-sshd.sh $script_url if ! curl -sL "$script_url" -o "$target_script.tmp"; then
echo "Script download failed at $(date '+%Y-m-d %H:%M:%S')"
rm -f "$target_script.tmp"
exit 1
fi
mv "$target_script.tmp" "$target_script"
else else
echo "Copying conf-sshd script..." echo "Copying conf-sshd script..."
cp $0 ~/.conf-sshd/conf-sshd.sh cp "$0" "$target_script"
fi fi
chmod +x ~/.conf-sshd/conf-sshd.sh
chmod +x "$target_script"
echo "Install conf-sshd script successfully." echo "Install conf-sshd script successfully."
# 将当前脚本追加到当前用户的 Crontab 中 # 将当前脚本追加到当前用户的 Crontab 中
crontab -l > ~/.conf-sshd/crontab.old echo "Configuring Crontab..."
echo '$cron "/bin/bash ~/.conf-sshd/conf-sshd.sh -o" >> ~/.conf-sshd/run.log' >> ~/.conf-sshd/crontab.old cron_command="/bin/sh $target_script -o >> $HOME/.conf-sshd/run.log 2>&1"
crontab ~/.conf-sshd/crontab.old cron_job="$cron $cron_command"
rm ~/.conf-sshd/crontab.old
( (crontab -l 2>/dev/null || true) | grep -F -v "conf-sshd.sh") | { cat; echo "$cron_job"; } | crontab -
echo "Crontab has been configured.(Cron: '$cron')" echo "Crontab has been configured.(Cron: '$cron')"
fi fi
fi fi