特点

ssh (Secure Shell) 为用户连接远端服务器的 shell 提供了安全的环境。

ssh 具有 2 个特点:

  • 基于非对称加密的安全认证,所以相比传统的网络服务程序,如 FTP、POP、Telnet 要更加安全。
  • 传输的数据是经过加密的,中间人攻击无效。
  • 传输的数据可以是经过压缩的,所以可以加快传输的速度。

在 Linux 上,客户端直接使用 ssh 即可,服务端需要安装 openssh ,Windows 用户端需要安装 Putty 。

免密登录

ssh 如果不进行配置的话,在每次连接的时候需要输入密码,这是非常麻烦的,我们可以采用非对称密钥的方式来进行免密登录。其核心思路是在 server 上存储公钥来对用户身份进行验证。需要强调的是,并不是必须要进行这样的设置。

ssh 提供基于非对称密钥的安全认证。客户端将将公钥上传到服务器。登录的时候,客户端向服务器发送登录请求;服务器收到请求后,向用户发送一段随机字符串;用户用自己的私钥加密后,再发送回服务器;服务器使用事先存储的公钥进行解密,如果解密成功,证明用户可信,允许登录。

客户端使用如下命令生成密钥

ssh-keygen

当然我们一般使用的时候会带一些参数:

参数含义
-t加密方法,如 rsa, ed25519
-C注释,会作为公钥的一部分,一般是邮箱
-f文件名,指定密钥存放的路径

在密钥生成过程中,会出现如下字样

Enter passphrase (empty for no passphrase):
# Enter same passphrase again:

这里提到的 passphrase 是为了保护私钥的,如果有人窃取了你的私钥文件(黑掉了个人电脑),那么它就完全掌握通信过程了。passphrase 就是为了缓解这一情况,当存在 passphrase 的时候,使用私钥前必须输入正确的 passphrase 。不过我们一般都为了方便,不设置 passphrase 。

在公钥生成好后,需要将公钥附加到服务器用户目录下的 $HOME/.ssh/authorized_keys` 文件中,这个动作可以用如下命令完成

ssh-copy-id username@remote_host

当然在 Github 或者 Gitlab 中是在图形界面中添加的,原理是类似的,如果我们希望访问 Github 的服务器,我们就要把自己的公钥上传给 Github 服务器。

当我们基于 ssh 使用 git clone 时,我们的用户名是 git ,这是一个神奇的现象,我在 stackoverflow 上找到了这篇帖子 。我没有太看懂,但是我猜测是真正完成功能的用户就是 git ,它是某种中间人?

命令

ssh 命令格式如下

ssh username@remote_host

参数如下:

参数格式含义
p-p 2222使用服务器的特定端口
i-i path/to/key_file使用特定私钥
t-t command command_arguments执行命令
T-T禁用了伪终端的分配
-J-J username@jump_host username@remote_host通过跳板机连接

scp 命令用于在服务器和客户端间传递文件,它的参数既有 ssh 的一面,也有 cp 的一面

scp remote_host:path/to/remote_file path/to/local_directory
scp -r remote_host:path/to/remote_directory path/to/local_directory

sftp 会启动一个交互式的、安全的 Ftp 服务器,如下所示:

sftp remote_user@remote_host
# Transfer remote file to the local system
get /path/remote_file
# Transfer local file to the remote system
put /path/local_file

SSH Config

我们可以看到 ssh 命令可以有非常复杂的参数,比如说我们指定特定的密钥,再使用一个跳板机,那么就会是命令很繁琐,我们可以将这些参数记录在 ~/.ssh/config 中,比如这样的

Host sshtest
    HostName ssh.test.com
    User user
    Port 2200
    IdentityFile ~/.ssh/id_rsa_test
    ProxyCommand ssh -q proxyuser@proxyhost -p proxyport nc %h %p

它等价于:

ssh -o "ProxyCommand ssh -q proxyuser@proxyhost -p proxyport nc %h %p" -p 2200 -i ~/.ssh/id_rsa_test user@ssh.test.com

SSH Tunnel

关于隧道的概念,可以参考 Tunnel 。SSH Tunnel 本质是一种端口转发(Port Forwarding)技术。

SSH Tunnel 有 3 种:

Local Port Forwarding

当 Client 需要访问位于 Server 上的资源或服务,但由于防火墙设置、网络配置或专用网络限制而无法直接访问时,就会使用本地端口转发。示意图如下:

命令如下:

ssh -L [local_port]:[destination_address]:[destination_port] [username]@[ssh_server]

其效果就是,原本在 server 上私有的 destination_port ,现在 client 可以通过直接访问本机的 local_port 来获得服务。

Remote Port Forwarding

Remote Port Forwarding 也被叫做反向隧道(Reverse Tunnel),让 Server 可以访问 Client 上的私密资源,相当于绕过 client 的防火墙,命令如下:

ssh -R [remote_port]:[destination_address]:[local_port] [username]@[ssh_server]

此时 server 可以通过访问 remote_port 来访问 client 的 local_host

Dynamic Port Forwarding

动态端口转发(Dynamic Port Forwarding)是一种将 Client 当作 Server 的 Proxy ,直观的效果就是 server 可以用 client 的梯子了。命令如下:

ssh -D [local_port] [username]@[ssh_server]

Server 限制密码登录

/etc/ssh/sshd_config 中增加如下配置即可:

PasswordAuthentication no
AuthenticationMethods publickey