运维

ssh使用

ssh使用SSL非对称加密实现,是保障网络通信安全的重要手段。常见的ssh登录远程服务器和github的代码上传都是使用了ssh协议

非对称加密

不同于传统的用户名/密码的验证方式,ssh使用非对称加密算法来保证安全性。

简单的说,现在有一种加密算法Ek和解密算法Dk,和一对特殊生成的密钥k1,k2。我们可以使用加密算法E和密钥k1来加密一段信息M。即X=Ek1(M)。非对称加密算法特殊的地方在于加密后的信息只能用另一个密钥k2来解开。即M=Dk2( Ek1(M) )。而只有k1的话是只能对信息加密不能解密的。这一过程中的k1和k2可以交换。即M=Dk1( Ek2(M) )。

我们把这两个密钥中的某一个自己偷偷藏着谁也不告诉,叫做私钥,另一个则公开出来,叫做公钥。这就是常说的公钥加密只有私钥能解,私钥加密只有公钥能解。

对于ssh登录来说,我们提前将自己的公钥放在服务器,私钥则自己藏着。我们考虑一个简化的模型。当需要远程登录服务器时,服务器生成一个随机数,用公钥加密发给客户端。客户端用私钥解密后将答案发给服务器,只有能正确解密的客户端才是合法的客户端。这里我们可以看到由于公钥加密的信息只有私钥能解,因此除了掌握着私钥的自己其他通信中间人都不知道具体的通信内容。实际的ssh登录过程比上述要更复杂一些,但核心原理就是以上了。

如果想深入了解非对称加密的知识可以参考密码学的书籍。

实战:

基础的Linux服务器免密码登录

创建公钥与私钥

输入ssh-keygen

root@a617896eadbb:/home/service# ssh-keygen

Generating public/private rsa key pair.

默认存放位置为用户目录的.ssh文件夹下(~/.ssh)

Enter file in which to save the key (/root/.ssh/id_rsa):

Created directory ‘/root/.ssh’.

密码不填,此密码是附加在密钥上的密码,不填的话登录时就不会要求输入密码

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /root/.ssh/id_rsa.

Your public key has been saved in /root/.ssh/id_rsa.pub.

The key fingerprint is:

SHA256:orq3rlX7nREk7TAWMCpdXWmikpT1sMxg3usV+hTqvAU root@a617896eadbb

The key’s randomart image is:

+—[RSA 2048]—-+

|    oo*o….     |

|   +oB =ooo      |

|  ..+.=.Ooo      |

|   .o .= O       |

|     .E S o      |

|     * B   .     |

|    o = o .      |

|   o.  + . o     |

|  +=o.. . o      |

+—-[SHA256]—–+

以上便创建了公钥和私钥

我们到.ssh里查看一下

root@a617896eadbb:/home/service# cd ~/.ssh

root@a617896eadbb:~/.ssh# ls

id_rsa  id_rsa.pub

可以看到有id_rsa和id_rsa.pub两个文件,其中id_rda为私钥文件,id_rda.pub为公钥文件

上传公钥到服务器

首先使用用户名密码登录远程服务器,创建.ssh文件,并将id_rda.pub的内容复制到.ssh/authorized_keys下

root@localhost:~# mkdir .ssh

root@localhost:~# cd .ssh   

root@localhost:~/.ssh# vim authorized_keys

设置文件权限为400(只有自己有读权限),并设置.ssh文件夹权限为755

root@localhost:~/.ssh# chmod 400 authorized_keys

root@localhost:~/.ssh# cd ..

root@localhost:~# chmod 755 .ssh/

接着断开服务器连接,再登录就不会要求输入密码了。ssh登录的过程通常会先尝试所有公钥,如果都不行再要求输入密码。因此如果登录时仍然要求输入密码可以检查自己的.ssh下是否有私钥文件,服务器上是否放了对应的公钥文件,服务器上的公钥文件权限是否正确。

github/gitlab使用ssh传输文件

github的ssh配置十分简单,在网页中找到ssh管理,将自己的公钥粘贴上去就行,注意是公钥不是私钥,私钥是万万不能外泄的,这是ssh安全性的核心所在。

ssh高阶应用

