注意:转载请注明出处:http://www.programfish.com/blog/?p=124
SSH 基本概念
SSH 英文全称是secure shell,字面意思:安全的shell。
SSH协议由IETF(Internet Engineering Task Force)的Network Working Group所制定,建立在应用层和传输层基础上相对可靠,专为远程登录会话和其他网络服务提供安全性的协议。
说其是Secure的很重要一个原因是ssh会对远程登陆时的认证信息和远程执行的命令进行加密传输。而传统的网络服务程序如ftp、telnet、pop、rlogin、rexec等都是在网络上用明文传送口令和数据,这样就容易受到网络上别有用心的人攻击(例如“中间人”)。而对SSH对口令及数据加密传输则可以有效防止这种攻击。
功能上它既可以代替telnet,又可以为ftp、pop、甚至ppp提供一个安全的“通道”。
ssh协议目前有SSH1和SSH2,SSH2协议兼容SSH1。
目前实现SSH1和SSH2协议的主要软件有OpenSSH和SSH Communications 软件。
OpenSSH是一款免费开源的SSH软件,而SSH Communications见分则是一款商业软件并且收费的。一般在类unix系统上使用的是OpenSSH。
SSH 层次结构
- 传输层协议 [SSH-TRANS]
提供服务器认证,数据机密性,信息完整性 等的支持;
- 用户认证协议 [SSH-AUTH]
为服务器提供客户端的身份鉴别;
- 连接协议 [SSH-CONN]
将加密的信息隧道复用成若干个逻辑通道,
对于这部分的详细内容请阅读:SSH协议详解 http://airekans.github.io/protocol/2012/06/28/ssh-explained/
相关的工具命令:
Sftp 使用了加密传输方式的远程传输工具,使用命令与ftp基本一样,这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低,适合网络安全性要求更高的情况使用。
Scp 非交互式sftp-server的客户端,用来向服务器上传/下载文件
Sshfs 远程目录挂载工具,非常方便实用,使用方法参见http://www.programfish.com/blog/?p=145
SSH 认证方式
SSH客户端的身份认证中提供三种方式:
- password(基于口令的安全验证)
- public key(基于密匙的安全验证)
- Hostbased验证
{SSH2.0还提供了 password-publickey 认证(方式一和二都进行)和 any 认证(进行方式一或二中的一种)}
其中最常用的是password验证及public key验证。
Password验证就是在你请求连接到远程主机的时候要求输入远程主机上的用户口令并加密传输到远程主机上进行验证。
而public key验证不需要在网络上传送口令,它依赖于在本地创建的一对密钥(公钥和私钥)进行验证。
以下会以实例操作介绍两种认证方式(使用开源的openSSH操作):
Password认证:
- 指定ip连接:
lfly@linux-oj9e:~> ssh 172.17.0.3
- 指定的主机名连接:
lfly@linux-oj9e:~> ssh www.programfish.com
- 指定登陆用户名(上面没有指定则使用当前用户名):
lfly@linux-oj9e:~> ssh lfly@172.17.0.3
lfly@linux-oj9e:~> ssh lfly@www.programfish.com
如果是第一次尝试连接到当前指定的远程主机,则会出现如下提示:
lfly@linux-oj9e:~> ssh 172.17.0.3
The authenticity of host ‘172.17.0.3 (172.17.0.3)’ can’t be established. ECDSA key fingerprint is 2a:d9:31:44:04:08:ed:ff:2e:0a:3d:31:53:65:3b:f3. Are you sure you want to continue connecting (yes/no)?
这里由于是本地首先连接到该远程主机(172.17.0.3),ssh会提示你是否要信 任这个主机,这里需要你键入yes回车,选择了信任这台主机后ssh会把这台主机上的公钥(public key)记录在~/.ssh/known_hosts这个文件下(.ssh是你家目录下的一个隐藏目录)。
这里其中一个公钥是这样的:
|1|w2w2Qcl7o5Mi4Iwcg613O+16I4A=|NpE0Zzu5NsgZ3DEpYLgNfzwhcR4= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBARhzN4tb3VaHAdPJBi/H+rW/ARafC0CSJE4QrpepOIv55T+P+AV9pMsPpug0juAW/E3V929p+KhtKqUrkMP+SU=
这样下一次你再尝试连接这个IP地址的远程主机时ssh会拉取它的公钥然后与 known_hosts文件里的这个ip的公钥作对比,如果对比吻合,则顺利跳过这步。如果对比不吻合,则ssh会提示你远程主机身份证明(公钥)已经改 变,这次连接可能正在受到中间人的攻击(man-in-the-middle attack)。
提示如下:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the ECDSA key sent by the remote host is 70:60:25:72:8f:96:f6:cd:25:16:80:30:30:58:de:ea. Please contact your system administrator. Add correct host key in /home/lfly/.ssh/known_hosts to get rid of this message. Offending ECDSA key in /home/lfly/.ssh/known_hosts:1 You can use following command to remove all keys for this IP: ssh-keygen -R 172.17.0.3 -f /home/lfly/.ssh/known_hosts ECDSA host key for 172.17.0.3 has changed and you have requested strict checking. Host key verification failed.
这种情况如果不是中间人攻击则很可能是因为远程主机上的操作系统更换了导致了ssh公钥改变了。
这样的话解决方法就很明了:手动删掉known_hosts里面的相应或全部内容后再尝试连接该远程主机。
- 使用别名认证(免去记远程ip的麻烦)
在~/.ssh下的config文件(没有则创建)里加入如下格式的内容:
Host cg
HostName 172.17.0.3
User lfly
这样的话我就把上面我的远程主机设置了一个别名为cg 。
下次就可以这样连接到该主机:
lfly@linux-oj9e:~> ssh cg
上面的命令等价于: lfly@linux-oj9e:~> ssh lfly@172.17.0.3
如果要设置多个远程主机的别名,则添加多个以上的三行为一组的内容进config文件即可。
public key认证(免密码认证)
过程:
- 先在本地创建一对密钥(公钥和私钥),并把公匙放在需要访问的服务器上;
- 客户端向远程服务器发出请求用你的公钥认证;
- 服务器收到请求之后,在本地找出你的公钥,然后把它和你发送过来的公钥进行比较。若两密匙一致,服务器就用公匙加密“质询”(challenge)并把它发送给客户端软件;
- 客户端软件收到“质询”之后就可以用私钥解密后再把它发送给服务器。
这种方式不需要在网络上传送口令,但你要记住密钥的口令(在创建密钥时会要求设置)。public key认证可以有效避免“中间人”攻击。
创建密钥:(公钥加密算法有rsa和dsa两种可选)
lfly@linux-oj9e:~/.ssh> ssh-keygen -t rsa (这里指定rsa公钥加密算法)
回车后ssh会询问你密钥要存放的位置,回车默认为~/.ssh/id_rsa。然后又要求输入密钥的口令,回车默认为空口令。成功创建则如下所示:
成功后可以看到.ssh文件夹下多了两个文件:id_rsa 和id_rsa.pub
lfly@linux-oj9e:~/.ssh> ls
config id_rsa id_rsa.pub known_hosts known_hosts.old
上传公钥(id_rsa.pub)到远程主机。有两种方法:
方法1、用scp复制
确定远程主机家目录里有没有.ssh这个目录,如果没有则先远程登陆并手动创建并设置权限为755
$ mkdir .ssh
$ chmod 755 .ssh
然后回到本地用scp上传文件到远程家目录下并重命名为authorized_keys文件:
lfly@linux-oj9e:~/.ssh> scp id_rsa.pub lfly@172.17.0.3:~/.ssh/authorized_keys
输入密码后则可完成。之后远程连接即可不用输入密码,如果不要求输入密码,说明还没成功:此时要检查远程主机家目录上.ssh目录权限应该要为700以及.ssh目录下的authorized_keys文件权限应该要为644。
方法2、用ssh-copy-id命令
lfly@linux-oj9e:~/.ssh> ssh-copy-id -i ~/.ssh/id_rsa.pub lfly@192.168.56.101
这里是要复制到192.168.56.101的lfly的家目录上,权限会自动设置,很方便。
方法1如果需要多台主机无密码访问该远程主机(即要多次添加不同的id_rsa.pub到authorized_keys文件)不可行,因为每次用scp上传会覆盖原有的内容。 而用方法2则会自动在authorized_keys文件结尾添加而非覆盖,所以更方便。
SSH做socks代理FQ
需要用到的工具:
- Tsocks 代码托管:https://github.com/pc/tsocks
- 一个能连接到外国ip主机的ssh帐号
Tsocks 是一个透明 SOCKS 代理软件。Ubuntu源里的这个包,opensuse用户可以在www.opensuse.org里搜索到这个包。
1. 安装后要配置/etc/tsocks.conf文件(以下为部分内容)
# We can access 192.168.0.* directly
local = 192.168.0.0/255.255.255.0 # Otherwise we use the server
server = 127.0.0.1
server_port = 7070
代理服务器为127.0.0.1即本机,端口为7070
2. 然后用ssh搭建ssh隧道:
lfly@linux-oj9e:~> ssh -fNC -D 7070 111.111.111.111
这里注意:上面填写的111.111.111.111替换成你能通过ssh登陆的外国主机的ip (关于ssh隧道详见参考资料)
3. Tsocks配置好了以及ssh隧道搭建成功后娐可FQ
Tsocks 的用法是在你要运行的工具前面加上 tsocks :
例如我要用火狐FQ:
lfly@linux-oj9e:~> tsocks firefox
欢迎访问本人网站:http://www.programfish.com
LinuxCoder 社区: http://linuxcoder.org
注意:转载请注明 “作者:广州Linux爱好者+云计算 刁金明”