问题提出:
传统的网络服务程序,如rsh、FTP、POP和Telnet其本质上都是不安全的;因为它们在网络上用明文传送数据、用户帐号和用户口令,很容易受到中间人(man-in-the-middle)攻击方式的攻击。就是存在另一个人或者一台机器冒充真正的服务器接收用户传给服务器的数据,然后再冒充用户把数据传给真正的服务器。
这个问题简单说就是如何认证服务器端。
另外 telnet ftp 等协议登录远程服务器都是通过密码验证的方式,没有其他方式。
这个问题简单说就是如何认证客户端。
为了解决以上的问题 ssh协议出现了,它是如何实现服务端人证和客户端认证的呢?
首先,我们来了解一下SSH中几种不同的Key。
SSH结合使用了Public Key和Secret Key,Public Key用于在建立安全通道前在客户端和服务端之间传输Secret Key和进行身份认证;Secret Key则用来作为SSH会话的安全保证,对数据进行加密和解密。
名称 | 生命周期 | 创建 | 类型 | 描述 |
---|---|---|---|---|
Host Key | 持久化 | 服务端 | Public Key | 服务器的公钥,用于对服务端进行认证 |
User Key | 持久化 | 用户 | Public Key | 对客户端(用户)进行认证 |
Server Key | 默认为1小时 | 服务端 | Public Key | 用于帮助建立安全的数据传输通道 |
Session Key | 客户端 | 会话(Session) | Secret Key | 对称秘钥,用于对传输的数据进行加密 |
SSH处理过程可以分解成几个主要阶段:
每个阶段均涉及到客户端与服务端的多次交互,通过这些交互过程完成包括证书传输、算法协商、通道加密等过程。
至此,双方完成协议协商。如果该过程中,客户端或服务端发送SSH版本无法兼容,任何一方都可以断开连接。
完成协议协商阶段后,客户端与服务端已经建立明文的通信通道,之后进入服务端认证阶段。
SSH协议中没有明确的服务端认证过程,而通过一系列的服务端与客户端的交互来确定服务端的身份,该过程还会完成Host Key、User Key、Session Key等在客户端与服务端之间的传输。
这个时候,客户端和服务端使用Host Key、Server Key和8字节的随机数生成一个128位的MD5值,作为此次会话的session key。
客户端在接收到服务端Host Key后,会检查自己的knows host数据库中(一般为~/.ssh/know_hosts文件),是否已经包含当前服务端的Host Key,如果有则继续下一步;如果没有或包含当前服务端的其他Host Key则,由用户决定是否信任该服务端,或终止当前连接。
客户端向服务端发送session Key
出于性能考虑,SSH采用对称加密(Secret Key),对实际通信内容进行加密,即Session Key。因此Session Key的安全尤为重要,一旦Session Key泄漏给攻击者,那所有的通信数据都可能被攻击者截获。
由于当前通道还是采用明文方式,客户端采用Host Key和Server Key对Session Key进行两次加密来加强安全性。
SSH提供多种客户端认证方式。
SSH-1:
SSH-2:
这里只讨论我们经常使用的的Password和Public Key方式。
此时安全通道已经及建立,之后的所有内容都通过Session Key加密后进行传输。
Password
Password方式既客户端提供用户和密码,服务端对用户和密码进行匹配,完成认证。类Unix系统中,如OpenSSH的框架,一般通过系统的本地接口完成认证。
Password的优势是简单,无需任何额外的配置就可以使用。缺点密码不便于记忆,过于简单的密码容易被暴力破解。
Public Key
Public Key认证的基本原理是基于分对称加密方式,分别在服务端对一段数据通过公钥进行加密,如果客户端能够证明其可以使用私钥对这段数据进行解密,则可以说明客户端的身份。因为服务端需要使用客户端生成的密钥对的公钥对数据首先加密,所以需要先将公钥存储到服务端的密钥库(Auhtorized Key)。还记得Github中使用git协议push代码前需要先添加SSH KEY吗?
下面详细介绍一个通过Public Key进行客户端认证的过程。
该阶段通过Session Key提供的对称加密(Secret Key)算法,保证需要传输的任何数据的安全。
SSH的主要特性如下,如上之讲解了加密,完整性和认证 ,至于授权和转发待续。
总结 :
客户端校验服务器端是通过用户手动确认服务器端是否值得信任。
服务器校验客户端 是必须把客户端的公钥先放到服务器的~/.ssh/authorized_keys 文件里,否则无法建立连接。
ssh协议的 这种实现方式 只局限于使用ssh 协议的客户端和服务器之间的交互,其他软件服务无法使用它。但是其实我们非常需要一个通用的,建立在应用层之下的一个传输层安全协议,它的目标是建立一种对上层应用协议透明的,不管是HTTP、FTP、还是电子邮件协议或其他任何应用层协议都可以依赖的底层的可安全通信的传输层协议。
网景公司于1994年为解决上面的问题,设计了SSL(Secure Sockets Layer)协议的1.0版本,但并未发布,直到1996年发布SSL3.0之后,开始大规模应用于互联网服务。可能很多人听所过TLS(Transport Layer Security)。它相当于是SSL协议的一个后续版本,他是SSL经过IETF标准化之后的产物
跟SSH相比SSL所面临的问题要更复杂一些,上面我们提到,SSH协议通过人工鉴别Public Key的printfinger来判断与之通信的服务器是否可信(不是伪装的中间人)。可是SSL是为了整个互联网上的所有客户端与服务器之间通信而设计的,他们彼此之间不可能自己判断通信的对方是否可信。那么如何解决这个问题呢?
ssl 如何实现服务器认证呢? 基于证书
步骤3 中,客户端校验服务器证书 (客户端 在和服务器建立连接之前,服务器的证书会线下 给到客户端,客户端把服务器的证书添加到信任管理器中,在握手的时候,服务器也会发送证书过来,客户端 1 可以通过比较服务器证书是否在自己信任证书列表来决定服务器是否是可信的。2 会使用CA的公钥对数字签名进行解密得出一个信息摘要,然后用哈希算法自己算出信息摘要,对比摘要,一致的话,证明该证书是CA机构颁发的。因为公钥只能解开私钥加密的数据,如果信息摘要是匹配的,那么证明该加密数据是由CA机构用私钥加密的,证书是可靠的。)
假如客户端校验通过,并使用证书公钥加密premaster secret发送给服务端,如果服务器端是假的,他肯定没有对应的私钥证书用来解密,也就无法完成正确的通信。
这样就认证了服务器
ssl 如何实现客户端认证呢?
客户端认证完 服务器之后 ,需要把自己的证书发送给服务器端,同样服务器端也会提前把客户端的证书 放到自己的信任管理器里。逻辑同服务器认证。
ssh 和ssl 的比较
1 服务器认证方式不同:
ssh 服务器认证 建立连接的时候,服务端下发公钥,然后客户端.ssh/know_hosts 文件里如果不存在需要手动确认服务器是否值得信任
ssl 服务器认证 是通过把正确服务器证书 放到客户端的信任管理器里,然后连接的时候下发证书,客户端自动做比较证书是否可以信任,
另外客户端可以跳过服务器认证。
2 客户端端认证方式不同:
ssh 客户端认证 是需要提前把客户端的公钥放到服务器的~/.ssh/authorized_keys文件里,然后建立连接的时候,服务器判断文件里是否存在客户端的公钥,如果不存在,停止建立连接
ssl客户端认证 是通过把客户端证书 放到服务端的信任管理器里,并且在连接的时候上传证书,服务器自动做比较证书是否可以信任
3 客服端认证的时候,服务端存放客户端证书的位置不同
ssh服务器是把客户端公钥放到了~/.ssh/authorized_keys文件里
ssl服务器是把客户端证书放到了服务器端信任的证书库里,然后通过一个位置指定这个证书库。
4 服务端认证的时候,客户端存放服务器证书的位置不同
ssh客户端是把服务端公钥放到了~/.ssh/know_hosts文件里
ssl客户端是把服务端证书放到了客户端端信任的证书库里,然后通过一个位置指定这个证书库。
5 认证的标准不同
ssh 是通过公钥认证。
ssl 是通过证书认证。
6 OSI七层模型中的位置不同
SSL协议包含两个子协议:
在互联网层次中,SSH与HTTP,FTP类似,归于OSI七层参考模型中的应用层协议,它是使用TCP协议的应用层服务中的一员。
为什么非要用证书呢?
如果使用公钥和私钥来做服务器和客户端认证有一个问题,以上我们说过,客户端要把服务器的证书或者公钥添加到自己的信任管理器里,如果客户端从一开始获取到的公钥就是假的,那后面的一切流程就都是错的了。所以数字证书出现了。
数字证书是经过权威机构(CA)认证的公钥,通过查看数字证书,可以知道该证书是由那家权威机构签发的,证书使用人的信息,使用人的公钥,以及数字签名。 这样客户端就可以判断出拿到的证书是否是真的证书。
它有以下特点:
1、由专门的机构签发的数字证书才安全有效。
2、签发数字证书是收费的。
3、不会被冒充,安全可信。
4、数字证书有使用期限,过了使用期限,证书变为不可用。CA也可以在试用期内,对证书进行作废操作。
ssh 协议使用示例:
SSH协议存在多种实现,既有商业实现,也有开源实现OpenSSH,它是自由软件,应用非常广泛。
SSH是由客户端和服务端的软件组成的,有两个不兼容的版本分别是:1.x和2.x。 用SSH 2.x的客户程序是不能连接到SSH 1.x的服务程序上去的。OpenSSH 2.x同时支持SSH 1.x和2.x。
ssh 服务器安装:
sudo yum install sshd或者sudo yum install openssh-server
sudo service sshd start
ssh 客户端登录:
口令登录: ssh -p 2222 user@host
公钥登录:
使用密码登录,每次都必须输入密码,非常麻烦。好在SSH还提供了公钥登录,可以省去输入密码的步骤。
所谓"公钥登录",原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
这种方法要求用户必须提供自己的公钥。如果没有现成的,可以直接用ssh-keygen生成一个:
$ ssh-keygen
运行上面的命令以后,系统会出现一系列提示,可以一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。
运行结束以后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。
这时再输入下面的命令,将公钥传送到远程主机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
六、authorized_keys文件
远程主机将用户的公钥,保存在登录后的用户主目录的$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文件后,公钥登录的设置就完成了。
1、Putty
经典的SSH客户端软件,不过太简陋了。免费的。
2、PuttyMan
基于Putty的SSH客户端软件,改进有限。免费的。
3、SSH Secure Shell Client
据说还不错。
4、SecureCRT
功能全面也比较流行的SSH客户端软件,收费的。
5、Xshell
功能全面,也是收费的,但Free for Home/School。
6 FinalShell
7linux ssh 命令
Teleport
TinySSH
openssh
1.安装SSH
如果你用的是redhat,fedora,centos等系列linux发行版,那么敲入以下命令:
sudo yum install sshd 或
sudo yum install openssh-server(由osc网友 火耳提供)
如果你使用的是debian,ubuntu,linux mint等系列的linux发行版,那么敲入以下命令:
sudo apt-get install sshd 或
sudo apt-get install openssh-server(由osc网友 火耳提供)
然后按照提示,安装就好了。
2.开启ssh服务
service sshd start
3.卸载服务
如果你用的是redhat,fedora,centos等系列linux发行版,那么敲入以下命令:
yum remove sshd
如果你使用的是debian,ubuntu,linux mint等系列的linux发行版,那么敲入以下命令:
sudo apt-get –purge remove sshd
4 配置
ssh_config和sshd_config都是ssh服务器的配置文件,二者区别在于,前者是针对客户端的配置文件,后者则是针对服务端的配置文件。两个配置文件都允许你通过设置不同的选项来改变客户端程序的运行方式。下面列出来的是两个配置文件中最重要的一些关键词,每一行为“关键词&值”的形式,其中“关键词”是忽略大小写的。
1、编辑 /etc/ssh/ssh_config 文件
Host *
ForwardAgent no
ForwardX11 no
RhostsAuthentication no
RhostsRSAAuthentication no
RSAAuthentication yes
PasswordAuthentication yes
FallBackToRsh no
UseRsh no
BatchMode no
CheckHostIP yes
StrictHostKeyChecking no
IdentityFile ~/.ssh/identity
Port 22
Cipher blowfish
EscapeChar
下面对上述选项参数逐进行解释:
带“#”表示该句为注释不起作,该句不属于配置文件原文,意在说明下面选项均为系统初始默认的选项。说明一下,实际配置文件中也有很多选项前面加有“#”注释,虽然表示不起作用,其实是说明此为系统默认的初始化设置。
Host *
"Host"只对匹配后面字串的计算机有效,“”表示所有的计算机。从该项格式前置一些可以看出,这是一个类似于全局的选项,表示下面缩进的选项都适用于该设置,可以指定某计算机替换号使下面选项只针对该算机器生效。
ForwardAgent no
"ForwardAgent"设置连接是否经过验证代理(如果存在)转发给远程计算机。
ForwardX11 no
"ForwardX11"设置X11连接是否被自动重定向到安全的通道和显示集(DISPLAY set)。
RhostsAuthentication no
"RhostsAuthentication"设置是否使用基于rhosts的安全验证。
RhostsRSAAuthentication no
"RhostsRSAAuthentication"设置是否使用用RSA算法的基于rhosts的安全验证。
RSAAuthentication yes
"RSAAuthentication"设置是否使用RSA算法进行安全验证。
PasswordAuthentication yes
"PasswordAuthentication"设置是否使用口令验证。
FallBackToRsh no
"FallBackToRsh"设置如果用ssh连接出现错误是否自动使用rsh,由于rsh并不安全,所以此选项应当设置为"no"。
UseRsh no
"UseRsh"设置是否在这台计算机上使用"rlogin/rsh",原因同上,设为"no"。
BatchMode no
"BatchMode":批处理模式,一般设为"no";如果设为"yes",交互式输入口令的提示将被禁止,这个选项对脚本文件和批处理任务十分有用。
CheckHostIP yes
"CheckHostIP"设置ssh是否查看连接到服务器的主机的IP地址以防止DNS欺骗。建议设置为"yes"。
StrictHostKeyChecking no
"StrictHostKeyChecking"如果设为"yes",ssh将不会自动把计算机的密匙加入"$HOME/.ssh/known_hosts"文件,且一旦计算机的密匙发生了变化,就拒绝连接。
IdentityFile ~/.ssh/identity
"IdentityFile"设置读取用户的RSA安全验证标识。
Port 22
"Port"设置连接到远程主机的端口,ssh默认端口为22。
Cipher blowfish
“Cipher”设置加密用的密钥,blowfish可以自己随意设置。
EscapeChar
“EscapeChar”设置escape字符。
2、编辑 /etc/ssh/sshd_config 文件:
Port 22
ListenAddress 192.168.1.1
HostKey /etc/ssh/ssh_host_key
ServerKeyBits 1024
LoginGraceTime 600
KeyRegenerationInterval 3600
PermitRootLogin no
IgnoreRhosts yes
IgnoreUserKnownHosts yes
StrictModes yes
X11Forwarding no
PrintMotd yes
SyslogFacility AUTH
LogLevel INFO
RhostsAuthentication no
RhostsRSAAuthentication no
RSAAuthentication yes
PasswordAuthentication yes
PermitEmptyPasswords no
AllowUsers admin
?下面逐行说明上面的选项设置:
Port 22
"Port"设置sshd监听的端口号。
ListenAddress 192.168.1.1
"ListenAddress”设置sshd服务器绑定的IP地址。
HostKey /etc/ssh/ssh_host_key
"HostKey”设置包含计算机私人密匙的文件。
ServerKeyBits 1024
"ServerKeyBits”定义服务器密匙的位数。
LoginGraceTime 600
"LoginGraceTime”设置如果用户不能成功登录,在切断连接之前服务器需要等待的时间(以秒为单位)。
KeyRegenerationInterval 3600
"KeyRegenerationInterval”设置在多少秒之后自动重新生成服务器的密匙(如果使用密匙)。重新生成密匙是为了防止用盗用的密匙解密被截获的信息。
PermitRootLogin no
"PermitRootLogin”设置是否允许root通过ssh登录。这个选项从安全角度来讲应设成"no"。
IgnoreRhosts yes
"IgnoreRhosts”设置验证的时候是否使用“rhosts”和“shosts”文件。
IgnoreUserKnownHosts yes
"IgnoreUserKnownHosts”设置ssh daemon是否在进行RhostsRSAAuthentication安全验证的时候忽略用户的"$HOME/.ssh/known_hosts”
StrictModes yes
"StrictModes”设置ssh在接收登录请求之前是否检查用户家目录和rhosts文件的权限和所有权。这通常是必要的,因为新手经常会把自己的目录和文件设成任何人都有写权限。
X11Forwarding no
"X11Forwarding”设置是否允许X11转发。
PrintMotd yes
"PrintMotd”设置sshd是否在用户登录的时候显示“/etc/motd”中的信息。
SyslogFacility AUTH
"SyslogFacility”设置在记录来自sshd的消息的时候,是否给出“facility code”。
LogLevel INFO
"LogLevel”设置记录sshd日志消息的层次。INFO是一个好的选择。查看sshd的man帮助页,已获取更多的信息。
RhostsAuthentication no
"RhostsAuthentication”设置只用rhosts或“/etc/hosts.equiv”进行安全验证是否已经足够了。
RhostsRSAAuthentication no
"RhostsRSA”设置是否允许用rhosts或“/etc/hosts.equiv”加上RSA进行安全验证。
RSAAuthentication yes
"RSAAuthentication”设置是否允许只有RSA安全验证。
PasswordAuthentication yes
"PasswordAuthentication”设置是否允许口令验证。
PermitEmptyPasswords no
"PermitEmptyPasswords”设置是否允许用口令为空的帐号登录。
AllowUsers admin #限定登录的用户名
"AllowUsers”的后面可以跟任意的数量的用户名的匹配串,这些字符串用空格隔开。主机名可以是域名或IP地址。
通常情况下我们在连接 OpenSSH服务器的时候假如 UseDNS选项是打开的话,服务器会先根据客户端的 IP地址进行 DNS PTR反向查询出客户端的主机名,然后根据查询出的客户端主机名进行DNS正向A记录查询,并验证是否与原始 IP地址一致,通过此种措施来防止客户端欺骗。平时我们都是动态 IP不会有PTR记录,所以打开此选项也没有太多作用。我们可以通过关闭此功能来提高连接 OpenSSH 服务器的速度。
服务端步骤如下:
编辑配置文件 /etc/ssh/sshd_config
vim /etc/ssh/sshd_config
找到 UseDNS选项,如果没有注释,将其注释
添加
UseDNS no
找到 GSSAPIAuthentication选项,如果没有注释,将其注释
添加
GSSAPIAuthentication no
保存配置文件
重启 OpenSSH服务器
/etc/init.d/sshd restart
注意:
一般远程修改ssh端口,建议22端口留着防止修改未成功,连不上都SB了。如果开启防火墙记得添加端口放行!
port 22
port 2345
ssh [email protected] "cd ~/x_engine/logs/strategy/ && cat strategy-info.log"
后面多个命令用 “” 引起来,并且多个命令之间 用 && 隔离。
使用ssh 连接服务器的时候 ,有时候会提示
The authenticity of host ... can't be established.
ECDSA key fingerprint is ...
Are you sure you want to
continue
connecting (
yes
/no
)
这是要客户端人工做服务端公钥认证 如果完全相信服务端,
为了避免出现上述场景,往 ssh 命令添加如下参数:
ssh
-o
"StrictHostKeyChecking no"
username@password 添加这个选项就可以了。
sshpass 是一个用于非交互的 ssh 密码验证工具,使用前先安装:
yum
install
sshpass
sshpass -p password
ssh
-o
"StrictHostKeyChecking no"
username@
hostname
《cmd》
方法1
怎么解决这个问题?幸运的是,您可以在命令中添加一个switch。switch是-t。-t做什么?它强制执行伪终端分配,因此ssh不知道它没有可用的本地终端。
因此,要通过ssh运行需要sudo权限的远程命令,ssh命令如下所示:
ssh -t USER @ SERVER_IP “sudo COMMAND”
方法2
ssh -o "StrictHostKeyChecking no" username@password "echo