-- W e l c o m e t o N o k e y _ b l o g --

AWS亚马逊云服务器.ssh目录下的authorized_keys文件被覆盖或修改后连接不上实例的解决方案(亲测)

8月 7 2015

一切源于自己对服务器知识理解的浅薄,主要是SSH和SFTP连接的规则。自己也是手贱啊,正因为贱所以才有机会接触这些知识领域,正所谓:兵来将挡,水来土掩!

问题出现的场景:公司PM给了我一个空的服务器(也就是亚马逊的云服务器AWS)让我临时传一些东西,然后我发现这个密钥只能用在SFTP上,而Xshell却用不了,我想安装一个node.js,所以必须用命令行,所以就萌生了用Xshell重新生成一个RSA密钥对,放到服务器上,覆盖掉authorized_keys这个文件(这即将成为一个很危险的操作)。当我覆盖完之后,尝试连接,失败。。。我发现我生成的是DSA的密钥类型!!!(其实当时即使我生成的是RSA估计也不行,因为那个密钥是亚马逊第一次创建实例的时候生成的)。最后我面临的问题就是:服务器的授权密钥文件被覆盖,无法使用SSH登陆,而且也没有口令登陆等其他方式。可能的解决方案是:修改或恢复authorized_keys文件。

当时头脑的第一反应就是,服务器的管理后台能够重新生成密钥对,结果是AWS是在实例创建的时候生成的一个密钥对,在控制面板并没有重新生成的选项。。。然后我想恢复这个实例,没想到恢复也这么麻烦,需要创建一个警报,我又不知道如何触发这个警报,无语了。

好吧,进入主题:Google “aws change key pair”,然后第一条就找到了这篇文章《Change key pair for ec2 instance》,眼前一亮,果然是Liunx系统层的解决方案啊,下面是步骤概览:

  • 1、Stop the running EC2 instance
  • 2、Detach its /dev/sda1 volume (let’s call it volume A)
  • 3、Start new t1.micro EC2 instance, using my new key pair
  • 4、Attach volume A to the new micro instance, as /dev/xvdf (or /dev/sdf)
  • 5、SSH to the new micro instance and mount volume A to /mnt/tmp
  • 6、Copy ~/.ssh/authorized_keys to /mnt/tmp/home/username/.ssh/authorized_keys
  • 7、Logout
  • 8、Terminate micro instance
  • 9、Detach volume A from it
  • 10、Attach volume A back to the main instance as /dev/sda1
  • 11、Start the main instance
  • 12、Login as before, using your new .pem file

AWS的一个实例是挂载一个SSD磁盘的,假设出问题的实例的磁盘名字叫Volume A,我们先在控制面板把这个磁盘卸载掉,然后新建一个实例,将Volume A连接到新的实例上面,然后SSH连接到新实例,将Volume A挂载到某个目录,这样把新实例的authorized_keys拷贝到Volume A.ssh目录下,这样我们就可以用新实例的密钥登录原来出问题的实例了,别忘了把Volume A连接回去。That’s All!

当然,在执行的时候遇到了一个问题,就是把Volume A挂载到/mnt/tmp目录的时候,总是提示一堆错误:

mount: wrong fs type, bad option, bad superblock on /dev/xvdf,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so.

然后我又找到了这篇文章,《Cannot mount an existing EBS on AWS》。给出的答案是:

  • Looks like you have partitioned that block device. In this case, you need to mount /dev/xvdf1, not just /dev/xvdf.

其实,当连接Volume A到新实例的时候,命名的是/dev/sdf,但实际看到的是它只是/dev/xvdf的一个软链接,至于为什么还会分割出一个/dev/xvdf1,我也不太清楚原因了,而且这个xvdf1才是主要的磁盘。

主要学到的Linux命令:mount -o rwln -s

----------------------

好吧,我承认我又年轻了,我上面的解决方案是申请的临时账号测试的,然后今天对实际服务器实例解决的时候,又碰到了问题:关于 Linux 的文件系统类型

其实我有料到,肯定会在挂载那里再出问题,可是这次替换 /dev/xvdf/dev/xvdf1 并没有什么卵用,那么为什么要替换呢?let’s do this first:

Nokey$ sudo fdisk -l

然后你将看到系统当前连接的磁盘的一些详细信息,其中有几列数据是这样的:

磁盘 /dev/xvda:107.4 GB, 107374182400 字节,209715200 个扇区
...
...
# Start End Size Type Name
1 2048 4095 1M BIOS boot parti
2 4096 209715166 100G Microsoft basic

/dev/xvda就是代表当前的磁盘引用,关键就要看#那一列,第一行的值是1,第二行是2,所以你也就明白 /dev/xvda1/dev/xvda2代表什么意思了吧。SizeType也是比较重要的两列信息,尤其是Type,它关系到挂载的时候指定的磁盘的文件类型。当然我们也可以使用 blkid 这个命令来查看卷文件类型:

Nokey$ blkid
/dev/block/202:2: UUID="6785eb86-c596-4229-85fb-4d30c848c6e8" TYPE="xfs" PARTUUID="e8c8ba12-3669-4698-b59b-2db878461f9a"
/dev/xvdf2: UUID="6785eb86-c596-4229-85fb-4d30c848c6e8" TYPE="xfs" PARTUUID="e8c8ba12-3669-4698-b59b-2db878461f9a"

细心的同学会发现,这两个磁盘的UUID(UUID是一个标帜你系统中的存储设备的字符串,其目的是帮助使用者唯一的确定系统中的所有存储设备,不管它们是什么类型的。它可以标识DVD驱动器,USB存储设备以及你系统中的硬盘设备等。What are those /dev/ Files?不一样,(至于为什么/dev/block/202:2会挂载磁盘我还没搞清楚,/block 目录下是块设备的一些软链接,那个202:2就是一个软链接,而202:82又反链接回到 ../xvdf2,202:2反链接到 ../xvda2,这两个设备的UUID冲突了) 也就是因为UUID的相同,你在mount的时候又会出现那个错误:

Nokey$ mount -t xfs /dev/xvdf2 /mnt/tmp
mount: wrong fs type, bad option, bad superblock on /dev/xvdf,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so.
Nokey$ dmesg | tail
...
[ 8952.229018] XFS (xvdf2): Filesystem has duplicate UUID 6785eb86-c596-4229-85fb-4d30c848c6e8 - can't mount
...

打印出的错误也的确是这样的,那么只能更改 /xvdf2 的 UUID 了,然后我又Google到了这篇文章:XFS Filesystem has duplicate UUID problem,也就是用xfs_admin这个命令:

Nokey$ xfs_admin -U generate /dev/xvdf2
Clearing log and setting UUID
writing all SBs
new UUID = 01fbb5f2-1ee0-4cce-94fc-024efb3cd3a4

继续mount,然后发现又成功了,嗯?我为什么说了“又”?