OpenSSH
早期主机使用远程登录的协议是telnet,TCP/23(telnet是基于TCP的23号端口的)
telnet有两大缺陷:
1、用户认证过程是明文的;
2、数据传输是明文的;
因此telnet不再使用了。于是就出现了ssh。
1、ssh
ssh(Secure SHell,安全的shell),与telnet一样,也是一种远程登录协议,但其与telnet的实现机制不同,ssh为TCP/22(基于TCP协议的22号端口)。
与telnet一样,ssh是基于C/S架构的。在服务器端,需要运行服务器软件,监听在某个端口(套接字上)。客户端发起连接请求,服务器端在收到请求后响应客户端请求,双发建立数据传输的通道,并一直处于连接状态,当所有用户请求处理完成之后再退出。因此需要专门的客户端软件和服务器端软件。
ssh在刚刚诞生时,出现了一款软件,但后来商业化了。于是就出现了基于ssh运行在Linux/Unix上的开源软件OpenSSH(Open:开源的意思)。
ssh主要有v1,v2两个版本,通过验证发现,v1版本存在致命的缺陷,无法有效的拒绝中间人攻击,这个缺陷非常致命,到目前为止,v1处于废弃状态;最好是使用v2,但由于许多古老的设备上还在使用v1,因此不得不使得客户端能够访问v1的服务。(新购的设备尽量拒绝v1版本的协议)而OpenSSH对两种版本的协议都提供了支持。
1.1、ssh服务器端
SSH无法实现Windows上的服务器端,故此处的服务器端指的是工作在Unix/Linux的服务器端。名称为sshd(OpenSSH提供的)。
服务器端也是一个可执行程序,只不过这个可执行程序直接工作在后台。而且不会退出,一旦退出服务即终止。
1.2、OpenSSH包含的两个组件
ssh(客户端工具,命令行的)、sshd(服务器端工具)
2、SSH认证的实现和实现加密数据传输的简要概述
sshd:主机密钥
ssh服务器端需要一个主机密钥(第一次向服务器发送一个请求时,对方总是需要我们确认一个东西(对方发来一个东西,询问是否接受),这个信息就是主机密钥)。
那么那么为什么需要主机密钥呢?若通信的双方此前从来没有通信过,那么如何建立安全通信呢?此前我们讨论过,需要借助于CA证书,但SSH客户端和服务器端都未必有证书。因此没有办法验证对方身份的可靠性,在此前提下,服务器端会向客户端发送一个主机公钥,我们的客户端就会接收对方主机公钥的指纹信息,接下来客户端会被询问是否认可这个指纹,此时就需要客户端(用户)自己确认这个服务器是否是你认可的服务器(因为没有任何有效的措施能够确认对方身份,只能凭借用户自己的判断)。因此client回答yes就表示就此接受了对方主机公钥,这个公钥是主机上一对密钥的公钥信息。
具体过程如下所示:
客户端通过远程连接进行身份认证时,需要将账号密码加密后传输至服务器端,在传输过程中,账号密码存在被窃取的风险。因此SSH还支持另外一种认证方式。SSH认证方式分为以下两种:
- 基于口令的认证:默认情况下都是基于口令的认证;
- 基于密钥的认证:客户端用户自身也生成一对密钥,它把公钥放在服务器上的某个家目录下(这个公钥信息必须严格保密,不能让任何第三方知道),私钥自己保留。以后远程登录这台服务器时,不再要求输入密码,而是传输数据时用对方的公钥加密数据,若对方能用私钥将数据解密即配对成功,此时不再需要口令。但基于密钥的认证需要事先配置。
3、注意(基本安全技巧)
- 基于口令的认证存在风险,在认证时输入用户名root和密码之后,有可能被第三方暴力将密码破解,因此,一般不允许使用root用户直接在基于ssh的客户端登录,若一定要使用root用户,只能通过登录普通用户后再su过去的方式实现。口令认证时位于互联网上的服务器最后一道也是唯一一道防线;
- 并且为了安全起见,也需要对普通用户登录的主机进行限制,若一定要在不被信任的主机上远程登录,则需要通过一台VPN服务器,先连接到VPN服务器上,再由VPN服务器转连;
- 更重要的是,最好不要使用22号端口进行远程登录,因为22号端口默认为远程登录端口,易被监控暴力破解;可以换一个端口使得别人无从揣测;
- 远程登录与系统安全性密切相关,怎么强调其安全性都不为过;
- 经常换密码(一般一个月换一次,最好密码是随机的并且足够长)
4、OpenSSH配置详解
在RedHat系列的系统上,ssh是由多个rpm包组成的rpm服务。这多个rpm包有的是提供客户端的,有的是提供服务器端的,有的是提供通用组件的。如下所示:
上图中:
openssh-server-...:服务器端
openssh-clients-...:客户端
openssh-5.3p2-...:通用组件库
openssh-askpass-...:建立会话时用到的工具和库文件
4.1、获取服务的运行状态:(如果当前有22号端口表明,ssh服务处于已经启动并工作的状态)
netstat -tnl(-t表示当前主机上根TCP建立连接的所有会话,-n表示以数字的方式显示IP地址和端口,-l表示显示处于监听状态(客户端已经启动并等待与客户端连接的状态)的服务)
netstat
-r:显示路由表
-n:
-t:TCP connection
-u:UDP connection
-l:listening
-p:process,哪一个进程或程序监听了当前这个服务
获取sshd服务运行状态的另外一种方法:
4.2、配置文件详解
ssh客户端和ssh服务器端都需要配置文件:
/etc/ssh目录下:
客户端ssh配置文件:/etc/ssh/ssh_config
服务器端sshd配置文件:/etc/ssh/sshd_config
moduli:ssh中用到的密钥交换的相关信息
v1版本主机密钥对:ssh_host_key,ssh_host_key.pub
v2版本主机密钥对:
DSA算法:ssh_host_dsa_key,ssh_host_dsa_key.pub
RSA算法:ssh_host_rsa_key,ssh_host_rsa_key.pub
主机密钥是ssh会话建立的根本前提,至关重要。
此处也反映了Linux的哲学思想之一:使用文本文件保存程序的配置信息。
sshd_config配置文件解释:
man sshd_config #获取帮助文档信息
sshd服务的任何改变配置要想其生效需重启服务(脚本服务在/etc/init.d/sshd)
service sshd {start|stop|restart|reload|force-reload|condrestart|try-restart|status}
#后带空格表示注释,#后不带空格表示可用选项;
Port:指定服务的端口号;
Protocol:启用的协议版本(默认优先使用v2版本);
AddressFamily:表示若当前主机同时启用了IPv4和IPv6的地址,那么打算在哪一类地址上启用ssh服务,any表示IPV4,IPV6都可以;
ListenAddress:表示监听在哪一个地址上(若当前主机配置了两个个IP地址,只需要其中一个提供服务,需要手动指定,若不指定,默认两个都提供服务。0.0.0.0表示任意地址,当前主机配置了哪个地址,哪个地址就能提供服务,配置了多个地址就在每一个地址上提供服务,否则手动指定);
HostKey:指定密钥;
KeyRegenerationInterval:客户端临时密钥生成的间隔时间,间隔指定时间后重新生成密钥;
ServerKeyBits:服务器端密钥长度;
SyslogFacility:指定哪一个facility记录日志;
LogLevel:日志级别;
LoginGraceTime:登录时的宽容时间(登录时等待登录的时间,不登录则强行退出);
LoginGraceTime:是否允许管理员直接登录;
StrictModes:是否使用严格限定模式(不重要);
MaxAuthTries:最大登录次数;
RSAAuthentication:是否支持RSA密钥认证(基于RSA机制的密钥认证);
PubKeyAuthentication:基于密钥的认证(如果启用,客户端会生成一对密钥,公钥会放在服务器端的某个家目录下);
AuthroizedKeysFile:指定客户端公钥文件存放的家目录的文件路径;
RhostRSAAuthentication:主机认证(指的是是否信任对方主机,接下来就不需要登录了而是直接使用,不安全);
PasswordAuthentication:是否允许基于口令的认证;
ChallengeResponseAuthentication:是否使用挑战式握手协议认证(不安全,一般不允许使用);
UsePAM:是否使用UsePAM(这是一种可插入式认证模块,一般都是启用的);
X11Forwarding:是否转发X11请求;
PrintMotd:在用户登录是是否打印/etc/motd文件的内容;
PrintLastLog:在登录时是否显示哪个主机在什么时候登录过(不推荐显示,会为不法用户提供信息,在互联网上,这种信息越少出现越好,最好软件版本号都不应该提供);
Banner:欢迎标语(用户登录SSH时会将指定文件的内容当做欢迎标语为用户打印一次,启用后建立一个文件,文件路径在此处指定,登录后会显示文件中的信息);
Subsystem:(将ftp基于SSH实现叫做sftp,将ftp基于SSL实现叫做ftps)指定sftp的服务器程序,只要指定的程序存在即可默认启动。
ssh客户端工具的使用:
ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] [user@]hostname [command]
常用命令组合:
ssh -l USERNAME REMOTE_HOST ['COMMAND']
ssh USERNAEM@REMOTE_HOST ['COMMAND']
-p port:指定端口
-X:登录到远程主机上,并且能够执行远程主机的窗口命令,因为这些窗口要在本地显示,因此,本地必须是图形化的
-Y:功能与-X一样,单比-X更安全
在第一次远程登录接受了密钥之后,系统会认为这是可信任的主机,因此它会将主机的密钥信息添加到可信任主机列表中。每个用户只要登录过远程主机,在当前用户的家目录下会生成一个.ssh文件夹,文件夹中有一个knows_host文件,任何时候接受了主机,哪个主机的公钥信息就会保存在这个文件中。因此当第二次进行远程登录时,会将文件中的公钥与远程主机的私钥一建立会话测试是否能匹配上,若配对成功,表示认可了对方主机,因此就不需要进行密钥接受了。(此过程信任是单向的)
SSH支持不登录远程主机但却可以在远程主机上执行命令,并将命令的执行结果返回到本地。只需在命令的最后加上可执行命令即可。
5、基于密钥的认证的实现:
需要一台主机作为客户端(前提是基于某个用户实现):
(1).生成一对密钥
ssh-keygen
-t [指定加密算法rsa或dsa](生成的密钥默认保存在用户家目录下面的.ssh/id_rsa和.ssh/id_rsa.pub)
-f /path/to/keyfile:指定生成的私钥文件目录
-N 'password':指定密码为password
注:.ssh的权限为700,若大于700,.ssh将无法使用。
(2).将生成的公钥传输至服务器端某用户及目录的.ssh/authrorized_keys文件中(可与当前用户不一致)
方法一:使用文件传输工具实现,专用命令:ssh-copy-id
ssh-copy-id -i /path/to/pubkey(公钥文件位置) USERNAME@ROMATE_HOST(既复制又能追加到文件尾部)
方法二:ssh另外一个重要的客户端工具scp(基于ssh的远程复制命令,能够在主机之间传输数据(因为是基于ssh传输,因此传输与过程是加密的))
scp [opetions] SRC DEST
-r:递归复制目录
-p:保存权限
-a:相当于-rp
SRC或DEST为REMOTE_MACHINE(远程主机)时的格式:
USERNAME@HOSTNAME:/path/to/somefile
scp的实现是需要先复制到临时文件中,再将临时文件使用cat 文件名 >> 目标文件 追加到文件中
(3).测试登录即可
sftp:基于SSH的ftp,既是客户端又是服务器端,数据传输过程是加密的;
sftp USERNAME@IP #连接远程主机
下载文件到本地:get /path/to/somefile
多个文件使用mget;
总结:
1.密码应该经常切换且足够复杂;
2.使用非默认端口;
3.限制登录的客户端地址;
4.禁止管理员直接登录;
5.仅允许有限用户登录;
6.使用基于密钥的认证;
7.不要使用版本1;
嵌入式系统专用的ssh软件:dropbear(可安装测试使用)