今天遇到个很妖的问题,虽然最终的解决方案让人很无语,但是通过本次问题的解决还是加深了自己对网络知识的认知。
故事是这样的,我们负责开发的混合云管理平台最近要上一套新的openstack,所以要将新openstack管理进来。由于平台是新搭建,我这边开发环境也是新改造的,所以在openstack的对接发生一系列不顺利的事情。最大的障碍是openstack创建起来的实例无法ssh登陆上去,整个排查过程如下:
1 网络通不通?
通过ping Ip的方式排查,确定没问题
2 端口通不通?
通过telnet ip+port的方式排查,确定没问题
3 是否被安全组墙掉了?
登陆上openstack平台,看到以IP地址段的方式配置的ssh入口,但是不确定自己的网络是否在入口网段内。这是本篇的重点,后面会详细说明,这里先直接公布答案,安全组没问题,我的IP没有被墙掉
4 鉴权是否有问题?
公司规定ssh要用key-pair方式,我检查openstack上我管理的实例也设置了我添加的密钥对,而且我也通过ssh -i XXX.pemuser@IP的方式指定了私钥文件,但是确实登陆不上。关于Openstack密钥对后面也会介绍下。
最终问题解决,是重新换了个密钥对,只能怀疑是Openstack内部生成密钥对的时候出现了bug,给我的私钥与平台上的公钥不是一对…..
Anyway,开源的东西就是这样,我已经习惯了,但是本文的重点不是吐槽OpenStack,它仍然是个非常优秀的产品,本文的重点是排查的过程中我对云平台网络故障排查和SSH密钥对这两个知识点有了更深刻的理解。
路由追踪:
Linux中traceroute命令查看全路径路由
由于我的linux在VM里,而且VM共享物理机网络,所以看到路由到了192.168.44.2就没有了,所以要回到物理机上继续追踪路由。
Windows的相同的命令是tracert命令
看到最终通过10.100.129.97这一跳进入到OpenStack的实例中。
然后我们有了路由信息后,再去对照下OpenStack安全组的22端口(SSH)的入参,但是是以IP段的格式配置的,所以我们要学会IP段是个什么鬼,通过IP段我们能计算出什么信息。
IP段:
先要了解子网掩码
子网掩码的作用在于定义了哪些是网络标识,哪些是主机标识,子网掩码必须与IP地址一起出现才有意义。
虽然有3类:
A类:255.0.0.0 11111111.00000000.00000000.00000000
B类:255.255.0.0 11111111.11111111.00000000.00000000
C类:255.255.255.0 11111111.11111111.11111111.00000000
但是凡是连续的1开头0结尾的32位二进制都是合理的子网掩码,例如
255.255.255.252 11111111.11111111.11111111.11111100
我们一般会将ip/0-32的方式来标识一个ip段,其中0-32代表了掩码中有多少个0.
子网掩码的意义是:该子网能支持多少个IP,计算方式是后面有多少个0就有2的N次方个ip。
如上有2个0,2的2次方是4,该子网有4个ip
例如10.100.129.97/30,我们来计算下子网有多少个IP:
00001010.01100100.10000001.01100001
&
11111111.11111111.11111111.11111100
=
00001010.01100100.10000001.01100000
=
10.100.129.96(这个是网络标识)
网络标识相同的机器才会处于同一网段,这是网络标识的意义,从算法上可以反向推断出,是否处于同一网段是由IP+子网掩码2部分决定的。
而刚才也说过该子网能支持4个IP,那IP是哪些呢? 从网络标识的算法上可以推算出,ip的第四段为01100000、01100001、01100010、01100011,也就是:10.100.129.96、10.100.129.97、10.100.129.98、10.100.129.99
子网虽然具有4个IP,但并不能都用于主机IP,与掩码0位对应IP的二进制位全1,是留给子网自己组播用的,也就是说00001010.01100100.10000001.01100011=10.100.129.99不能作为主机IP。网络标识也不能作为主机IP。所以该子网可以分配给主机的IP只有10.100.129.97、10.100.129.98
子网支持的IP数是2的N次方(N=后面子网掩码后面几个0),能分配给主机的IP还要再减2.
那现在问题又来了,既然子网掩码我们可以自己定义的,为什么还要做A类、B类、C类这种划分呢?其实ABC是代表着子网的规模,有了这些基本的划分后我们先根据自己的需要大体知道自己属于哪个规模,也就是哪类子网,然后再决定是否启用自定义的掩码更精细的管理网络。
举个例子,我现在需要搭建500台主机的局域网,那么我知道C类子网只能支持250多个,所以C网是不够用的,我的网络是一个B网(B网能支持6万多台主机)。当然标准B网对我500台机器来说台奢侈了,我可以选择用255.255.253.0,或者为了公司规模预见性的多配置一些,255.255.252.0就差不多了。
我们刚才讲了网络标识的概念,在同一个网络中还有主机标识的概念,代表着该主机在该网络中的标识。主机标识的计算与网络标识正好相反,是IP与掩码取反后再AND,还是以10.100.129.97/30为例,如下:
00001010.01100100.10000001.01100001
&
00000000. 00000000.00000000.00000011
=
00000000. 00000000. 00000000.00000001
=
0.0.0.1(这个是10.100.129.97这个IP在网络中主机号)
同理可以计算出
10.100.129.96:0.0.0.0
10.100.129.98:0.0.0.2
10.100.129.99:0.0.0.3
主机号全0表示网络本身,全1表示网络广播,这俩不能作为主机IP使用,这点前面已经介绍过了。
SSH Key-Pair
Key-Pair是非对称加密的一组密钥(对称加密非对称加密在https://blog.csdn.net/yejingtao703/article/details/78712386这一篇中有详细介绍,而且在https://blog.csdn.net/yejingtao703/article/details/78723276这一篇https领域也有广泛应用),public的公钥由被请求端保留,而且在OpenStack的UI平台上是可以看得到,而private的私钥是由ssh请求发起端保留的,只有创建key-pair的人才拥有。
SSH的key-Pair是单向的,public key是锁,private key是钥匙,也就是说我们只能拿钥匙去开锁,而不能用锁去访问钥匙。所以说如果有双向访问的需求需要2套key-pair,各自拿一个自己的锁和对方的钥匙。
OpenStack中设置密钥对有2种方式:
1在平台上创建密钥对,生成密钥对的同时操作员可以下载到该密钥对的私钥pem文件。
2 操作员自己通过ssh-keygen-f filename方式创建密钥对,将公钥上传到平台。
无论哪一种方案其结果都是一样的,平台保留公钥,操作员自己保留私钥。云平台在创建实例时将公钥设置到~/.ssh/authorized_keys中,这样操作员就可以用自己手上的钥匙打开云实例上的锁了。
回到我今天遇到的问题,最终换了一套钥匙和锁就解决了,可能是OpenStack生成了一对劣质产品,也可能钥匙在传输的构成中被污染了,总之钥匙打不开锁。
我这里用的是OpenStack,AWS、阿里云、腾讯云等平台也是安全组+key pair这种方式,所以本篇的排查步骤所有平台通用。