Update SSH密钥部署及安全加固脚本
This commit is contained in:
336
SSH密钥部署及安全加固脚本
336
SSH密钥部署及安全加固脚本
@@ -1,52 +1,59 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# SSH密钥部署及安全加固脚本
|
# 完全自动化SSH密钥部署脚本
|
||||||
# 功能:
|
# 功能:一键生成通用SSH密钥并自动部署到当前服务器
|
||||||
# 1. 自动生成SSH密钥对(默认密码:88888888)
|
# 特性:
|
||||||
# 2. 部署公钥到多台服务器
|
# 1. 完全自动化,无需任何交互
|
||||||
# 3. 安全加固:禁用密码登录(仅在所有密钥部署验证成功后)
|
# 2. 生成通用密钥对,固定密码88888888
|
||||||
# 4. 提供回滚机制防止锁定
|
# 3. 自动将公钥部署到当前服务器的authorized_keys
|
||||||
|
# 4. 自动加固SSH配置(禁用密码登录)
|
||||||
|
# 5. 生成的密钥可在多台服务器上通用
|
||||||
|
|
||||||
# 配置参数
|
# 配置参数
|
||||||
KEY_DIR="$HOME/.ssh" # 密钥存放目录
|
KEY_DIR="$HOME/.ssh"
|
||||||
KEY_NAME="auto_key" # 密钥名称
|
KEY_NAME="universal_ssh_key"
|
||||||
KEY_PASSWORD="88888888" # 固定密钥密码
|
KEY_PASS="88888888"
|
||||||
KEY_TYPE="ed25519" # 默认使用更安全的Ed25519算法
|
KEY_TYPE="ed25519"
|
||||||
SSH_PORT="22" # 默认SSH端口
|
SSH_PORT="22"
|
||||||
TEMP_BACKUP="/tmp/ssh_backup" # 临时备份目录
|
BACKUP_DIR="/tmp/ssh_setup_backup_$(date +%s)"
|
||||||
LOCKFILE="/tmp/ssh_secure.lock" # 安全操作锁文件
|
|
||||||
|
|
||||||
# 颜色定义
|
# 颜色定义
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
BLUE='\033[0;34m'
|
NC='\033[0m'
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# 检查并安装依赖
|
# 日志函数
|
||||||
|
log() {
|
||||||
|
echo -e "$(date '+%Y-%m-%d %H:%M:%S') $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 安装必要依赖
|
||||||
install_deps() {
|
install_deps() {
|
||||||
local deps=(ssh-keygen ssh sshpass expect)
|
log "${YELLOW}检查系统依赖...${NC}"
|
||||||
|
local pkgs=(ssh-keygen ssh sshpass expect)
|
||||||
local missing=()
|
local missing=()
|
||||||
|
|
||||||
for dep in "${deps[@]}"; do
|
for pkg in "${pkgs[@]}"; do
|
||||||
if ! command -v "$dep" &>/dev/null; then
|
if ! command -v "$pkg" &>/dev/null; then
|
||||||
missing+=("$dep")
|
missing+=("$pkg")
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ${#missing[@]} -gt 0 ]; then
|
if [ ${#missing[@]} -gt 0 ]; then
|
||||||
echo -e "${YELLOW}正在安装依赖: ${missing[*]}${NC}"
|
log "${YELLOW}正在安装依赖: ${missing[*]}${NC}"
|
||||||
|
|
||||||
if command -v apt-get &>/dev/null; then
|
if command -v apt-get &>/dev/null; then
|
||||||
apt-get update -qq && apt-get install -y -qq "${missing[@]}" >/dev/null || {
|
apt-get update -qq && apt-get install -y -qq "${missing[@]}" >/dev/null || {
|
||||||
echo -e "${RED}依赖安装失败${NC}"; return 1
|
log "${RED}依赖安装失败${NC}"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
elif command -v yum &>/dev/null; then
|
elif command -v yum &>/dev/null; then
|
||||||
yum install -y -q "${missing[@]}" >/dev/null || {
|
yum install -y -q "${missing[@]}" >/dev/null || {
|
||||||
echo -e "${RED}依赖安装失败${NC}"; return 1
|
log "${RED}依赖安装失败${NC}"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
echo -e "${RED}不支持的包管理器,请手动安装: ${missing[*]}${NC}"
|
log "${RED}不支持的包管理器${NC}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -55,206 +62,157 @@ install_deps() {
|
|||||||
|
|
||||||
# 生成SSH密钥
|
# 生成SSH密钥
|
||||||
generate_key() {
|
generate_key() {
|
||||||
echo -e "${BLUE}正在生成${NC} ${YELLOW}${KEY_TYPE}${NC} ${BLUE}类型SSH密钥...${NC}"
|
log "${YELLOW}正在生成SSH密钥...${NC}"
|
||||||
|
|
||||||
[ -d "$KEY_DIR" ] || mkdir -p "$KEY_DIR"
|
mkdir -p "$KEY_DIR" || {
|
||||||
chmod 700 "$KEY_DIR"
|
log "${RED}无法创建SSH目录${NC}"
|
||||||
|
return 1
|
||||||
ssh-keygen -t "$KEY_TYPE" -C "auto-deploy-key" -N "$KEY_PASSWORD" -f "${KEY_DIR}/${KEY_NAME}" -q || {
|
|
||||||
echo -e "${RED}密钥生成失败${NC}"; return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 生成新密钥
|
||||||
|
ssh-keygen -t "$KEY_TYPE" -C "universal_auto_key" -N "$KEY_PASS" -f "${KEY_DIR}/${KEY_NAME}" -q || {
|
||||||
|
log "${RED}密钥生成失败${NC}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 设置正确权限
|
||||||
|
chmod 700 "$KEY_DIR"
|
||||||
chmod 600 "${KEY_DIR}/${KEY_NAME}"
|
chmod 600 "${KEY_DIR}/${KEY_NAME}"
|
||||||
chmod 644 "${KEY_DIR}/${KEY_NAME}.pub"
|
chmod 644 "${KEY_DIR}/${KEY_NAME}.pub"
|
||||||
|
|
||||||
echo -e "${GREEN}密钥生成成功:${NC}"
|
log "${GREEN}SSH密钥生成成功${NC}"
|
||||||
echo -e "私钥: ${KEY_DIR}/${KEY_NAME}"
|
|
||||||
echo -e "公钥: ${KEY_DIR}/${KEY_NAME}.pub"
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# 测试密钥登录
|
# 部署公钥到本机
|
||||||
test_key_login() {
|
deploy_key_locally() {
|
||||||
local server="$1"
|
log "${YELLOW}正在部署公钥到本机...${NC}"
|
||||||
local user="${2:-root}"
|
|
||||||
|
|
||||||
echo -e "${BLUE}测试密钥登录 ${user}@${server}...${NC}"
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
if ! ssh -i "${KEY_DIR}/${KEY_NAME}" -o PasswordAuthentication=no -o StrictHostKeyChecking=no -o ConnectTimeout=5 \
|
# 备份原密钥
|
||||||
"${user}@${server}" "echo -n" >/dev/null 2>&1; then
|
if [ -f "${KEY_DIR}/authorized_keys" ]; then
|
||||||
echo -e "${RED}密钥登录测试失败 - ${user}@${server}${NC}"
|
cp "${KEY_DIR}/authorized_keys" "${BACKUP_DIR}/authorized_keys.bak" || {
|
||||||
|
log "${RED}authorized_keys备份失败${NC}"
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 添加新公钥
|
||||||
|
if [ -f "${KEY_DIR}/${KEY_NAME}.pub" ]; then
|
||||||
|
mkdir -p "${KEY_DIR}"
|
||||||
|
touch "${KEY_DIR}/authorized_keys"
|
||||||
|
chmod 600 "${KEY_DIR}/authorized_keys"
|
||||||
|
|
||||||
|
# 检查是否已存在相同公钥
|
||||||
|
if ! grep -q "$(cat "${KEY_DIR}/${KEY_NAME}.pub")" "${KEY_DIR}/authorized_keys"; then
|
||||||
|
cat "${KEY_DIR}/${KEY_NAME}.pub" >> "${KEY_DIR}/authorized_keys" || {
|
||||||
|
log "${RED}公钥添加失败${NC}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
log "${GREEN}公钥已添加到本机${NC}"
|
||||||
|
else
|
||||||
|
log "${YELLOW}相同公钥已存在,跳过添加${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "${RED}公钥文件不存在${NC}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${GREEN}密钥登录测试成功 - ${user}@${server}${NC}"
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# 部署公钥到服务器
|
# 安全加固SSH配置
|
||||||
deploy_key() {
|
secure_ssh() {
|
||||||
local server="$1"
|
log "${YELLOW}正在加固SSH配置...${NC}"
|
||||||
local user="${2:-root}"
|
|
||||||
local port="${3:-22}"
|
|
||||||
|
|
||||||
echo -e "${BLUE}正在部署到 ${user}@${server}:${port}...${NC}"
|
# 备份原配置
|
||||||
|
cp /etc/ssh/sshd_config "${BACKUP_DIR}/sshd_config.bak" || {
|
||||||
|
log "${RED}sshd_config备份失败${NC}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# 备份原authorized_keys
|
# 应用安全配置
|
||||||
sshpass -p "$KEY_PASSWORD" ssh -o StrictHostKeyChecking=no -p "$port" "${user}@${server}" \
|
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
|
||||||
"[ -f ~/.ssh/authorized_keys ] && cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.bak" 2>/dev/null
|
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
|
||||||
|
sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
||||||
|
|
||||||
# 部署新密钥
|
# 重新加载SSH服务
|
||||||
if ! sshpass -p "$KEY_PASSWORD" ssh -o StrictHostKeyChecking=no -p "$port" "${user}@${server}" \
|
if systemctl reload sshd >/dev/null 2>&1 || service sshd reload >/dev/null 2>&1; then
|
||||||
"mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
|
log "${GREEN}SSH配置已更新并重载${NC}"
|
||||||
grep -q \"\$(cat ${KEY_DIR}/${KEY_NAME}.pub)\" ~/.ssh/authorized_keys 2>/dev/null || \
|
else
|
||||||
cat ${KEY_DIR}/${KEY_NAME}.pub >> ~/.ssh/authorized_keys && \
|
log "${RED}SSH服务重载失败,正在回滚...${NC}"
|
||||||
chmod 600 ~/.ssh/authorized_keys" 2>/dev/null; then
|
cp "${BACKUP_DIR}/sshd_config.bak" /etc/ssh/sshd_config
|
||||||
echo -e "${RED}公钥部署失败 - ${user}@${server}${NC}"
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# 验证部署
|
# 验证部署
|
||||||
if ! test_key_login "$server" "$user"; then
|
verify_deployment() {
|
||||||
echo -e "${RED}部署验证失败 - ${user}@${server}${NC}"
|
log "${YELLOW}验证密钥登录...${NC}"
|
||||||
# 尝试回滚
|
|
||||||
sshpass -p "$KEY_PASSWORD" ssh -o StrictHostKeyChecking=no -p "$port" "${user}@${server}" \
|
# 测试本地密钥登录
|
||||||
"[ -f ~/.ssh/authorized_keys.bak ] && mv -f ~/.ssh/authorized_keys.bak ~/.ssh/authorized_keys" 2>/dev/null
|
if ssh -i "${KEY_DIR}/${KEY_NAME}" -o PasswordAuthentication=no -o StrictHostKeyChecking=no -o ConnectTimeout=5 localhost "echo 连接测试成功" >/dev/null 2>&1; then
|
||||||
|
log "${GREEN}密钥登录验证成功${NC}"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log "${RED}密钥登录验证失败${NC}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${GREEN}成功部署到 ${user}@${server}${NC}"
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# 安全加固 - 禁用密码登录
|
# 显示成功信息
|
||||||
secure_server() {
|
show_success() {
|
||||||
local server="$1"
|
echo -e "\n${GREEN}✔ SSH密钥部署成功!${NC}"
|
||||||
local user="${2:-root}"
|
echo -e "=============================="
|
||||||
local port="${3:-22}"
|
echo -e "${YELLOW}重要信息:${NC}"
|
||||||
|
echo -e "密钥路径: ${KEY_DIR}/${KEY_NAME}"
|
||||||
# 创建锁文件防止重复操作
|
echo -e "密钥密码: ${KEY_PASS}"
|
||||||
touch "$LOCKFILE"
|
echo -e "\n${YELLOW}使用说明:${NC}"
|
||||||
echo -e "${YELLOW}正在安全加固 ${user}@${server}...${NC}"
|
echo -e "1. 此密钥可在其他服务器上使用相同方法部署"
|
||||||
|
echo -e "2. 连接到其他服务器时使用:"
|
||||||
# 备份原sshd配置
|
echo -e " ssh -i ${KEY_DIR}/${KEY_NAME} 用户名@服务器IP"
|
||||||
ssh -i "${KEY_DIR}/${KEY_NAME}" -o StrictHostKeyChecking=no -p "$port" "${user}@${server}" \
|
echo -e "3. 需要输入密钥密码时使用: ${KEY_PASS}"
|
||||||
"sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak" || {
|
echo -e "\n${RED}⚠ 请确保在其他服务器部署前先备份现有密钥${NC}"
|
||||||
echo -e "${RED}配置备份失败 - ${user}@${server}${NC}"; return 1
|
echo -e "==============================\n"
|
||||||
}
|
|
||||||
|
|
||||||
# 修改配置禁用密码登录
|
|
||||||
ssh -i "${KEY_DIR}/${KEY_NAME}" -o StrictHostKeyChecking=no -p "$port" "${user}@${server}" \
|
|
||||||
"sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config && \
|
|
||||||
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config && \
|
|
||||||
sudo systemctl reload sshd" || {
|
|
||||||
echo -e "${RED}安全配置失败 - ${user}@${server}${NC}"
|
|
||||||
|
|
||||||
# 尝试回滚
|
|
||||||
ssh -i "${KEY_DIR}/${KEY_NAME}" -o StrictHostKeyChecking=no -p "$port" "${user}@${server}" \
|
|
||||||
"sudo mv -f /etc/ssh/sshd_config.bak /etc/ssh/sshd_config && sudo systemctl reload sshd" 2>/dev/null
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# 二次验证
|
|
||||||
if ! test_key_login "$server" "$user"; then
|
|
||||||
echo -e "${RED}安全加固后验证失败 - 正在回滚${NC}"
|
|
||||||
ssh -i "${KEY_DIR}/${KEY_NAME}" -o StrictHostKeyChecking=no -p "$port" "${user}@${server}" \
|
|
||||||
"sudo mv -f /etc/ssh/sshd_config.bak /etc/ssh/sshd_config && sudo systemctl reload sshd" 2>/dev/null
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}安全加固成功 - ${user}@${server}${NC}"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 显示帮助
|
|
||||||
show_help() {
|
|
||||||
echo -e "${BLUE}使用说明:${NC}"
|
|
||||||
echo "1. 仅生成密钥: $0"
|
|
||||||
echo "2. 生成并部署到服务器: $0 [用户名] 服务器1 [服务器2 ...] [端口]"
|
|
||||||
echo -e "\n${YELLOW}示例:${NC}"
|
|
||||||
echo "生成密钥: $0"
|
|
||||||
echo "部署到多台服务器: $0 root server1.example.com server2.example.com 22"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# 主函数
|
# 主函数
|
||||||
main() {
|
main() {
|
||||||
# 检查root权限
|
|
||||||
if [ "$(id -u)" -ne 0 ]; then
|
|
||||||
echo -e "${RED}请使用root用户运行此脚本${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 安装依赖
|
# 安装依赖
|
||||||
install_deps || exit 1
|
install_deps || {
|
||||||
|
log "${RED}依赖安装失败,退出脚本${NC}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# 生成密钥
|
# 生成密钥
|
||||||
generate_key || exit 1
|
generate_key || {
|
||||||
|
log "${RED}密钥生成失败,退出脚本${NC}"
|
||||||
# 如果没有提供服务器参数,则只生成密钥
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
echo -e "${GREEN}SSH密钥已生成,但没有指定部署服务器${NC}"
|
|
||||||
show_help
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 解析参数
|
|
||||||
local user="root"
|
|
||||||
local servers=()
|
|
||||||
local port="22"
|
|
||||||
|
|
||||||
# 第一个参数可能是用户名
|
|
||||||
if [[ "$1" != *.* ]] && [[ "$1" != *:* ]] && [[ "$1" != "root" ]]; then
|
|
||||||
user="$1"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 最后一个参数可能是端口号
|
|
||||||
if [[ "${@: -1}" =~ ^[0-9]+$ ]]; then
|
|
||||||
port="${@: -1}"
|
|
||||||
servers=("${@:1:$#-1}")
|
|
||||||
else
|
|
||||||
servers=("$@")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 部署到所有服务器
|
|
||||||
local all_success=true
|
|
||||||
for server in "${servers[@]}"; do
|
|
||||||
deploy_key "$server" "$user" "$port" || {
|
|
||||||
all_success=false
|
|
||||||
echo -e "${RED}${server} 部署失败,跳过安全加固${NC}"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
done
|
|
||||||
|
|
||||||
# 只有所有服务器都部署成功才进行安全加固
|
|
||||||
if $all_success; then
|
|
||||||
echo -e "${YELLOW}所有服务器部署成功,开始安全加固...${NC}"
|
|
||||||
for server in "${servers[@]}"; do
|
|
||||||
secure_server "$server" "$user" "$port" || {
|
|
||||||
echo -e "${RED}${server} 安全加固失败${NC}"
|
|
||||||
all_success=false
|
|
||||||
}
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 清理锁文件
|
|
||||||
rm -f "$LOCKFILE"
|
|
||||||
|
|
||||||
# 最终状态报告
|
|
||||||
if $all_success; then
|
|
||||||
echo -e "\n${GREEN}所有操作成功完成!${NC}"
|
|
||||||
echo -e "${YELLOW}重要信息:${NC}"
|
|
||||||
echo -e "密钥位置: ${KEY_DIR}/${KEY_NAME}"
|
|
||||||
echo -e "密钥密码: ${KEY_PASSWORD}"
|
|
||||||
echo -e "已禁用密码登录的服务器: ${servers[*]}"
|
|
||||||
echo -e "\n${BLUE}您现在可以使用密钥登录这些服务器:${NC}"
|
|
||||||
echo "ssh -i ${KEY_DIR}/${KEY_NAME} ${user}@服务器地址 -p ${port}"
|
|
||||||
else
|
|
||||||
echo -e "\n${RED}部分操作失败,请检查上述错误信息${NC}"
|
|
||||||
echo -e "${YELLOW}注意: 未成功加固的服务器仍允许密码登录${NC}"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
}
|
||||||
|
|
||||||
|
# 部署到本机
|
||||||
|
deploy_key_locally || {
|
||||||
|
log "${RED}本地部署失败,退出脚本${NC}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 安全加固
|
||||||
|
secure_ssh || {
|
||||||
|
log "${RED}SSH加固失败,退出脚本${NC}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 验证部署
|
||||||
|
verify_deployment || {
|
||||||
|
log "${RED}部署验证失败,退出脚本${NC}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示成功信息
|
||||||
|
show_success
|
||||||
}
|
}
|
||||||
|
|
||||||
# 执行主函数
|
# 执行主函数
|
||||||
main "$@"
|
main
|
||||||
|
|||||||
Reference in New Issue
Block a user