SSH 是一种以安全的方式提供远程登陆的协议,也是目前远程管理Linux系统的首选方式,SSH由IETF的网络小组所制定,SSH为建立在应用层基础上的安全协议,SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议.利用SSH协议可以有效防止远程管理过程中的信息泄露问题.
SSH是一种网络协议,用于计算机之间的加密登录,如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露.最早的时候,互联网通信都是明文通信,一旦被截获,内容就暴露无疑.SSH协议将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界获得推广,目前已经成为Linux系统的标准配置.
SSH之所以能保证安全,在于它采用了公钥加密,SSH登陆验证的流程如下: 1.远程主机收到用户的登录请求,并把自己的公钥发给用户. 2.用户接受并使用这个公钥,将登录密码加密后,发送给远程主机. 3.远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录.
这个过程本身是安全的,但是实施的时候存在一个风险,如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪.因为不像https协议,SSH协议的公钥是没有证书中心(CA)公证的,都是自己签发的,很容易被钻空子.
SSH远程登陆
口令登陆
使用口令登陆: 通过使用用户名密码登陆远程主机,如下.
代码语言:javascript复制[root@localhost ~]# ssh root@192.168.1.5 -p 22
The authenticity of host 'host (192.168.1.5)' can't be established.
RSA key fingerprint is 94:ee:d7:e0:de:9f:ac:65:22:c1:22:2d:37:12:38:0d.
Are you sure you want to continue connecting (yes/no)?yes
root@192.168.1.5's password:
这段话的意思是,无法确认host主机的真实性,只知道它的公钥指纹,所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,所以对其进行MD5计算,将它变成一个128位的指纹.
输入密码后如果密码正确,就可以登录了,当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts
之中,下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码.
每个SSH用户都有自己的known_hosts文件,此外系统也有一个这样的文件,通常是/etc/ssh/ssh_known_hosts
,保存一些对所有用户都可信赖的远程主机的公钥.
公钥登陆
使用密码登录,每次都必须输入密码,非常麻烦,好在SSH还提供了公钥登录,可以省去输入密码的步骤,所谓"公钥登录",原理很简单,就是用户将自己的公钥储存在远程主机上.登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来.远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码.
1.通过命令生成密钥对,此时系统会在/root/.ssh/id_rsa
下面生成两个文件一个公钥一个私钥.
[root@localhost ~]# ssh-keygen
Generating public/private rsa key pair.
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.
2.通过一个命令将生成的公钥自动的拷贝到对方主机上,此时系统会将id_rsa.pub拷贝到对方/root目录下,并会自动命名为authorized_keys.
代码语言:javascript复制[root@localhost ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.22
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.1.22 (192.168.1.22)' can't be established.
ECDSA key fingerprint is SHA256:2kWFaV72YVvAl2EU2Zop4uAjP3Gy2jW92d0Va/HrSMM.
ECDSA key fingerprint is MD5:fc:6c:91:b0:02:e6:7e:98:52:af:0d:b3:47:d4:69:ef.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
3.下次使用ssh登陆对方主机,无需密码即可登陆上了,如果无法登陆请确保以下配置是否开启.
代码语言:javascript复制[root@localhost ~]# ssh root@192.168.1.22
Last login: Mon Nov 5 09:59:45 2018 from 192.168.1.8
[root@localhost ~]# vim /etc/ssh/sshd_config
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
其他配置
sshd服务的配置文件默认保存在/etc/ssh/sshd_config
文件中,下面我们将介绍sshd_config配置文件中的参数.
port 22 #监听端口
addressFamily any #允许所有人链接
listenAddress 0.0.0.0 #IPV4监听IP 0.0.0.0表示监听所有
listenAddress : : #IPV6监听IP
protocol 2 #使用二代协议
syslogFacility AUTHPRIV #日志认证等级
permitRootLogin yes #是否允许root登陆
passwordAuthentication yes #是否使用密码认证
permitEmptyPasswords no #是否允许空密码
loginGraceTime 2m #2分钟不输入后自动断开连接
printMotd yes #登陆后根据/etc/motd内容打印信息
printLastLog yes #输出最后一次登录信息
useDNS yes #反查主机名,关闭后可提升登陆速度
gSSAPIAuthentication yes #GSS认证,关闭后可提升登陆速度
pidFile /var/run/sshd.pid #存放sshPID的地方
usePrivilegeSeparation sandbox/yes/no #是否允许以较低权限运行
pubkeyAuthentication yes #使用公钥认证机制
authorizedKeysFile .ssh/auth #公钥的存放位置
MaxAuthTries 5 #密码最大尝试次数
MaxSessions 10 #最大允许终端数
看了上面的配置参数,接下来我们来继续看一下ssh命令的常用参数吧.
代码语言:javascript复制[root@localhost ~]# ssh --help
语法格式:[ ssh [选项] [用户名]@[地址] ]
-e #支持反斜线控制的字符转换
-q #静默模式
-i #指定身份文件
-o #指定配置选项
-X #开启X11转发功能
-x #关闭X11转发功能
-y #开启信任X11转发功能
-1 #强制使用ssh协议版本1
-2 #强制使用ssh协议版本2
-4 #强制使用IPv4地址
-6 #强制使用IPv6地址
-C #请求压缩所有数据
-f #后台执行ssh指令
-N #不执行远程指令
-F #指定ssh指令的配置文件
-A #开启认证代理连接转发功能
-a #关闭认证代理连接转发功能
-l #指定连接远程服务器登录用户名
-g #允许远程主机连接主机的转发端口
-p #指定远程服务器上的端口
-b #使用本机指定地址作为对应连接的源ip地址
SCP数据传输
scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的,可能会稍微影响一下速度.两台主机之间复制文件必需得同时有两台主机的复制执行帐号和操作权限,首先我们先看一下,scp命令的常用参数,以及几个小例子.
代码语言:javascript复制[root@localhost ~]# scp --help
语法格式:[ scp [选项] [用户名]@[地址] ]
-1 #强制scp命令使用协议ssh1
-2 #强制scp命令使用协议ssh2
-4 #强制scp命令只使用IPv4寻址
-6 #强制scp命令只使用IPv6寻址
-B #使用批处理模式,过程中不询问
-C #允许压缩
-p #留原文件的修改时间,访问时间和访问权限
-q #不显示传输进度条
-r #传送文件夹
-v #详细方式显示输出
-c #以cipher加密传输
-F #指定一个替代的ssh配置文件
-i #传输时指定密钥文件
-l #限制传输带宽,以Kbit/s为单位
-P #指定传输端口
-S #指定加密传输时所使用的程序
本地到远程: 将本地的/etc/passwd
拷贝到远程的/tmp
目录下.
[root@localhost ~]# scp /etc/passwd root@192.168.1.22:/tmp/
root@192.168.1.22's password:
passwd 100% 898 876.6KB/s 00:00
远程到本地: 将远程的/etc/shadow
拷贝到本地的/tmp
目录下.
[root@localhost ~]# scp root@192.168.1.22:/etc/shadow /tmp/
root@192.168.1.22's password:
shadow 100% 714 741.2KB/s 00:00
目录的拷贝: 把远程的/etc
整个目录,拷贝到本机的/tmp
目录下.
[root@localhost ~]# scp -r root@192.168.1.22:/etc/ /tmp/
root@192.168.1.22's password:
fstab 100% 465 188.1KB/s 00:00
crypttab 100% 0 0.0KB/s 00:00
mtab 100% 0 0.0KB/s 00:00
...省略...
SSH端口操作
绑定本地端口
SSH可以传送数据,那么我们可以让那些不加密的网络连接,全部改走SSH连接,从而提高安全性,假定我们要让8080端口的数据,都通过SSH传向远程主机,命令就这样写.
代码语言:javascript复制[root@localhost ~]# ssh -D 8080 user@host
SSH会建立一个socket,去监听本地的8080端口.一旦有数据传向那个端口,就自动把它转移到SSH连接上面,发往远程主机.可以想象,如果8080端口原来是一个不加密端口,现在将变成一个加密端口.
本地端口转发
有时,绑定本地端口还不够,还必须指定数据传送的目标主机,从而形成点对点的"端口转发".为了区别后文的"远程端口转发",我们把这种情况称为"本地端口转发"(Local forwarding).
假定host1是本地主机,host2是远程主机.由于种种原因,这两台主机之间无法连通.但是,另外还有一台host3,可以同时连通前面两台主机.因此,很自然的想法就是,通过host3,将host1连上host2.
我们在host1执行下面的命令:
代码语言:javascript复制[root@localhost ~]# ssh -L 2121:host2:21 host3
命令中的L参数一共接受三个值,分别是"本地端口:目标主机:目标主机端口",它们之间用冒号分隔.这条命令的意思,就是指定SSH绑定本地端口2121,然后指定host3将所有的数据,转发到目标主机host2的21端口(假定host2运行FTP,默认端口为21).
这样一来,我们只要连接host1的2121端口,就等于连上了host2的21端口.
代码语言:javascript复制[root@localhost ~]# ftp localhost:2121
"本地端口转发",使得host1和host3之间仿佛形成一个数据传输的秘密隧道,因此又被称为"SSH隧道",下面是一个比较有趣的例子.
代码语言:javascript复制[root@localhost ~]# ssh -L 5900:localhost:5900 host3
它表示将本机的5900端口绑定host3的5900端口(这里的localhost指的是host3,因为目标主机是相对host3而言的).
另一个例子是通过host3的端口转发,ssh登录host2.
代码语言:javascript复制[root@localhost ~]# ssh -L 9001:host2:22 host3
这时,只要ssh登录本机的9001端口,就相当于登录host2了.
代码语言:javascript复制[root@localhost ~]# ssh -p 9001 localhost
上面的-p参数表示指定登录端口.
远程转发端口
既然"本地端口转发"是指绑定本地端口的转发,那么"远程端口转发"(remote forwarding)当然是指绑定远程端口的转发,下面还是接着看上面那个例子,host1与host2之间无法连通,必须借助host3转发.但是,特殊情况出现了,host3是一台内网机器,它可以连接外网的host1,但是反过来就不行,外网的host1连不上内网的host3.这时,"本地端口转发"就不能用了.
解决办法是,既然host3可以连host1,那么就从host3上建立与host1的SSH连接,然后在host1上使用这条连接就可以了.
我们在host3执行下面的命令:
代码语言:javascript复制[root@localhost ~]# ssh -R 2121:host2:21 host1
R参数也是接受三个值,分别是"远程主机端口:目标主机:目标主机端口".这条命令的意思,就是让host1监听它自己的2121端口,然后将所有数据经由host3,转发到host2的21端口.由于对于host3来说,host1是远程主机,所以这种情况就被称为"远程端口绑定",绑定之后,我们在host1就可以连接host2了.
代码语言:javascript复制[root@localhost ~]# ftp localhost:2121
这里必须指出,"远程端口转发"的前提条件是,host1和host3两台主机都有sshD和ssh客户端.