目标
- 了解SSH是什么
- 服务端安装SSH
- 客户端安装SSH
- ssh连接远程服务
- ssh config配置讲解(多服务器管理方式)
- ssh免密码登入
- 权限问题
- 运维小技巧
SSH是什么
SSH的全称为Secure Shell,即安全外壳协议。SSH是传输层和应用层上的安全协议,专门为远程登录会话和其他网络服务提供安全性的协议。我们实际用到就是登入远程服务器,或者从git远程仓库拉取代码。
ssh认证过程分析
ssh涉及到两个验证:主机验证和用户身份验证。通过主机验证,再通过该主机上的用户验证,就能唯一确定该用户的身份。一个主机上可以有很多用户,所以每台主机的验证只需一次,但主机上每个用户都需要单独进行用户验证。
服务器安装SSH
一般情况下,服务器上都已经安装了ssh服务。可以通过 rpm -qa | grep ssh
来进行ssh服务的查看。
如果服务器上没有安装,那么我们可以直接通过yum install openssh-server
来进行安装。
客户端安装SSH
一般情况下,Linux服务器都会安装ssh客户端(它其实是openssh的客户端),但是如果安装的是minial版本的Linux,那么就不会自带ssh客户端。
此时需要手动进行安装,通过 yum install openssh-clients
启动SSH服务
启动:service sshd start,本质上是启动/etc/init.d/sshd 服务。
开机运行:chkconfig sshd on
sshd服务是open ssh的一个后台进程。
远程连接SSH
ssh 账号@ip -p 端口
ssh config配置文件的使用(多服务器管理方式)
上面我们已经学习了ssh命令的基本使用,使用ssh命令登入服务器,只需使用如下的方式即可。
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">ssh -p 26822 root@104.194.71.231</pre>
但是当我们管理多台服务器时,如果每次登入我们都需要把ip和端口找出来来进行登入,会使得我们的运维非常麻烦。因此我们可以使用ssh config文件,将这些信息进行记录,然后使用别名
的方式就可以完成登入。
SSH连接建立之前,会在系统中寻找它的配置文件,一般有两个位置:
- /etc/ssh/ssh_config:这里是对所有的用户适用的全局配置。
- ~/.ssh/config:这是个人用户的配置,只对当前用户生效,并且它会覆盖全局配置。
注意:一般来说,~/.ssh 目录的权限为700,config文件的权限需要为600。
- 在~/.ssh目录下创建一个的config文件
- 输入如下内容
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">host "linux1" HostName 104.194.71.231 User root Port 26822</pre>
它的格式是param value,或者是param=value,其中param对大小写不敏感。
- 连接远程服务器
通过这种方式,就可以简化我们的命令使用方式,避免每次都需要输入ip、账号、端口等信息。可以在config中配置多个远程服务器的信息。
config文件的权限问题
需要特别注意的是,如果当我们使用非root账号时,可能会出现如下的错误信息:
其原因时config的文件的权限必须时600。
ssh 免密码登入
ssh key 使用非对称加密方式来生成公钥和私钥,其分别对应两个文件,一般使用RSA算法。
私钥存放在本地的~/.ssh目录下。
公钥可以对外公开,放在外部服务器的~/.ssh/authorized_keys
- 我们在客户端使用ssh-keygen -t rsa 来生成公私钥
在服务器端创建****authorized_keys****文件,将客户端的公钥信息拷贝到服务器端的authorized_keys文件中。如果authorized_keys已经有内容,则追加到尾部。
在客户端,将私钥进行加载。
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">ssh-add linux1_rsa</pre>
这个步骤貌似是可选的,并不一定要执行。
- 此时,我们就完成了免密码登入到服务器。
ssh-copy-id命令使用
上面我们已经介绍了免密码登入的方式,其本质就是将自己生成的公钥,放到远程服务器的authorized_keys文件中。正常情况下,我们需要登入到远程服务器,然后创建authorized_keys文件,然后将公钥信息复制到文件中,这样虽然可以,但是处理起来有点麻烦。因此,我们可以使用更简单的方式,ssh-copy-id命令来完成这个工作:
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">ssh-copy-id -i 公钥文件 用户@地址 -p 22</pre>
在config中配置私钥文件
前面我们已经讲了使用config管理多台服务器以及使用公私钥实现免密码登入。现在我们将两者进行结合。即在config配置文件中配置一个私钥文件:
通过使用IdentifyFile来指定私钥文件。
这样我们就可以使用ssh hadoop102
就能直接登入远程服务器了。
免密码登入时出现的权限问题
对于.ssh目录以及authorized_keys文件,必须按照特定的权限来设置,不能随意设置。sshd为了安全,对属主的目录和文件权限有所要求。如果权限不对,则ssh的免密码登陆不生效。
用户目录权限为 755 或者 700,就是不能是77x。
.ssh目录权限一般为755或者700。
rsa_id.pub 及authorized_keys权限一般为644
rsa_id权限必须为600
ssh免密码登陆设置时Authentication refused: bad ownership or modes错误解决方法
SSH拉取git代码
在之前,我拉取代码一直使用的是https的方式,每次都需要输入账号和密码,特别的Low。对于这个问题,由于没有阻塞日常的开发,所以我也不以为然。但是当你的同事给你的git地址是这样的呢?git@git.coding.net:wzw/leave-a-message.git
卧槽,尴尬了,此时你用原来的方式似乎不行,最傻的方式就是你把它再次转成https,这他么太Low了。。。。所以我对次做了一番研究,同时也看了几篇文章进行了学习。
下面是我的一个研究过程,为了测试远程仓库,我特意注册了coding.net这个账号来进行测试。
最简单的方式
- 生成公私钥:
ssh-keygen -t rsa -C 784580872@qq.com
此时会生成id_rsa和id_ras.pub文件,然后你将你的公钥贴到远程服务器上去即可。
- 然后通过
ssh -T git@git.coding.net
来进行验证是否ok,注意,这里使用的是ssh来验证。
好了,就是如此简单。但是这样做有一个前提是,你的.ssh目录下面必须有一个id_rsa文件,它里面存放了我的私钥文件。
如果我将id_rsa文件删除,将其改名为coding-net_id_rsa呢?是否可以?
再次执行,你会发现,它报权限被拒绝,卧槽。。。。为啥会这样?此时我们可以开启调式模式,看看上面的命令到底在干啥。
通过输出信息我们可以看到,它会依次查找id_rsa、id_dsa等文件来获取私钥信息,由于我们的私钥文件被重命名了,因此找不到,所以报了权限错误。
修改私钥文件
通过上面的分析,我们知道如果要执行ssh -T git@git.coding.net 成功的话,必须有一个id_rsa文件。但是这会有一个问题,如果我有多个账号,咋办?两个账号不可能共用同一个私钥文件,因为私钥文件中包含了你的账号信息。
为了解决这个问题,我们可以将私钥的信息加载到ssh-agent的session中,那么当程序寻找私钥的时候,会优先到ssh-agent的session中去寻找。这个session的生命周期很短,如果失效,就需要重新加载私钥文件到新的session中。
加载私钥文件到ssh-agent的session中,结果缺报了这个错误,原因是ssh-agent没有开启。
下面我们来开启ssh-agent,然后进行私钥文件的加载,最后连上远程服务器。
通过上面的分析可以看到,如果当我们的私钥文件不是id_rsa时,那么我们就需要将私钥文件通过ssh-agent来进行加载到会话中才能实现免密码的操作。
运维小技巧
ssh 端口修改
ssh服务默认开放的端口是22,它的配置文件是/``**etc/ssh/sshd_config**``**(sshd_config是服务器端文件,ssh_config是客户端文件)**
** 。**我们可以通过修改该配置文件来改变ssh服务的端口。
注意,这里的Port可以配置多个,那么ssh服务在启动的时候,就会绑定多个端口。
限制登录的来源IP
限制登录的来源IP有多种方式:
- 通过防火墙来进行配置
- 通过修改
/etc/hosts.allow
来进行限制。
基于防火墙的配置方式
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">Iptables -A INPUT -s 192.168.1.0/24 -p tcp -m state --state NEW -m - tcp --dport 2222 -j ACCEPT</pre>
基于/etc/hosts.allow的方式限制
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">vim /etc/hosts.allow sshd:192.168.125.115:allow sshd:all:deny</pre>
这里我们配置了只有115这台机器才可以访问,其他IP不允许访问该机器。当使用其他IP的机器进行访问时,远程服务器会自动关闭连接。(这里我使用了192.168.125.101来访问)
仅允许特定用户
一般情况下,我们都会配置禁止root账户远程登入。我们可以通过修改/etc/ssh/sshd_config
文件来进行设置。
当我们配置了PermitRootLogin no
之后,就可以实现root账号的禁止登入。
取消密码验证,只用密钥对验证
我们只需要将PasswordAuthentication
修改成no即可。当再次尝试使用密码登入时,就会报如下的错误:
只允许通过指定的网络接口来访问 SSH 服务
默认情况下,ssh服务启动绑定的IP是0.0.0.0
。我们可以对其进行修改:
当修改完成之后,再次重启SSH服务,它就会绑定我们给定的IP地址:
SSH端口转发
ssh除了建立远程的安全隧道外,还可以实现端口转发的功能。我们看一个实际的业务场景:
MySQL服务器由于没有公网IP,如果我们想要去访问,只能通过跳板机来进行请求的转发。这种转发模式被称为正向转发
。其原理就是通过ssh来启动一个端口,比如上面的7777,然后我们连接到7777;ssh又会建立一个与MySQL的连接,然后将我们的请求转发到MySQL。这样,我们就可以远程登入到MySQL服务器了。
由于我们没有公网IP,那么我就使用hadoop102来模拟跳板机,然后使用hadoop103来模拟MySQL服务。首先,我们会在Hadoop103上面启动一个3306的端口。
然后我们在Hadoop102启动7777端口,来让其进行端口的转发:
0.0.0.0:7777是让hadoop102启动7777端口,而hadoop103:6666是让其将请求转发到hadoop103的6666端口,而后面的root@hadoop103表示的是跳转机地址,跳转机的地址可以和目标机器不是同一台,那么会多一次转发。比如像下面这样:
-N 告诉SSH客户端,这个连接不需要执行任何命令,仅仅做端口转发。
-f 告诉SSH客户端在后台运行。
下面我们通过连接Hadoop102的7777端口来进行测试:
通过这个例子,我们就完成了SSH端口正向转发的实现,不过这样做会存在安全隐患,相当于是把MySQL服务直接给开放出去了,因此我们还需要再防火墙这一层做IP白名单的限制。