SSH Notes

plus2047 于 2021-10-19 发布

UPDATED ON 2018.01.01

基础使用

# basic usage
ssh username@XXX.XXX.XXX.XXX -p port
ssh username@example.com -p port
# If ignore port: using 22. If ignore username: using local username.

配置文件

编辑 .ssh/config 可以在登录时使用主机缩写,而非 IP 地址。一个主机名设置例子如下,可以在 config 文件中设置多个主机。

host ws
	hostname XXX.XXX.XXX.XXX
	port 22
	user plus

而后就可以使用缩写登陆:

ssh ws

通过 SSH 使用的文件传输工具

SSH 的强大之处远远不止是远程登录。有很多工具在 SSH 之上工作,如简单文件拷贝 scp 和文件夹同步 rsync。 这里只记录了最基本的用法。这两个工具都会读取 ssh 的配置文件,可以使用配置文件中配置好的主机名。

# copy file
scp from_file ws:to_file
scp -r ws:from_dir to_dir
# sync folder, -v: print the rate of prograss
# -r: --recursive
rsync -av from_dir to_dir

注意,有个坑是 zsh 中使用 scp 时,如果要使用通配符,需要把通配符转义,否则 zsh 似乎尝试在本地处理通配符导致通配符没有效果:

# bash:
scp -r ws:~/hello* ./
# zsh:
scp -r ws~/hello\* ./

SSH Key 密钥登录设置

使用密码验证每次都需要重复输入,而且有安全问题。因此建议配置密钥对验证。

任意 *UIX 环境通常支持 ssh-keygen 命令生成密钥对。默认配置下(一路按回车),会在 ~/.ssh 目录下生成两个文件:id_rsa, id_rsa.pub. 其中 .pub 文件是公钥,另一个是私钥。将公钥复制到要登陆的服务器的 .ssh/authorized_keys 文件中(写到这个文件里,这不是一个文件夹。如果文件不存在则直接把公钥复制过去重命名成这个文件),私钥留在本地(运行 ssh 客户端的电脑上),保持在 .ssh/id_rsa 这个位置就可以。之后就可以不用密码远程登录了。

注意检查文件权限:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

密钥验证的安全性非常高。私钥不泄漏、算法是最新算法时可以认为是不可能攻破的。可以查一下非对称密钥体系的工作原理,会对一系列加密技术如 https 等有更好的理解。

SSH 代理设置

可以通过 SSH 进行各种的端口转发、代理设置等,因此所有利用网络的程序,如 Jupyter Notebook 等可以配合 SSH 使用。

本地分享服务器网络环境

用于服务器有更广的网络访问权限,或者从本地访问服务器上的资源(如 Jupyter Notebook)的情况。有两种方式:

- SSH tunneling: Dynamic port forwarding (SOCKS proxy on localhost:9999):
    ssh -D 9999 -C username@remote_host

- SSH tunneling: Forward a specific port (localhost:9999 to slashdot.org:80):
    ssh -L 9999:slashdot.org:80 username@remote_host

第一条会在本地 9999 端口开一个 socks 代理,本地浏览器将代理指向这个端口 (localhost:9999) 时,本地的网络环境就会相当于远程主机的网络环境。

第二条会将本地的 9999 端口映射到指定的网址,访问这个网址时使用的是服务器端的网络环境。

注意,这些代理(前向代理)需要在 /etc/ssh/sshd_config 中允许 TCP 前向代理:AllowTcpForwarding yes. (Ubuntu 默认开启)

服务器分享本地网络环境

只映射一个端口较为容易:

ssh -R 8888:localhost:1080 username@remote_host

此时访问服务器 8888 端口相当于访问本地 8888 端口。

有时候服务器不允许访问网络,但是可以被 ssh 连接,此时可以通过 ssh 分享本地整个网络环境给服务器。如果要将本地的网络环境完整映射到远程则比较麻烦,需要打开一个本地 HTTP 代理,然后把这个代理端口映射到远端。你本地很可能有一个 HTTP 或 HTTPS 代理 —— 科学上网工具一般会在本地开一个 HTTP 代理。如果需要架设本地 HTTP 代理服务器,可以使用 proxy2. 如果本地代理端口为 8888,则之前的命令即可讲该端口映射到服务器的 1080 端口。在服务器上运行:

export HTTP_PROXY=localhost:1080
export HTTPS_PROXY=localhost:1080

即可为 wget, git 等程序设置代理。可以把这两行命令写入 .ssh/authorized_keys.bashrc 中。

另一种方式不需要本地开启 HTTP 代理,但需要本地主机打开 SSHD 服务。避免麻烦,把本地和远程主机分别称为 A 和 B,从 A 运行:

ssh -R 2222:localhost:22 username_B@host_B

这将 A 的 SSH 登录端口 22 映射到了 B 的 2222 端口。在 B 运行:

ssh -D 9876 username_A@localhost -p 2222

这样能在 B 得到一个位于 9876 端口的 socks 代理,但问题是 socks 代理不如 HTTP 代理好用,因此不推荐这种方式。

MOSH

mosh 是一款“稳定”的 ssh 替代品。在网络中断时 ssh 连接会中断,但 mosh 能够保持连接,同时在网络连接不稳定时表现较好。但 mosh 没有 ssh 的丰富功能,如各种端口重定向等。在只进行交互式使用时是个不错的替代品。

使用时需要在服务器、本地进行安装:apt install mosh. 而后基本用法与 ssh 相同,可以自动使用 ssh 的配置文件。

Exit SSH

SSH 不像 Screen 那样对特定的快捷键有反应,而是对特定的按键序列有反应。有时候因为失去网络连接等,SSH 远程主机不再有反应,此时退出 SSH 的方法是,依次按下以下三个键:

Enter, ~, .