Linux互信之基于密钥的SSH互信

举报
工业云大湿兄 发表于 2018/09/03 15:09:44 2018/09/03
【摘要】 需求描述:在多节点并行计算设置中,建立Linux主机间的SSH互信是非常重要的环节。特别是对于云仿真场景中的求解计算的集群是必要前提。ssh连接需要验证用户身份,通常情况下使用本机的用户密码。当需要实现自动连接时,手工输入密码显然是不可行的,那么我们可以使用密钥方式或者使用基于主机的互信。---本文以华为云上的Centos 6.5为例基于密钥的ssh互信1 原理远程主机(client)生成一...

需求描述:

在多节点并行计算设置中,建立Linux主机间的SSH互信是非常重要的环节特别是对于云仿真场景中的求解计算的集群是必要前提。ssh连接需要验证用户身份,通常情况下使用本机的用户密码。当需要实现自动连接时,手工输入密码显然是不可行的,那么我们可以使用密钥方式或者使用基于主机的互信。

---本文以华为云上的Centos 6.5为例

基于密钥的ssh互信

原理

远程主机(client)生成一对密钥,将公钥分发给主机(server),当client连接server时,client使用私钥产生凭证(签名包括了client的身份信息)发送给serverserver接受后使用公钥解密验证。

注意,签名是基于用户的,并且是单向的。不同的用户要生成自己的密钥对,若要实现双向互访,主机间需要拥有对方的公钥。

server间实现SSH无密码互访(集群中常用)是将所有server的公钥文件汇总并发布到每台server,进而实现server间的自由互访。

2   两节点间ssh免密

场景设定:给用户testssh-0001(192.168.1.6)节点和ssh-0002(192.168.1.132)之间配置ssh免密。

                 --- 先在ssh-0001上进行配置

(1)                   配置域名映射:

vim /etc/hosts

image.png

(2)                   生成RSA密钥,一直按回车选择默认配置即可:

ssh-keygen -t rsa

(3)                   将密钥发送到对应节点:

ssh-copy-id test@ssh-0002  (输入test在ssh-0002上的密码)

(4)                   以上的步骤已经完成user用户的ssh-0001ssh-0002的免密,再在ssh-0002节点上重复以上步骤完成ssh-0002ssh-0001的免密。

3  集群root用户的ssh免密脚本制作

场景设定:给用户root在集群的slavemaster节点之间配置ssh免密,集群的master节点为ssh-0001,其他slave节点为ssh-0002ssh-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. 吐槽一下我们云社区的嵌入代码的组件啊啊啊啊好丑啊,我想放截图结果压缩的好不清晰,就很难受。管理员大大看下这里啊。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。