SSH入门
概述
SSH是Linux系统的登录工具,现在广泛用于服务器登录和各种加密通信。
SSH的软件架构是服务器-客户端模式(Server - Client)。在这个架构中,SSH软件分成两个部分:向服务器发出请求的部分,称为客户端(client),OpenSSH的实现为ssh;接收客户端发出的请求的部分,称为服务器(server),OpenSSH的实现为sshd。
ssh客户端
ssh登录
~/.ssh文件夹下的id_rsa, id_dsa, id_ecdsa, id_ecdsa_sk, id_ed25519, id_ed25519_sk, id_xmss等密钥。
|
|
此外还可以使用ssh-add命令来把密钥添加到高速缓存中,从而不需要指定对应的密钥,提升登录速度。
使用ssh-add之前是需要开启ssh-agent的,很多操作系统默认是不开启的,可以通过下面的方式开启:
|
|
主要包含以下几个命令:
- 添加密钥到缓存
1 2# 添加~/.ssh/id_dsa ssh-add ~/.ssh/id_dsa - 列出所有添加的密钥
1ssh-add -l
配置了上述ssh-add之后,应该能够顺利的通过下面的命令克隆代码
|
|
相比与这种方式,在~/.ssh/config文件中配置可能会更为简单有效,配置示例如下:
|
|
ssh端口转发
SSH 除了登录服务器,还可以作为加密通信的中介,充当两台服务器之间的通信加密跳板,使得原本不加密的通信变成加密通信。这个功能称为端口转发(port forwarding),又称 SSH 隧道(tunnel)。
端口转发有两个主要作用:
- 将不加密的数据放在 SSH 安全连接里面传输,使得原本不安全的网络服务增加了安全性,比如通过端口转发访问 Telnet、FTP 等明文服务,数据传输就都会加密。
- 作为数据通信的加密跳板,绕过网络防火墙。
术语
- Client Host:也就是我们运行
ssh命令定义隧道(tunnel)的一端 - Tunnel Host:其实就是建立隧道连接的一端
- Ingress:我们称初始化的那一端,或者进入的那一端,或者监听的那一端为ingress
- Egress:退出、终止的一端为egress
动态转发
动态转发指的是,本机与 SSH 服务器之间创建了一个加密连接,然后本机内部针对某个端口的通信,都通过这个加密连接转发。它的一个使用场景就是,访问所有外部网站,都通过 SSH 转发。动态转发需要把本地端口绑定到 SSH 服务器。至于 SSH 服务器要去访问哪一个网站,完全是动态的,取决于原始通信,所以叫做动态转发。
|
|
上面命令中,-D表示动态转发,local-port是本地端口,tunnel-host是 SSH 服务器,-N表示这个 SSH 连接只进行端口转发,不登录远程 Shell,不能执行远程命令,只能充当隧道。
如果经常使用动态转发,可以将设置写入 SSH 客户端的用户个人配置文件(~/.ssh/config)。
|
|
将本机的9999端口都转发到guopai16(10.176.22.16)
|
|
注意,这种转发采用了 SOCKS5协议。访问外部网站时,需要把 HTTP 请求转成 SOCKS5协议,才能把本地端口的请求转发出去。
下面是 SSH 隧道建立后的一个使用实例:
|
|
本地转发
本地转发(local forwarding)指的是,SSH 服务器作为中介的跳板机,建立本地计算机与特定目标网站之间的加密连接。本地转发是在本地计算机的 SSH 客户端建立的转发规则。
它会指定一个本地端口(local-port),所有发向那个端口的请求,都会转发到 SSH 跳板机(tunnel-host),然后 SSH 跳板机作为中介,将收到的请求发到目标服务器(target-host)的目标端口(target-port)。
|
|
上面命令中,-L参数表示本地转发,local-port是本地端口,target-host是你想要访问的目标服务器,target-port是目标服务器的端口,tunnel-host是 SSH 跳板机。
还可以添加-g 参数,表示将本地当作网关,其他可以访问本机的机器可以通过local-port访问到target-port。
注意,本地端口转发采用 HTTP协议,不用转成 SOCKS5协议。
如果经常使用本地转发,可以将设置写入 SSH 客户端的用户个人配置文件(~/.ssh/config)。
|
|
现在有一台 SSH 跳板机guopai16,我们想要通过这台机器,在本地9999端口与目标网站www.baidu.com的80端口之间建立 SSH 隧道,就可以写成下面这样。
|
|
接着我们在本地访问localhost:9999/,在guopai16上抓取80端口的流量如下:

