--------------------------------------------------------------------html
本文参考多篇文章结合自身状况完成,可自由转载,需保留本文出处!ios
博主:疲惫的豆豆git
http://www.cnblogs.com/dzblog/p/6930147.htmlgithub
--------------------------------------------------------------------算法
看完后须要明白的如下几个概念:shell
know_host : 存储 已经确保正常、能够安全链接的全部服务器(hosts)的公钥。ubuntu
authorized_hosts : 存储 已经认证的客户端的公钥。vim
public key :公钥segmentfault
private key :私钥安全
使用ssh和https有什么不一样:
HTTPS:使用https url克隆对初学者来讲会比较方便,复制https url而后到git Bash里面直接用clone命令克隆到本地就行了,可是每次fetch和push代码都须要输入帐号和密码,这也是https方式的麻烦之处(发现了https免密登陆的方式)。
SSH:使用SSH url克隆却须要在克隆以前先配置和添加好SSH key,所以,若是你想要使用SSH url克隆的话,你必须是这个项目的拥有者或管理员,不然你是没法添加SSH key的。另外ssh默认是每次fetch和push代码都不须要输入帐号和密码,若是你想要每次都输入帐号密码才能进行fetch和push也能够另外进行设置
生成SSH Key的基本命令:
#步骤1: cd ~/.ssh ls #这两个命令就是检查是否已经存在id_rsa.pub或id_dsa.pub文件,若是文件已经存在,那么你能够跳过步骤2 #步骤2:建立一个SSH Key ssh-keygen -t rsa -C "你的email地址" #代码参数含义: #-t指定密钥类型,默认是rsa,能够省略。 #-C设置注释文字,好比邮箱。 #-f指定密钥文件存储文件名。
SSH是一种网络协议,用于计算机之间的加密登陆。若是一个用户从本地计算机,使用SSH协议登陆另外一台远程计算机,咱们就能够认为,这种登陆是安全的,即便被中途截获,密码也不会泄露。
最先的时候,互联网通讯都是明文通讯,一旦被截获,内容就暴露无疑。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登陆信息所有加密,成为互联网安全的一个基本解决方案,迅速在全世界得到推广,目前已经成为Linux系统的标准配置。
SSH仅仅是一协议标准,其具体的实现有不少,既有开源实现的OpenSSH,也有商业实现方案。使用范围最普遍的固然是开源实现OpenSSH。
本文只讨论SSH在Linux Shell中的用法。若是要在Windows系统中使用SSH,请使用PuTTY。
SSH主要用于远程登陆。假定你要以用户名user,登陆远程主机host,只要一条简单命令就能够了。
$ ssh user@host
若是本地用户名与远程用户名一致,登陆时能够省略用户名。
$ ssh host
SSH的默认端口是22,也就是说,你的登陆请求会送进远程主机的22端口。使用p参数,能够修改这个端口,好比改为8888。
$ ssh -p 8888 user@host
上面这条命令表示,ssh直接链接远程主机的8888端口。
既然说ssh是互联网安全的一个基本解决方案,那若是保证数据安全?
首先想到的实现方案确定是对数据进行加密。加密的方式主要有两种:
所谓对称加密,指加密解密使用同一套秘钥。以下图所示:
对称加密-Client端
对称加密-Server端
对称加密的加密强度高,很难破解。
可是在实际应用过程当中不得不面临一个棘手的问题:如何安全的保存密钥呢?尤为是考虑到数量庞大的Client端,很难保证密钥不被泄露。一旦一个Client端的密钥被窃据,那么整个系统的安全性也就不复存在。为了解决这个问题,非对称加密应运而生。非对称加密有两个密钥:"公钥"和"私钥"。
特性:
公钥加密后的密文,只能经过其对应的私钥进行解密。
经过公钥推理出私钥的可能性微乎其微。
以用户TopGun为例,以下(图三):
登陆流程:
远程Server收到Client端用户TopGun的登陆请求,Server把本身的公钥发给用户。
Client使用这个公钥,将密码进行加密。
Client将加密的密码发送给Server端。
远程Server用本身的私钥,解密登陆密码,而后验证其合法性。
若验证结果,给Client相应的响应。
私钥是Server端独有的,这就保证了Client的登陆信息即便在网络传输过程当中被窃据,也没有私钥进行解密,保证了数据的安全性,这充分利用了非对称加密的特性。
这就必定安全了吗?
SSH之因此可以保证安全,缘由在于它采用了公钥加密。
整个过程如上图所示:
(1)远程主机收到用户的登陆请求,把本身的公钥发给用户。
(2)用户使用这个公钥,将登陆密码加密后,发送回来。
(3)远程主机用本身的私钥,解密登陆密码,若是密码正确,就赞成用户登陆。
这个过程自己是安全的,可是实施的时候存在一个风险:
Client端如何保证接受到的公钥就是目标Server端的?,若是一个攻击者中途拦截Client的登陆请求,向其发送本身的公钥,Client端用攻击者的公钥进行数据加密。攻击者接收到加密信息后再用本身的私钥进行解密,不就窃取了Client的登陆信息了吗?
若是有人截获了登陆请求,而后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。由于不像https协议,SSH协议的公钥是没有证书中心(CA)公证的,也就是说,都是本身签发的。能够设想具体场景,若是攻击者插在用户与远程主机之间(好比在公共的wifi区域),用伪造的公钥,获取用户的登陆密码。再用这个密码登陆远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)。
以用户TopGun为例,如图四:
那SSH协议是如何应对的呢?
从上面的描述能够看出,问题就在于如何对Server的公钥进行认证?在https中能够经过CA来进行公证,但是SSH的publish key和private key都是本身生成的,无法公证。只能经过Client端本身对公钥进行确认。
一般在第一次登陆的时候,系统会出现下面提示信息:
$ ssh user@host The authenticity of host 'host (12.18.429.21)' can't be established. RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d. Are you sure you want to continue connecting (yes/no)?
上面的信息说的是:没法确认主机host(12.18.429.21)的真实性,不过知道它的公钥指纹,询问你是否继续链接?
所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,因此对其进行MD5计算,将它变成一个128位的指纹。上例中是98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d,再进行比较,就容易多了。
之因此用fingerprint代替key,主要是key过于长(RSA算法生成的公钥有1024位),很难直接比较。因此,对公钥进行hash生成一个128位的指纹,这样就方便比较了。
很天然的一个问题就是,用户怎么知道远程主机的公钥指纹应该是多少?
回答是没有好办法,远程主机必须在本身的网站上贴出公钥指纹,以便用户自行核对,或者本身甄别host地址是否正确。
假定通过风险衡量之后(通常用户直接就选择yes吧),用户决定接受这个远程主机的公钥。
Are you sure you want to continue connecting (yes/no)? yes
系统会出现一句提示,表示host主机已经获得承认。
Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.
而后,会要求输入密码。
Password: (enter password)
若是密码正确,就能够登陆了。
当远程主机的公钥被接受之后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再链接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。
每一个SSH用户都有本身的known_hosts文件,此外系统也有一个这样的文件,一般是/etc/ssh/ssh_known_hosts,保存一些对全部用户均可信赖的远程主机的公钥。
我本地的known_hosts文件,能够发现已经保存了五个我以为放心的服务器(hosts)的公钥
简单说,当host已被确认,并被追加到文件known_hosts中,下次链接只须要输入密码便可,以后的流程就按照图3进行。
|1|sgbtTTUJ/9xTRBchGIGXXt51J6M=|Bb5EzE/lSWWElJN12apF7fSxtSY= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAQmeHZvdibukSrHVjiGvRRp121o9u6wggOnckia4LTv6AS/r3F05BogWJuPCyjEXT+U3neNYGtcqbSsXv/fO+U= |1|F4L6YTHVeEcS/E9eqk5xLOHKNr4=|SEILG9DHeT9FA9H/cjyvMzWSgew= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGZgdcSEtfhdP83mlq1WOUlByl5zT4Mxn2SrH/EydDTO32reFKwUgAVOnHC0qVXIpp1Cup//qi1BbItUguENAro= |1|pPkIGKq8X1aFVc3Yawr3L8waBes=|JOtrUbUxAAq20A/yKwHWKawirIk= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGZgdcSEtfhdP83mlq1WOUlByl5zT4Mxn2SrH/EydDTO32reFKwUgAVOnHC0qVXIpp1Cup//qi1BbItUguENAro= |1|QCS+wt47tTYBGwGT/xCqca38sTo=|IqOJYH8AS6hvBwKO8V5dwmfGQik= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBORUpIyKsByC4cmSytCVpSLrLcWgu5x/2Oy0eDpxI9qzvQf13p9/e74un+AsyspKhV8CVW0ES65YPy1cgGGp79Y= |1|/cf8UrQvOCilbSE6NBIPApJ+QDU=|sC0XF3Ug/QyCl770t0EsulwcXN8= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHEfk6MWAQM5uutCW+wUiTVcEkE5NUG4Tp6AFputB7dKlga1yOEA1mHs90gDN8Gg1u44mUEEDp/xPU6qnZ2Lv6A=
使用密码登陆,每次都必须输入密码,很是麻烦。好在SSH提供了另一种能够免去输入密码过程的登陆方式:公钥登陆。
所谓"公钥登陆",原理很简单,就是用户将本身的公钥储存在远程主机上。
登陆的时候,远程主机会向用户发送一段随机字符串,用户用本身的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,若是成功,就证实用户是可信的,直接容许登陆shell,再也不要求密码。
以用户TopGun为例,流程以下:
公钥认证流程:
1. Client端用户TopGun将本身的公钥存放在Server上,追加在文件authorized_keys中。
2. Server收到登陆请求后,随机生成一个字符串str1,并发送给Client。
3. Client用本身的私钥对字符串str1进行加密。
4. 将加密后字符串发送给Server。
5. Server用以前存储的公钥进行解密,比较解密后的str2和str1。
6. 根据比较结果,返回客户端登录结果。
在步骤1中,Client将本身的公钥存放在Server上。须要用户手动将公钥copy到server上。这就是在配置ssh的时候进程进行的操做。下图是GitLab上SSH keys设置视图:
这种方法要求用户必须提供本身的公钥。若是没有现成的,能够直接用ssh-keygen生成一个:
$ ssh-keygen
运行上面的命令之后,系统会出现一系列提示,能够一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),若是担忧私钥的安全,这里能够设置一个。
运行结束之后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。
好比,我须要用用户user登陆host服务器,只需再输入下面的命令,将公钥传送到远程主机host上面:
$ ssh-copy-id user@host
好了,今后你再登陆,就不须要输入密码了。
若是仍是不行,就打开远程主机的/etc/ssh/sshd_config这个文件,检查下面几行前面"#"注释是否取掉。
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
而后,重启远程主机的ssh服务。
// ubuntu系统
service ssh restart
// debian系统
/etc/init.d/ssh restart
远程主机将用户的公钥,保存在登陆后的用户主目录的$HOME/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就好了。
这里不使用上面的ssh-copy-id命令,改用下面的命令,解释公钥的保存过程:
$ ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub
这条命令由多个语句组成,依次分解开来看:(1)"$ ssh user@host",表示登陆远程主机;(2)单引号中的mkdir .ssh && cat >> .ssh/authorized_keys,表示登陆后在远程shell上执行的命令:(3)"$ mkdir -p .ssh"的做用是,若是用户主目录中的.ssh目录不存在,就建立一个;(4)'cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub的做用是,将本地的公钥文件~/.ssh/id_rsa.pub,重定向追加到远程文件authorized_keys的末尾。
写入authorized_keys文件后,公钥登陆的设置就完成了。
我本地的ahtorized_keys文件。添加后内容以下:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQsqm2aqI3MCUcDlcqnU9JfE30TYfUjayKGf/+WvLOpFVUqhwnrAFVT7VaCW5G5Lh3IlWzGCflhl0Yjasb3BTELV+W+zHpefgEwJaNB725yfzdPvk/aGrHv7UusggMqqR11JDW2zlISo/xUysEzJ4pTnjz6AcdKUCE8biB3s37yTSa8k78g2j06tzLglr+np179jCiq9RJfKCs/omeCHbU+pyhcCk6DoL/SRHzNczfHIcJBvhWvY7CPKHb2vqD9k5d9cS2renGvB2/fCkyyNdnVZgKc3r5ufJUD+yWJ6yMHNT/hMn0uybEHuVz8s/zXjdH3xgx40UrfLs8eNKTKpAN app@bjxg-ap-27-7 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCk7sNBV8ag8KKApN4mapTQTkDEbcA3VNFIhSuO+YLTbkO29KU6FSQhlT2It2hmmmdaVJXEMx6JmQS7+62DNHIpHnzaKimEU+tKosAdOwHoZPcskMw6QlvjkhicKg7+kNsFdeSuAtE3V4ShbFPUfRNAs/9a/b56/FqqGIk6oPVu19CSvMyLnnqTht9rMQdIw4uOynogEKivgdwsAFh4qayJSz8VwklN9dx+8dqw8e9e/CxXEDWuZ2T/DtEa+gIRy0bvJaDcgzcpvxMkf+71HTpYlvkziF1YPmPX60gcyCkRkLnmM1fSkHXhAmBxZuSLc3l1VKXXWkH9rsgvxLzKuML/ app@bjxg-ap-28-7
生成密钥操做
1. 打开ssh目录,通常是隐藏的 cd ~/.ssh
2. 生成密钥文件,这样就会生成默认名字为id_rsa和id_rsa.pub
ssh-keygen -t rsa -C "YOUR_EMAIL@YOUREMAIL.COM" (说明:YOUR_EMAIL@YOUREMAIL.COM换成你本身的邮箱)
3. 打开公钥文件(id_rsa.pub),并把内容复制至代码托管平台上 或者 须要访问的服务器(host)上的authorized_keys里。
vim ~/.ssh/id_rsa.pub
进入 GitLab-->帐户设置-->Profile Settings --> SSH Keys,点击Add keys 按钮,在 Title 文本框中输入任意字符,在 Key 文本框粘贴刚才复制的公钥字符串,按保存按钮完成操做。
cd ~/.ssh/ vim authorized_keys
4. 测试
ssh -T git@gitlab.com #或者 ssh -T user@host
成功应该提示:
delon@macpro:~/.ssh$ ssh -T git@git.hostname.com
Welcome to GitLab, CIRobot!
这样就能够只用ssh协议的URL了,通常默认是https协议的,如图点击SSH便可切换:
这样push代码时就不用再输密码了。
ssh-keygen是用于生产密钥的工具。
id_rsa:保存私钥
id_rsa.pub:保存公钥
authorized_keys:保存已受权的客户端公钥
known_hosts:保存已认证的远程主机公钥
关系图:
须要注意的是:一台主机可能既是Client,也是Server。因此会同时拥有authorized_keys和known_hosts。
这部分Git熟悉的基本能够略过:有些童鞋可能在设置这个多帐号前已经配置了一个Github/GitLab的ssh,而后把代码clone下来,配置多帐号后,原来的代码就提交不上了。
此时你进入 原来clone的代码文件夹下,执行 git remote -v,便可看到远处资源库路径
如:git@github.com:test/xxxxxx.git
执行git remote remove origin删除该远程路径
执行git remote add origin git@test.github.com:test/xxxxxx.git加上正确的远程仓库。
GitLab的话
执行git remote add origin http://git.host.com/ios/项目名.git
https://segmentfault.com/a/1190000002627706
http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html
http://www.jianshu.com/p/33461b619d53