# SSH

SSH(Secure Shell 的缩写)是一种网络协议,用于加密两台计算机之间的通信,并且支持各种身份验证机制。

实务中,它主要用于保证远程登录和远程通信的安全,任何网络服务都可以用这个协议来加密。

SSH 也是 Linux 系统的登录工具,现在广泛用于服务器登录和各种加密通信。

# SSH 是什么

历史上,网络主机之间的通信是不加密的,属于明文通信。这使得通信很不安全,一个典型的例子就是服务器登录。登录远程服务器的时候,需要将用户输入的密码传给服务器,如果这个过程是明文通信,就意味着传递过程中,线路经过的中间计算机都能看到密码,这是很可怕的。

SSH 就是为了解决这个问题而诞生的,它能够加密计算机之间的通信,保证不被窃听或篡改。它还能对操作者进行认证(authentication)和授权(authorization)。明文的网络协议可以套用在它里面,从而实现加密。

# SSH 历史

1995 年,芬兰赫尔辛基工业大学的研究员 Tatu Ylönen 设计了 SSH 协议的第一个版本。

SSH 1 协议存在一些安全漏洞,所以 1996 年又提出了 SSH 2 协议,但是,官方的 SSH2 软件是一个专有软件,不能免费使用。

1999 年,OpenBSD 的开发人员决定写一个 SSH 2 协议的开源实现,这就是 OpenSSH 项目。

现在,SSH-2 有多种实现,既有免费的,也有收费的。本书的内容主要是针对 OpenSSH。

# SSH 架构

SSH 的软件架构是服务器-客户端模式(Server - Client)。

向服务器发出请求的部分,称为客户端(client),OpenSSH 的实现为 ssh;

接收客户端发出的请求的部分,称为服务器(server),OpenSSH 的实现为 sshd。

# SSH 服务器

SSH 的架构是服务器/客户端模式,两端运行的软件是不一样的。OpenSSH 的客户端软件是 ssh,服务器软件是 sshd。

如果没有安装 sshd,可以用下面的命令安装。

# Debian
sudo apt install openssh-server
# 启动
sshd
# 自启
sudo systemctl enable sshd.service
# 重启
sudo systemctl restart  sshd.service

# SSH 客户端

OpenSSH 的客户端是二进制程序 ssh。它在 Linux/Unix 系统的位置是/usr/local/bin/ssh

Linux 系统一般都自带 ssh,如果没有就需要安装。

# Ubuntu 和 Debian
sudo apt install openssh-client

# SSH 配置

ssh 公钥生成和上传到服务器

# 生成密钥
ssh-keygen -C "[email protected]"

# 生成公司 SSH-key
ssh-keygen -t rsa -C "[email protected]" -f ~/.ssh/id-rsa
# 生成Github SSH-key
ssh-keygen -t rsa -C "[email protected]" -f ~/.ssh/github-rsa

# 上传密钥
ssh-copy-id -i id-rsa user@hostname
ssh-copy-id -i github-rsa user@hostname

# 测试
ssh -T [email protected]
ssh -T git@yougitserver

# 基本用法

ssh 登录服务器的命令如下。

# 不指定用户名的情况下,将使用客户端的当前用户名
ssh hostname
ssh user@hostname
ssh -l username host

ssh 默认连接服务器的 22 端口,-p 参数可以指定其他端口。

ssh -p 8821 foo.com
ssh foo.com:8821

# 主机设置

用户个人的配置文件~/.ssh/config,可以按照不同服务器,列出各自的连接参数,从而不必每一次登录都输入重复的参数。下面是一个例子。

Host remoteserver
    HostName remote.example.com
    User neo
    Port 2112
ssh remoteserver
# 等同于
ssh -p 2112 [email protected]

# SSH 密钥登录

SSH 默认采用密码登录,这种方法有很多缺点,简单的密码不安全,复杂的密码不容易记忆,每次手动输入也很麻烦。密钥登录是比密码登录更好的解决方案。

# 生成密钥

密钥登录时,首先需要生成公钥和私钥。OpenSSH 提供了一个工具程序 ssh-keygen 命令,用来生成密钥。

ssh-keygen
# 指定密钥的加密算法
ssh-keygen -t rsa
# 指定密钥的二进制位数
ssh-keygen -t rsa -b 1024
# 添加注释
ssh-keygen -C username#@host

# 手动上传公钥

生成密钥以后,公钥必须上传到服务器,才能使用公钥登录。

OpenSSH 规定,用户公钥保存在服务器的~/.ssh/authorized_keys 文件。

注意,authorized_keys 文件的权限要设为 644,即只有文件所有者才能写。

chmod 644 ~/.ssh/authorized_keys

# 自动上传公钥

OpenSSH 自带一个 ssh-copy-id 命令,可以自动将公钥拷贝到远程服务器

ssh-copy-id -i key_file user@host
# 
ssh-copy-id -i id_rsa user@host

# 关闭密码登录

为了安全性,启用密钥登录之后,最好关闭服务器的密码登录。

对于 OpenSSH,具体方法就是打开服务器 sshd 的配置文件 /etc/ssh/sshd_config,将 PasswordAuthentication 这一项设为 no

PasswordAuthentication no

修改配置文件以后,不要忘了重新启动 sshd,否则不会生效。

service sshd restart

# SCP 命令

scp 是 secure copy 的缩写,相当于 cp 命令 + SSH。它的底层是 SSH 协议,默认端口是 22,相当于先使用 ssh 命令登录远程主机,然后再执行拷贝操作。

使用 scp 传输数据时,文件和密码都是加密的,不会泄漏敏感信息。

# 本地文件复制到远程

复制本机文件到远程系统的用法如下。

# 语法
$ scp SourceFile user@host:directory/TargetFile
# 示例
$ scp file.txt [email protected]:/remote/directory
# 将本机整个目录拷贝到远程目录下
$ scp -r localmachine/path_to_the_directory username@server_ip:/path_to_remote_directory/

# 远程文件复制到本地

# 语法
$ scp user@host:directory/SourceFile TargetFile
# 示例
$ scp [email protected]:/remote/file.txt /local/directory

# 两个远程系统之间的复制

本机发出指令,从远程主机 A 拷贝到远程主机 B 的用法如下。

# 示例
$ scp [email protected]:/files/file.txt [email protected]:/files

# 学习资料

SSH 教程 (opens new window)