Luna Tech

Tutorials For Dummies.

SSH With Git

2019-10-28


0. Background

今天把博客文章上传的流程优化了一下,之前我是本地把project push到GitHub,然后Server通过HTTPS来pull change,但是这个流程的问题在于每次pull change都要输一遍GitHub的用户名密码,为了省掉输入信息的时间,我今天在Server生成了SSH Key pair,通过SSH链接来操作GitHub repo,实现了效率的提升~

本文会介绍SSH协议,SSH Key pair的一些原理,以及我的具体操作步骤。

1. Preparation

在没有配置SSH之前,我是无法通过ssh链接来clone GitHub project的,显示Permission Denied。

Figure 1: Fail to build SSH connection

1. 生成SSH key pair

按照惯例,所有的SSH key都存在你系统的根目录下,一个.ssh的隐藏文件夹。

注:这里我采用的是Linux server作为例子(MacOS也一样,直接在Terminal操作即可),Windows用户需要下载PuTTy

# check existing keys
cd ~/.ssh
ls -al ~/.ssh

Figure 2: List existing SSH key pairs

# create a new ssh key for github
ssh-keygen -t rsa -b 4096 -C "[email protected]"

1. 如果不熟悉SSH的原理,建议先不要用default的名字,取一个专门的ssh key名字,比如这里我用的是/home/lunawen/.ssh/github,也就是在/home/lunawen/.ssh这个文件夹里面生成一个叫做github的ssh key。

更新:这一步建议大家还是用default的key,因为我后来遇到了奇怪的问题……

2. 我没有单独输入passphrase(也就是在回答这个问题的时候直接按回车键);

如果这一步你输入了passphrase的话,下面把SSH key加入SSH Agent的时候也需要用到这个passphrase,所以要记住哦~

Figure 3: Generate SSH key pair

这一步完成后,我们的ssh文件夹中会新增两个文件——githubgithub.pub

# check existing keys
cd ~/.ssh
ls -al ~/.ssh

Figure 4: New SSH key pair generated

为什么会有两个文件呢?

如果你也有这样的疑问,就先跟我一起了解一下SSH以及SSH key的原理吧~


2. SSH & SSH keys

1. What is SSH protocol?

SSH全称Secure Shell,于1995年出生,它的目的是让两台电脑之间的连接更加安全;打比方就是两个人说话的时候,SSH协议可以保护他们的谈话内容不被别人窃听。

怎么做到呢?简而言之,两台电脑通过SSH协议连接之后,他们之间的所有沟通都是被加密过的,所以就算别人听到了,没法解密的话,也听不懂= =。

用SSH协议传输文件的时候,实际用的是建立于SSH协议上的SFTP (SSH File Transfer Protocol),比常见的FTP要安全很多。

SSH的默认端口是22,要建立SSH连接必须保证SSH的端口开放哦~

想要改变默认端口也是可以的,Linux系统可以通过sudo vi /etc/ssh/sshd_config这个指令去修改默认配置,这里不做展开,有兴趣的可以看这篇文章

2. What are SSH keys?

SSH Key的全称是Secure Shell Keys,SSH Keys是成对出现的,作用是让电脑和电脑之间建立可信赖的关系。

打个比方,现实生活中,每扇门都有一个锁,和至少一把钥匙;

而在计算机的世界里,SSH keys就是给两台电脑“配对”的媒介,SSH Key的Private Key就相当于门上的那把锁,只有持有配对的钥匙(Public Key)才能打开那把锁。

你可以给自己信赖的人发放钥匙(Public Key)邀请他们到你家来玩,但是如果你的Private Key(门上的锁)丢了或者换了,这扇门就不可能被原来的钥匙(Public Key)打开。

具体的配对过程跟非对称加密算法 有关,在此不做展开。

另外,和现实生活中类似的是,SSH Keys有不同的size(就像我们的钥匙大小形状也不一样),最常用的一种是RSA 2048-bit encryption。


3. 怎么使用SSH Key

1. 把Private Key加入到SSH Agent

SSH Agent是一个用来管理用户SSH key的程序;每台电脑可以有多个SSH key pair。

# Add the private key to SSH agent
ssh-add ~/.ssh/github

Figure 5: Add SSH private key into SSH Agent

经过前面的背景知识补充,你应该明白为什么我们一开始生成SSH Key的时候会得到两个不同的文件了,那个github.pub就是public key,如果其他电脑持有这个public key,他们就可以跟你的电脑建立连接。

现在我们需要做的是,让GitHub和我们的Server建立友好关系,这样我们就不用在每次pull repo的时候输入用户名密码了(节约了打字时间哦!)。

