名校课程推荐 | MIT《CS 实用工具课程》-远端设备

远端设备

对于程序员来说,在日常工作中使用远程服务器已经变得越来越普遍。如果你需要使用远程服务器来部署后端软件,或者需要用到更高算力的服务器,那么你可以使用Secure Shell(SSH)。与所介绍的大多数工具一样,SSH是高度可配置的,值得我们花时间学习。

执行命令

ssh经常被忽略的一个特征是它可以直接运行命令。

  • 通过ssh foobar@server ls在foobar主文件夹中执行ls命令

  • 可以与管道结合使用,ssh foobar@server ls | grep PATTERN在本地查询远端ls的输出,而ls | ssh foobar@server grep PATTERN在远端对本地ls的输出进行查询。

SSH密钥

基于密钥的验证机制使用了密码学中的公钥,向服务器证明客户端持有对应的私钥,而不需要公开其私钥。这样你就不需要每次重新输入密码。而私钥(例如~/.ssh/id_rsa)实际上就是你的密码,所以要这样处理。

  • 密钥生成。只需运行ssh-keygen -t rsa -b 4096即可生成密钥对。如果不选择对密钥对进行加密,任何拥有你私钥的人都将能够访问授权的服务器,因此建议选择输入某个密钥对的密码并使用ssh-agent来管理shell会话。

如果你已经配置了使用SSH密钥推送到Github,你可能已经完成了这里列出的步骤,并且已经有了一对有效的SSH密钥。运行ssh-keygen -y -f /path/ to /key可以检查是否持有密钥对的密码并验证它。

  • 基于密钥的身份验证。ssh会查询.ssh/authorized_keys确认哪些用户被允许进入。可以通过以下命令复制公钥:
cat .ssh/id_dsa.pub | ssh foobar@remote 'cat >> ~/.ssh/authorized_keys'

如果支持ssh-copy-id,可以使用下面这种更简单的解决方案

ssh-copy-id -i .ssh/id_dsa.pub foobar@remote

通过ssh复制文件

使用ssh复制文件有多种方法:

  • ssh+tee, 最简单的方法是,先执行ssh命令,然后通过这样的方法利用标准输入实现cat localfile | ssh remote_server tee serverfile

  • scp:如果需要拷贝大量的文件或目录,使用scp 命令会更加方便,因为它可以轻松遍历相关路径。语法如下:scp path/to/local_file remote_host:path/to/remote_file

  • rsync 对 scp 进行了改进,可以检测本地和远端的相同文件以防止重复拷贝。它还提供了一些诸如符号连接、权限管理等精细的操控功能,甚至还可以基于 --partial标记实现断点续传。rsync 的语法和scp类似。

后台进程

默认情况下,当中断一个ssh连接,父shell的子进程会一同终止。有几种选择

  • nohup - nohup工具允许终端退出进程仍继续运行。虽然有时可以通过 &disown 实现这一点,nohup是更好的默认命令。可以通过这里了解更多。

  • tmuxscreen - 虽然 nohup 能让进程在后台继续运行,但是对于交互式shell会话来说它并不方便。这种情况下,使用screentmux这类终端多路复用器是一种方便的选择,因为可以轻松分离和重新连接相关会话。

最后,如果你disown了一个程序,想要将它重新连接到当前终端,你可以查看reptyrreptyr PID 会通过进程ID号(PID)找到正在运行的程序并将它转换到当前终端。

端口转发

在很多场景中,你会遇到这样的软件,它通过监听设备上的端口继而工作。如果在本地设备上,可以简单地执行 localhost:PORT127.0.0.1:PORT,但是如果是通过网络没有直接可用端口的远程服务器,怎么办?这就需要用到端口转发。端口转发又两种:本地端口转发和远程端口转发(更多细节可参看下图,图片来源:this SO post)。

本地端口转发

远程端口转发

常见的情景是本地端口转发,即远端设备上的服务监听一个端口,而你希望在本地设备上的一个端口建立连接并转发到远程端口上。比如,我们在远端服务器上运行 jupyter notebook 并监听 8888 端口,然后建立从本地端口 9999 的转发 ,使用 ssh -L 9999:localhost:8888 foobar@remote_server,这样只需要访问本地的 localhost:9999 即可。

图形化转发

如果我们要在服务器中运行基于图形界面(GUI)的程序,转发端口是不够的。你可以通过远程桌面控制软件发送完整的桌面环境(比如像RealVNC、Teamviewer这样的选项)。不过,对于单个图形化GUI工具来说,SSH提供了一个很好的替代方案:图形化转发。