私钥和公钥通常都以文件方式放在~/.ssh下,这样在保存上有很大的不安全因素。一是公钥与私钥放在一起,拥有本地用户权限和访问公钥目录权限的人往往也能访问私钥,例如一些本地应用。二是私钥只是一段文本没有做鉴权,所有拥有私钥文件的人都可以登录。例如假若公司里的某同事掌握着有重要信息的服务器,我们完全可以趁他不在时打开他电脑复制粘贴他的密钥。因此需要提升私钥在物理上的安全性。

使用ssh agent提高私钥安全性和便利性

之前创建公私钥对的时候我们选择了不输入密码,因为这样可以免密码登录最省事。我们也可以在创建时设置密码,这样当我们用公私钥登录时会提示我们输入密码。这样虽然安全性更高一些但也变麻烦了。这时就需要靠ssh agent了。

通常客户端在安装ssh时也会随配ssh agent,这是一个一直运行的ssh代理,我们可以将自己的私钥填入其中,这样当需要使用ssh时,服务器的ssh首先会询问本地的ssh agent并依次尝试所有已保存的私钥,若都不成功再向用户询问。

首先我们用之前的办法创建公私密钥对,这次我们选择输入密码,并且不把密钥放在默认的位置,我们选择放在~/.ssh/keys/id_rsa下

root@a617896eadbb:/home/service# ssh-keygen

Generating public/private rsa key pair.

Enter file in which to save the key (/root/.ssh/id_rsa):~/.ssh/keys/id_rsa

Created directory ‘/root/.ssh/keys’.

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

接着在ssh agent中添加我们生成的密钥

ssh-add -K ~/.ssh/keys/id_rsa

按照提示输入私钥的密码,-K选项会将此密码和密钥同时保存一份在用户的keychain里,在mac下可以进入keychain access.app查看保存的密钥。这样再一次登录服务器时可以自动从ssh agent拿到私钥并从keychain中拿到密码,一次性免密码登录成功。

使用ssh-add -l可以列出当前所有保存的密钥

如果我们重启了电脑,再使用ssh-add -l的话会发现原本保存的所有密钥都被清空了。如果是在mac下的话,我们可以使用

ssh-add -A

来取回之前保存在keychain中的密钥,将这个命令加入到登录shell的配置后(如~/.bashrc,~/.zashrc),便可以登录时自动加载密钥

使用ssh config定制化ssh

如果我们管理者多台服务器,通常管理员会给服务器取一个好记的名字,例如picasso。我们想要直接用这个名字ssh登录服务器,而不是用冗长的域名或ip。

如果我们想把登录公司的私钥与平时个人使用的私钥分开,这时我们可能需要动态的区分登录哪个服务器使用哪个私钥。

如果某台服务器只允许ipv4登录,而默认ssh时用ipv6登录

这些情况都需要我们用到ssh的config文件

在.ssh下建立config文件,写入内容如下

Host pica picasso

HostName picasso.example.com

User picasso

IdentityFile ~/.ssh/keys/picasso/id_rsa

AddressFamily inet 

HostName github

Host github.com

User auroraka

IdentityFile ~/.ssh/keys/auroraka/id_rsa

AddressFamily inet inet6

HostName *

User auroraka

IdentityFile ~/.ssh/keys/auroraka/id_rsa

AddressFamily inet inet6

在HostName中填入服务器地址,用Host取别名,用User指定用户,IdentityFile指定私钥位置。其他更详细配置可以查看man ssh_config

这样,我们就可以实现ssh pica一键登录picasso.example.com服务器了

使用ssh -A在服务器验证本地私钥

在服务器上使用git时往往会遇到没有添加公钥无法访问git仓库的尴尬问题。为此专门生成一个公私钥对并上传至git显然不是一个优美的解决方案,一个比较好的办法是使用ssh agent

在ssh连接服务器时使用-A参数,这样所有需要验证私钥的请求会被ssh agent转发到本地客户端,在本地进行验证后再将结果传给服务器。对于本次ssh连接而言,在服务器上的操作犹如拥有本地所有的私钥。但是对于其他用户而言,他们最多只能看到公钥。并且使用ssh -A使我们可以在服务器只有公钥的情况下从服务区A继续ssh连接服务器B

这样服务器上就只有公钥没有私钥,保证了安全性。

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s