# get content of the public key
cat ~/.ssh/github.pub

Figure 6: Get public key content

2. 把Public Key加入GitHub账户

登录GitHub -> 进入Settings界面 -> 选择SSH and GPG keys。

Figure 7-1: Set up public key in GitHub

Figure 7-2: Set up public key in GitHub

新建SSH Key。

Figure 7-3: Set up public key in GitHub

Figure 7-4: Set up public key in GitHub

1. 给这个钥匙取个名字,随便你叫什么都行;

2. 把刚才看到的Public Key的内容全部复制进去,记得检查一下头尾,不要漏掉字符;

3. 添加SSH Key。

3. 通过SSH来clone project

之前我们是无法通过SSH来操作GitHub Repo的,而如果通过HTTPS的连接来操作Repo,每次都需要输入用户名密码。

现在,当我们完成了GitHub Public Key的配置之后,我们可以直接通过SSH来进行操作啦~

假如我要Clone这个project,首先要切换到SSH的选项:

Figure 8-1: Use SSH

Figure 8-2: Get SSH link

然后只要用git clone ssh-link就可以直接Clone了(无用户名密码输入过程)。

Figure 8-3: Use SSH to clone the project

同理,在这个project里面使用任何的git command(如git pull),都不需要再次验证你的身份。

Figure 9: Use SSH to pull changes

是不是方便很多呀!😎

下面的图总结了我们之前完成的几个步骤:

1. Client生成SSH Key pair;

2. Private Key加入到Client的SSH Agent进行统一管理;

3. Public Key加入到Server的key list里面,作为配对依据;

Figure 10: SSH concept


4. SSH连接是如何建立起来的?

那么,为什么我们不用输用户名密码了呢??

SSH到底是通过什么流程来进行验证的呢?

在实际体会到SSH的便利后,让我们来深入了解一下刚才到底发生了什么:

1. 首先,当我们敲入git clone的指令之后,我们的电脑会跟GitHub Server创建链接,我们的电脑会把Public Key发到GitHub Server;

2. GitHub Server会根据我们发过来的Public Key,找一找有没有一样的Public Key(如果之前没有把Public Key加入到GitHub,这一步就会失败);如果找到了相同的Public Key,GitHub Server会用这个Public Key加密一段信息,发送给我们的Client;

3. 这段信息只能被Private Key解密,如果我们的Client解密成功,就代表我们的身份得到了认证;

4. SSH连接成功建立;

5. 之后GitHub Server和我们的Client就可以通过Public Key加密,Private Key解密的方式进行信息传输,这样就保证了信息的安全。

Figure 11: SSH connection creation process


5. Troubleshooting + 一些问题

这篇文章本来是周六就写完的,但是在发布文章的时候,我突然发现,我在remote server执行git pull的时候遇到了Permission Error……

Figure 12: permission denied (public key)

这不是打脸了吗……明明文章是关于ssh的设置,到最后还是没有设置成功……最让我百思不得其解的是,之前明明是可以用的啊(不然我是怎么截的图……),第二次就不行了???

经过了漫长的trouble shooting过程,看了很多文章,还是不明白为啥会有这个问题……

对比了我的操作过程和官方教程,发现唯一的区别可能是我没有用默认的id_rsa文件来做配置,而是自己重新生成了一个github key pair。

于是我尝试把默认的public key加入了GitHub的SSH key里面,

cat ~/.ssh/id_rsa.pub

Figure 13: default public key

然后遇到了文件夹的Permission issue,这个时候千万不要用sudo git clone ...来尝试解决问题,而必须要改变当前文件夹的权限。

为什么呢?

因为如果用sudo来clone project,这个进程使用的ssh key是从 /root/.ssh里面来的,而不是/home/user/.ssh,换言之,你server所采用的public key和GitHub里面存的不是同一个,这么一来你就会看到从GitHub发来的Permission Denied error,然后陷入【为什么明明已经存了这个key它就是不认识??】的无限纠结(说的就是我)。

Figure 14: use default key

修改文件夹权限的指令是:

sudo chmod a+rwx .

修改完成后,再次用git clone,这次是成功的(我的default key是有passphrase的,现在每次clone都要输一遍……不开心)。

当我尝试删除GitHub里面的id_rsa.pub文件,只保留github.pub文件时,我是无法进行git clone操作的(如图12)……太闹心了。

两个public key都在我的authorized_keys文件中,难道只能有一个是active的吗……

Figure 15: authorized_keys

目前还没有发现解决方案,如果有朋友知道的话请告诉我一下😢…

References:

Github Official Documentation

What are SSH Keys?

How SSH Key works?

Why not use sudo git clone?