|
|
则别的机器可以通过当前本机的ip:8000访问10.176.22.11:8000。
远程转发
远程转发指的是在远程 SSH 服务器建立的转发规则。 它跟本地转发正好反过来。建立本地计算机到远程计算机的 SSH 隧道以后,本地转发是通过本地计算机访问远程计算机,而远程转发则是通过远程计算机访问本地计算机。它的命令格式如下。
|
|
上面命令中,-R参数表示远程端口转发,remote-port是远程计算机的端口,target-host和target-port是目标服务器及其端口,remotehost是远程计算机。
如果经常执行远程端口转发,可以将设置写入 SSH 客户端的用户个人配置文件(~/.ssh/config)。
|
|
内网某台服务器localhost在 80端口开了一个服务,可以通过远程转发将这个 80 端口,映射到具有公网 IP 地址的my.public.server服务器的 8080端口,使得访问my.public.server:8080这个地址,就可以访问到那台内网服务器的 80端口。
|
|
ssh-keygen生成密钥
密钥登录时,首先需要生成公钥和私钥。OpenSSH 提供了一个工具程序ssh-keygen命令,用来生成密钥。
ssh-keygen常用选项如下所示:
-b指定密钥的二进制位数
这个参数值越大,密钥就越不容易破解,但是加密解密的计算开销也会加大。一般来说,-b至少应该是1024,更安全一些可以设为2048或者更高。
-C 指定密钥的注释
格式为username@host。下面命令生成一个4096位 RSA 加密算法的密钥对,并且给出了用户名和主机名。
|
|
-f 指定生成的私钥文件
|
|
-F 检查某个主机名是否在known_hosts文件里面
|
|
-N指定私钥的密码(passphrase)
|
|
-p重新指定私钥的密码(passphrase)
-p参数用于重新指定私钥的密码(passphrase)。它与-N的不同之处在于,新密码不在命令中指定,而是执行后再输入。ssh 先要求输入旧密码,然后要求输入两遍新密码。
-R将指定的主机公钥指纹移出known_hosts文件
|
|
-t指定生成密钥的加密算法,一般为dsa或rsa
|
|
SSH服务器配置
安装基本的依赖
|
|
修改sshd配置信息
|
|
我们可以修改一下信息:
|
|
给对应用户下增加公钥
生成密钥以后,公钥必须上传到服务器,才能使用公钥登录。
手动设置公钥
OpenSSH 规定,用户公钥保存在服务器的~/.ssh/authorized_keys文件。你要以哪个用户的身份登录到服务器,密钥就必须保存在该用户主目录的~/.ssh/authorized_keys文件。只要把公钥添加到这个文件之中,就相当于公钥上传到服务器了。每个公钥占据一行。如果该文件不存在,可以手动创建。
用户可以手动编辑该文件,把公钥粘贴进去,也可以在本机计算机上,执行下面的命令。
|
|
上面示例中,user@host要替换成你所要登录的用户名和主机名。
注意,authorized_keys文件的权限要设为644,即只有文件所有者才能写。如果权限设置不对,SSH 服务器可能会拒绝读取该文件。
自动上传公钥
OpenSSH 自带一个ssh-copy-id命令,可以自动将公钥拷贝到远程服务器的~/.ssh/authorized_keys文件。如果~/.ssh/authorized_keys文件不存在,ssh-copy-id命令会自动创建该文件。
|
|
上面命令中,-i参数用来指定公钥文件,user是所要登录的账户名,host是服务器地址。如果省略用户名,默认为当前的本机用户名。执行完该命令,公钥就会拷贝到服务器。
默认情况下会与同名的私钥进行校验,如果想不校验的话,那么直接加上-f
重新启动ssh服务
|
|
常见问题
验证私钥后,仍要求输入密码
在私钥验证通过后,仍然要求输入对应密码的情况下,需要检查以下事项:
- 检查
~/.ssh/authorized_keys的权限是否为600,且组权限是否正常 - 检查
~/.ssh文件夹的权限是否为700,且组权限是否正常 - 检查
~/.ssh/authorized_keys是否和私钥匹配,且组权限是否正常
连接服务器时间过长
有可能是因为DNS反查时间太长了,在/etc/ssh/sshd_config中将useDNS修改为no,然后执行如下语句重启ssh服务器。
|
|
如何debug ssh
开启debug模式下的sshd:
|
|
然后在指定连接这个端口下的ssh,无论连接是否成功,一次连接后,在服务器上都会显示对应的日志。