1、检查端口
-
检查分发对象22端口是否打开
nmap -p22 ip地址
如果要批量检查端口可以参考我写的这篇文章:linux自动化一键批量检查主机端口
2、命令行分发密钥原理
Linux分发密钥原理主要涉及SSH(Secure Shell)协议,该协议用于在客户端和服务器之间建立安全的加密连接。以下是Linux分发密钥原理的详细解释:
2.1、密钥对生成
-
私钥(Private Key):私钥是保密的,用于解密数据和证明身份。它必须被用户单独妥善保管,不能泄露给未经授权的人员。
-
公钥(Public Key):公钥是公开的,用于加密数据和验证身份。它可以按需配置到目标服务器上的相应账号中。
-
例子:在Linux系统中,通常使用
ssh-keygen
命令来生成密钥对:ssh-keygen -t rsa
执行上面命令,一直按回车可以生成一个RSA密钥对,生成的私钥文件默认名为
id_rsa
,公钥文件默认名为id_rsa.pub
,密码为空。
保存在默认目录。执行下面命令可以查看到
ls /root/.ssh/
2.2、密钥分发
-
将公钥复制到服务器:客户端需要将生成的公钥文件(如
id_rsa.pub
)复制到目标服务器的用户家目录下的.ssh
文件夹中,并重命名为authorized_keys
文件(如果该文件已存在,则将其内容追加到该文件中)。这可以通过scp
命令或ssh-copy-id
命令来实现。 -
例子: 分发密钥到目标机器
ssh-copy-id -i /root/.ssh/id_rsa.pub root@目标机器IP地址
2.3、SSH登录认证
-
客户端发送登录请求:当客户端尝试通过SSH连接到服务器时,它会发送一个包含其公钥的登录请求。
-
服务器验证公钥:服务器接收到登录请求后,会在用户家目录下的
.ssh/id_rsa.pub
文件中查找与客户端公钥相匹配的记录。 -
生成随机数并加密:如果找到匹配的公钥,服务器会生成一个随机数,并使用该公钥对其进行加密。
-
客户端解密并返回:客户端使用自己的私钥对加密的随机数进行解密,并将解密后的原文信息返回给服务器。
-
服务器验证身份:服务器将客户端返回的信息与原始随机数进行比对。如果比对成功,则表示客户端成功证明了其身份,允许其登录到服务器。
-
例子:
ssh root@目标机器IP地址 hostname -I
或
ssh 目标机器IP地址 hostname -I
上面命令执行结果如下
3、创建自动化分批量发密钥脚本并执行
注意: 下面所有的脚本测试文件请保证在同一个目录下。脚本和测试文件直接复制粘贴在终端,然后回车即可
-
批量发密钥脚本
cat <<EOF>> distribute_keys.sh #!/usr/bin/bash # 作者:黑子哥呢? # 描述:一键批量分发密钥# 检查是否提供了正确数量的参数 if [ "\$#" -ne 3 ]; thenecho "错误:此脚本需要三个参数:用户名、用户密码和SSH密钥密码"echo "用法:sh \$0 <用户名> <用户密码> <SSH密钥密码>"exit 1 fi# 脚本自身路径赋值给变量SH SH=\$0# 接收脚本执行时传递的第一个参数作为用户名 USER_NAME=\$1# 接收脚本执行时传递的第二个参数作为用户密码 USER_PASSWORD=\$2# 接收脚本执行时传递的第三个参数作为SSH密钥的密码 SSH_KEY_PASSWORD=\$3 echo "开始执行:\$SH" echo "开始检查SSH密钥对是否存在"# 判断~/.ssh/id_rsa和~/.ssh/id_rsa.pub文件是否都不存在 if [ ! -f ~/.ssh/id_rsa ] && [ ! -f ~/.ssh/id_rsa.pub ]; thenecho "SSH密钥对不存在!" echo "开始自动创建SSH密钥对..."# 使用用户输入的密码创建SSH密钥对,重定向输出到/dev/null以隐藏详细信息ssh-keygen -t rsa -f ~/.ssh/id_rsa -P "\$SSH_KEY_PASSWORD" -C "管理机" &>/dev/nullecho "SSH密钥对创建成功!" elseecho "SSH公钥文件已存在" fi# 显示私钥和公钥的位置 echo "私钥位置:\$HOME/.ssh/id_rsa" echo -e "公钥位置:\$HOME/.ssh/id_rsa.pub\n"# 服务器列表的文件路径 HOST_LIST="host.txt"# 获取本地服务器公钥的路径 SSH_KEY="\$HOME/.ssh/id_rsa.pub"# 临时文件用来保存分发成功的服务器 OPEN_HOST_FILE=\$(mktemp)# 临时文件用于保存分发失败的服务器 CLOSED_HOST_FILE=\$(mktemp)# 临时文件用于保存测试连接失败的服务器 DISTRIBUTE_HOST_FILE=\$(mktemp)# 遍历服务器列表并分发密钥,同时保存结果到临时文件 echo "开始分发公钥..." while IFS= read -r HOST; doecho "正在分发公钥给\$HOST"# expect脚本的参数包括:服务器地址、用户名、密码、公钥路径、公钥密码expect distribute_keys.exp "\$HOST" "\$USER_NAME" "\$USER_PASSWORD" "\$SSH_KEY" "\$SSH_KEY_PASSWORD" &>/dev/nullif [ \$? -eq 1 ]; thenecho "分发公钥给\$HOST失败!"echo "\$HOST" >> "\$CLOSED_HOST_FILE"continuefiecho "正在测试\$HOST服务器SSH连接..."# expect脚本的参数包括:服务器地址、公钥密码expect connection.exp "\$HOST" "\$SSH_KEY_PASSWORD" &>/dev/null if [ \$? -eq 0 ]; thenecho "测试连接\$HOST成功!"echo "\$HOST" >> "\$OPEN_HOST_FILE"elseecho "测试连接\$HOST失败!"echo "\$HOST" >> "\$DISTRIBUTE_HOST_FILE"fi done < "\$HOST_LIST"# 如果分发成功的服务器文件不为空,则显示成功的服务器列表 if [ -s "\$OPEN_HOST_FILE" ]; thenecho "分发公钥成功的服务器列表如下:"cat "\$OPEN_HOST_FILE" fi# 如果分发失败的服务器文件不为空,则显示失败的服务器列表 if [ -s "\$CLOSED_HOST_FILE" ]; thenecho "分发公钥失败的服务器列表如下:"cat "\$CLOSED_HOST_FILE" fi# 如果分发失败的服务器文件不为空,则显示测试连接失败的服务器列表 if [ -s "\$DISTRIBUTE_HOST_FILE" ]; thenecho "测试连接失败的服务器列表如下:"cat "\$DISTRIBUTE_HOST_FILE" fi # 删除临时文件 rm -f "\$OPEN_HOST_FILE" "\$CLOSED_HOST_FILE" "\$DISTRIBUTE_HOST_FILE" EOF
-
expect分发公钥交互脚本
cat <<EOF>> distribute_keys.exp # !/usr/bin/expect # 作者:黑子哥呢? # 描述:密钥分发交互脚本# 设置超时时间为2秒 set timeout 2# 从命令参数中获取远程主机的主机名、用户名、密码、密钥和密钥密码 set hostname [lindex \$argv 0] set username [lindex \$argv 1] set password [lindex \$argv 2] set ssh_key [lindex \$argv 3] set ssh_key_password [lindex \$argv 4]# 启动ssh-copy-id命令,将本地SSH公钥复制到远程主机上 spawn ssh-copy-id -f -i \$ssh_key \$username@\$hostname # 等待并处理交互提示 expect {"*yes/no*" {send "yes\r"expect "*password:"send "\$password\r"}"*password*" {send "\$password\r"}"*passphrase*" {send "\$ssh_key_password\r"}default {exit 1} } expect eof EOF
-
expect测试连接交互脚本
cat <<EOF>> connection.exp # !/usr/bin/expect # 作者:黑子哥呢? # 描述:连接交互脚本# 设置超时时间为2秒 set timeout 2# 从命令参数中获取远程主机的主机名和密钥密码 set hostname [lindex \$argv 0] set ssh_key_password [lindex \$argv 1]# 启动ssh命令,测试连接命令 spawn ssh \$hostname w# 等待并处理交互提示 expect {"*passphrase*" {send "\$ssh_key_password\r"}"*passdord*" {send "\$ssh_key_password\r" } } expect eof EOF
-
创建测试文件,下面的ip地址改成自己的即可
cat <<EOF>> host.txt 1.1.1.12 1.1.1.13 1.1.1.14 EOF
-
执行脚本
注意:如果SSH密钥不存在脚本会自动创建,同时请确认好root用户密码和SSH密钥密码正确,密码错误可能导致脚本执行过程中分发公钥失败sh distribute_keys.sh 用户 用户密码 SSH密钥密码
我开启了1.1.1.12和1.1.13服务器,另外一台服务器处于关机状态 ,运行结果如下:
四、安全性与便捷性
- 安全性:由于私钥是保密的,并且只有匹配的公钥才能解密由私钥加密的数据,因此这种基于密钥的认证方式比传统的密码认证方式更安全。即使攻击者截获了加密的通信内容,也无法解密出私钥或密码。
- 便捷性:一旦配置了公钥/私钥对,用户就可以实现无密码登录多个服务器。这大大提高了操作的便捷性,并减少了密码泄露的风险。
综上所述,Linux分发密钥原理是通过生成密钥对、分发公钥、进行SSH登录认证等步骤来实现的。这种基于密钥的认证方式不仅提高了安全性,还带来了操作的便捷性。