使用 -X 标志告诉SSH进行转发

对于受信的X11转发,可以使用 -Y 标志

最后要注意的是,它们工作的前提是服务器上的 sshd_config 必须有以下选项

X11Forwarding yes
X11DisplayOffset 10

漫游

连接远程服务器的一个常见痛点是遇到由关机、休眠或网络环境变化导致的掉线。如果连接的延迟很高,用ssh也会很闹心。Mosh(即 mobile shell )对 ssh 进行了改进,它支持连接漫游、间歇连接及智能本地回显。

Mosh在所有常见的发行版和包管理器中都可用,它需要一个ssh服务器才能在服务器上工作。你不需要成为超级用户来安装mosh,但是它需确保打开服务器中的60000到60010端口(它们通常是开启的,因为它们不在权限范围内)。

Mosh的一个不足是它不支持漫游端口/图形化转发,如果你经常要用到这些功能,mosh可能帮助不大。

SSH配置

客户端

我们已经讨论了很多可以传播的参数。一种很有吸引力的替代方法是创建shell别名,比如alias my_serer="ssh -X -i ~/.id_rsa -L 9999:localhost:8888 foobar@remote_server,不过这里还有一个更好的替代方案,就是使用 ~/.ssh/config

Host vm
    User foobar
    HostName 172.16.174.141
    Port 22
    IdentityFile ~/.ssh/id_rsa
    RemoteForward 9999 localhost:8888

# Configs can also take wildcards
Host *.mit.edu
    User foobaz

使用 ~/.ssh/config 文件来创建别名还有一个额外优势,类似 scprsyncmosh这些程序也都可以读取这个配置并将设置转换为对应的标志。

注意,~/.ssh/config文件可以看成是一个配置文件,一般来说,它可以包含在其他的配置文件中,但是如果你公开了它,想一想这会向互联网上的陌生人提供多少信息——你的服务器地址、你正在使用的用户、开放的端口等等。这可能会让你暴露于某些类型的攻击下,所以要谨慎共享你的SSH配置。

警告:永远不要把你的RSA密钥(~/.ssh/id_rsa*)放置在公开存储库中!

服务器侧

服务器侧的配置通常在 /etc/ssh/sshd_config指定。你可以在这里配置免密认证、修改 shh 端口、开启 X11 转发等等。也可以为每个用户单独指定配置。

远程文件系统

有时将一个远程文件夹挂载到本地会比较方便,sshfs可以将远程服务器上的文件夹挂载到本地,然后你就可以使用本地编辑器了。

练习

  1. SSH在宿主机工作需要运行SSH服务器。在虚拟机上安装一个SSH服务器(比如OpenSSH),然后继续之后的作业。通过运行ip addr查询设备ip,查找inet字段(忽略与回路接口对应的127.0.0.1)。

  2. ~/.ssh/目录下,查看是否有SSH密钥对。如果没有,用 ssh-keygen -t rsa -b 4096 命令生成。建议你对密钥添加密码,通过 ssh-agent 可以实现 ,详情查看这里

  3. 使用 ssh-copy-id 将密钥复制到你的虚拟机。测试你是否可以在无密码的条件下进行ssh。然后,编辑你服务器中的 sshd_config,通过编辑 PasswordAuthentication 值实现免密认证。通过编辑PermitRootLogin 值禁用root登录。

  4. 编辑服务器中的 sshd_config 来改变ssh端口并查看是否仍能ssh。如果你有一个面向公众的服务器,那么非默认端口和仅使用密钥的登录会限制大量的恶意攻击。

  5. 在你的服务器或虚拟机上安装mosh,创建连接,然后断开服务器或虚拟机的网络适配器,mosh能正常恢复吗?

  6. 本地端口转发的另一个用处是将某些宿主机连接到服务器。如果你的网络过滤了一些网站,例如 reddit.com,你可以通过如下操作连接服务器:

    • 运行 ssh remote_server -L 80:reddit.com:80
    • 设置 reddit.com,设置 /etc/hosts中的www.reddit.com127.0.0.1
    • 检查你正通过服务器进入网站
    • 如果不明显,可以使用ipinfo.io之类的网站,它会根据你的主机公共ip改变。
  7. 后台端口转发可以通过几个额外标志轻松实现。查询 -N-f 标志在ssh中的作用,并找出像 ssh -N -f -L 9999:localhost:8888 foobar@remote_server 此类命令的作用。

推荐阅读

客服