Linux互信之基于密钥的SSH互信
需求描述:
在多节点并行计算设置中,建立Linux主机间的SSH互信是非常重要的环节。特别是对于云仿真场景中的求解计算的集群是必要前提。ssh连接需要验证用户身份,通常情况下使用本机的用户密码。当需要实现自动连接时,手工输入密码显然是不可行的,那么我们可以使用密钥方式或者使用基于主机的互信。
---本文以华为云上的Centos 6.5为例
基于密钥的ssh互信
1 原理
远程主机(client)生成一对密钥,将公钥分发给主机(server),当client连接server时,client使用私钥产生凭证(签名包括了client的身份信息)发送给server,server接受后使用公钥解密验证。
注意,签名是基于用户的,并且是单向的。不同的用户要生成自己的密钥对,若要实现双向互访,主机间需要拥有对方的公钥。
server间实现SSH无密码互访(集群中常用)是将所有server的公钥文件汇总并发布到每台server,进而实现server间的自由互访。
2 两节点间ssh免密
场景设定:给用户test在ssh-0001(192.168.1.6)节点和ssh-0002(192.168.1.132)之间配置ssh免密。
--- 先在ssh-0001上进行配置
(1) 配置域名映射:
vim /etc/hosts
(2) 生成RSA密钥,一直按回车选择默认配置即可:
ssh-keygen -t rsa
(3) 将密钥发送到对应节点:
ssh-copy-id test@ssh-0002 (输入test在ssh-0002上的密码)
(4) 以上的步骤已经完成user用户的ssh-0001到ssh-0002的免密,再在ssh-0002节点上重复以上步骤完成ssh-0002到ssh-0001的免密。
3 集群root用户的ssh免密脚本制作
场景设定:给用户root在集群的slave和master节点之间配置ssh免密,集群的master节点为ssh-0001,其他slave节点为ssh-0002和ssh-0003(192.168.1.67)。
(1) 参数设定。slave与slave_ip可以设置多余两个,但是需要数量相同一一对应。
master="ssh-0001" master_ip="192.168.1.6" master_password="sshtest" slave=("ssh-0002" "ssh-0003") slave_ip=("192.168.1.132" "192.168.1.67") slave_password=("sshtest" "sshtest")
(2) 基本配置:
a. 设定日志路径。
b. 抓取/etc/ssh下的key的日期 (为了做基于主机互信做准备)。
c. 安装sshpass。
LOG_PATH="ssh_root_config.log" etc_ssh_year=$(stat /etc/ssh/ssh_host_rsa_key | grep -i Modify | awk -F'[ -]' '{print $2}') yum -y install sshpass
(3) 更新/etc/hosts:
a. 删除/etc/hosts中旧的域名记录,再添加新的(为了脚本可重复执行)。
#Renew /etc/hosts sed -i "/${master}/d" /etc/hosts echo "$master_ip $master" >> /etc/hosts for (( i = 0 ; i < ${#slave[@]} ; i++)) do sed -i "/${slave[$i]}/d" /etc/hosts echo "${slave_ip[$i]} ${slave[$i]}" >> /etc/hosts done echo "Finish renew /etc/hosts"
(4) 更新/etc/ssh中的host key (为了基于主机互信做的准备, 如果不需要可以不做):
a. 如果/etc/ssh/中的host key的修改日期为2016年, 则需要更新。
b. 删除旧的host key,并重启sshd服务。
#Renew master node host key if [ $etc_ssh_year == "2016" ]; then echo "# start renew /etc/ssh/ssh_hosts_rsa_key on master" rm -f /etc/ssh/ssh_host* service sshd restart echo "# Check /etc/ssh directories:" > $LOG_PATH ls -l /etc/ssh/ | grep "ssh_host" >> $LOG_PATH else echo "# /etc/ssh/ssh_hosts_rsa_key on master is uptodate" echo "# /etc/ssh/ssh_hosts_rsa_key on master is uptodate" > $LOG_PATH fi
(5) 生成RSA密钥:
a. 如果/root/.ssh/id_rsa不存在才生成,否则直接跳过。
#Generate master rsa key if [ ! -f "/root/.ssh/id_rsa" ]; then echo "# start generate root rsa key on master" ssh-keygen -t rsa -f /root/.ssh/id_rsa -N "" echo "# Check /root/.ssh directories:" >> $LOG_PATH ls -l /root/.ssh/ | grep "id_rsa" >> $LOG_PATH else echo "# root rsa key exist on master" echo "# root rsa key exist on master" >> $LOG_PATH fi
(6) 更新known_hosts:
a. 删除旧的known_hosts。
#Remove old known_hosts for target nodes for (( i = 0 ; i < ${#slave[@]} ; i++)) do echo "# start remove host key for ${slave[$i]}" ssh-keygen -R ${slave[$i]} >> $LOG_PATH ssh-keygen -R ${slave_ip[$i]} >> $LOG_PATH done
b. 添加新的known_hosts。
#Generate new known_hosts file echo "# start generate the known_hosts file on master" ssh-keyscan ${slave[*]} >> /root/.ssh/known_hosts echo "# Check /root/.ssh/known_hosts:" >> $LOG_PATH cat /root/.ssh/known_hosts >> $LOG_PATH
(7) 复制RSA密钥到slave节点:
#Copy rsa keys to slave nodes for (( i = 0 ; i < ${#slave[@]} ; i++)) do echo "# start copy rsa keys to ${slave[$i]}" echo "# Debug pass : ${slave_password[$i]}" sshpass -p ${slave_password[$i]} ssh-copy-id -i /root/.ssh/id_rsa.pub ${slave[$i]} echo "# Check ${slave[$i]} /root/.ssh/authorized_keys:" >> $LOG_PATH ssh root@${slave[$i]} "cat /root/.ssh/authorized_keys" >> $LOG_PATH done
(8) 给slave节点完成以上配置:
#Slave nodes root ssh authorization for (( i = 0 ; i < ${#slave[@]} ; i++)) do scp /etc/hosts root@${slave[$i]}:/etc echo "# Check ${slave[$i]} /etc/hosts:" >> $LOG_PATH ssh root@${slave[$i]} "cat /etc/hosts" >> $LOG_PATH if [ "2016" == $(ssh root@${slave[$i]} "stat /etc/ssh/ssh_host_rsa_key | grep -i Modify | awk -F'[ -]' '{print \$2}'") ]; then echo "# start generate root rsa key on ${slave[$i]}" ssh root@${slave[$i]} "rm -f /etc/ssh/ssh_host*; service sshd restart" else echo "# /etc/ssh/ssh_hosts_rsa_key on ${slave[$i]} is uptodate" fi ssh-keygen -R ${slave[$i]} ssh-keygen -R ${slave_ip[$i]} ssh-keyscan ${slave[$i]} >> /root/.ssh/known_hosts echo "# Check ${slave[$i]} /etc/ssh/ directories:" >> $LOG_PATH ssh root@${slave[$i]} "ls -l /etc/ssh/ | grep 'ssh_host'" >> $LOG_PATH if ssh ${slave[$i]} test -e "/root/.ssh/id_rsa"; then echo "# root rsa key exist on ${slave[$i]}" else echo "# start generate root rsa key on ${slave[$i]}" ssh root@${slave[$i]} "ssh-keygen -t rsa -f /root/.ssh/id_rsa -N ''" fi echo "# Check ${slave[$i]} /root/.ssh/ directories:" ssh root@${slave[$i]} "ls -l /root/.ssh/ | grep 'id_rsa'" >> $LOG_PATH echo "# start remove host key for master" ssh root@${slave[$i]} "ssh-keygen -R ${master}" >> $LOG_PATH echo "# start generate the known_hosts file for master" ssh root@${slave[$i]} "ssh-keyscan ${master} >> /root/.ssh/known_hosts" >> $LOG_PATH echo "# start copy ${slave[$i]} rsa keys to master" sed -i "/${slave[$i]}/d" /root/.ssh/authorized_keys ssh root@${slave[$i]} "cat /root/.ssh/id_rsa.pub" >> /root/.ssh/authorized_keys echo "# Check ${slave[$i]} /root/.ssh/authorized_keys:" >> $LOG_PATH ssh root@${slave[$i]} "cat /root/.ssh/authorized_keys" >> $LOG_PATH done
(9) 更新所有节点的hostname:
#Modify hostname sed -i "/HOSTNAME/d" /etc/sysconfig/network echo "HOSTNAME=${master}" >> /etc/sysconfig/network hostname ${master} for (( i = 0 ; i < ${#slave[@]} ; i++)) do ssh root@${slave[$i]} "sed -i \"/HOSTNAME/d\" /etc/sysconfig/network; echo \"HOSTNAME=${slave[$i]}\" >> /etc/sysconfig/network; hostname ${slave[$i]}" done
验证成果:
root用户可以在master跟任意slave节点之间双向SSH免密访问。
结语:
脚本我放在附件了,只需要更改前面的参数就可以直接跑。下一篇讲另一种互信:基于主机的ssh互信~
credit to 谢坤
p.s. 吐槽一下我们云社区的嵌入代码的组件啊啊啊啊好丑啊,我想放截图结果压缩的好不清晰,就很难受。管理员大大看下这里啊。
- 点赞
- 收藏
- 关注作者
评论(0)