关于远程访问的技巧

Posted by Hsz on May 23, 2018

远程访问

所谓远程访问是指在一台机器(本地机器Local)上操作互联上另一台机器(远端Remote)上的资源的行为.

工作时候我们往往需要远程访问我们的服务器/工作站.利用其上的资源,要么是做比较重的计算任务,要么是为服务debug等等.

通常远程访问的操作依赖于开源工具ssh.本文就是结合场景介绍如何使用这些工具更加高效的进行远程访问.

注意:本文针对非windows系统.

前置知识

  • Local端ssh的设置方法

    通常ssh本地端设置是设置ssh客户端,一般修改~/.ssh/config文件.这样配置是用户进程级的修改,每次重新打开terminal就会重载配置.

  • Remote端ssh的设置方法

    通常ssh远端的设置是设置ssh服务器,一般修改/etc/ssh/sshd_config文件.这样配置是全局级别的修改.通常要重启ssh的服务端sudo reload ssh.

  • ssh的基本用法

    ssh <username>@<host>:<port>默认的端口是22

无密码连接

场景: 多数时候我们使用密码来登录远端,但每次都要输入密码很麻烦.

这个场景很常见,而无密码登录也是如hadoop,spark这些分布式计算框架的基本需求.使用方法是使用非对称加密(通常使用rsa加密),并将公钥信息交给要访问的计算机即可,

具体步骤为:

  1. 使用ssh-keygen -t rsa -P "" 用于生成本机的公钥私钥对
  2. cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys命令将公钥信息保存到ssh客户端可以识别的位置.
  3. ssh localhost 自己连下自己,第一次会要你设置下,以后就可以无密码自己登陆自己了
  4. ssh-copy-id -i ~/.ssh/id_rsa.pub <username>@<remote_host>

指定秘钥登录远端

场景: 工作中远端往往使用非对称加密的方式连接,只有使用指定公钥才可以访问.通常这个公钥会以文件的形式交付到我们手中.

在登录时可以使用-i <公钥/的/path>来指定使用哪个公钥

ssh防止断连

场景: 我们使用ssh连接远端,但通常上个厕所回来就发现连接断开了.

可以使用

ServerAliveInterval 30

设置本地的ssh客户端,让它每隔30s发送一个信号给服务端以保持连接.

复用连接

场景: 我们需要在多个terminal窗口中打开到同一个服务器的连接,但不想每次都输入用户名,密码,或是等待连接建立.

本地设置中新增:

ControlMaster auto
ControlPath /tmp/ssh_mux_%h_%p_%r

连接共享不止可以帮助你共享多个SSH连接,如果你需要通过SFTP与服务器传输文件,你会发现它们使用的依然是同一条连接; 如果你使用的Bash,你会发现,你甚至ssh甚至支持Tab对服务器端文件进行自动补全,共享连接选项对于那些需要借助ssh的工具,比如rsync,git等等也有效.

长连接

场景: 我们需要在多个terminal窗口中打开到同一个服务器的连接,但不想每次都输入用户名,密码,或是等待连接建立.

本地设置中新增:

ControlPersist 4h

这样每次通过ssh与服务器建立连接之后,这条连接将被保持4个小时,即使在你退出服务器之后,这条连接依然可以重用,因此,在你下一次(4小时之内)登录服务器时,你会发现连接以闪电般的速度建立完成.

如果你发现自己每条需要连接同一个服务器无数次,那么长连接选项就是为你准备.

本地端口转发

场景: 我们买了阿里/腾讯的数据库服务(远端机器A),而且没有开通外网访问权限.但我们希望可以本地直接访问它(比如用gui客户端查询什么的),这时候我们有一台可以连接到机器A的远端机B

这种场景也挺常见的,我们可以使用本地端口转发(LocalForward)来实现.

ssh -L <local_port>:<A_hostname>:<A_port> <B_username>@<B_Host>

如果要监控的服务部署在B上,压根没有什么A,那更加简单了

ssh -L <local_port>:localhost:<B_port> <B_username>@<B_Host>

这中情况用的更多,远端机在本地起了一个服务(或者docker起了一个服务,比如就是监控容器的服务),这个服务并不打算让别人看到,必须要可以登录远端的人才可以使用,这时候就可以这样设置.

远端端口转发

场景: 我们使用的本地端处在一个内网环境内,它可以连接处于内网的远端机A(A上提供一个服务)而有一台处于外网的远端机B希望使用远端机A上的服务,但它既不能连接远端A也连不上本地机.

这种情况也可能发生,就是不太常见,可以使用如下的命令设置远端端口(RemoteForward)转发来完成需求

ssh -R <local_port>:<A_hostname>:<A_port> <B_username>@<B_Host>

注意,这边是使用本地机器作为中转站的,与以上的用法逻辑都不相同.

连接配置化

场景: 某些主机使我们非常常用的,我不想每次都要打一段很长的命令.

这个需求挺正常的,如果登录可以配置化就会很方便,在windows下,xshell默认就是配置登录信息然后登录,每次双击下就能连接也确实方便.

ssh可以在设置中将一些连接信息配置化以实现这个目的,其基本语法是使用关键字Host指定一个连接,再在其下编辑参数. 可以编辑的参数就是ssh -h中指示的参数(需要将命名法转变为帕斯卡命名法),其形式如下:

Host <link_name>
<param_name> <parm_value>
.
.
.

举个例子:

Host a
HostName <host>
User <username>
IdentityFile <path>

连接配置同样可以配置本地端口转发和远端端口转发,使用的参数名分别为LocalForwardRemoteForward.

文件交互

场景: 很多时候我们需要向远端发送文件或者从远端将一些log文件取下来本地分析.

通常文件交互可以使用两种工具,一种是scp,一种是lrzsz

通常windows下用lrzsz而mac/linux下使用scp.

使用lrzsz

lrzsz需要先登录上远端,然后在远端执行.mac下使用要安装iterm,使用iterm代替自带的terminal才可以使用.

  • 安装:

sudo apt-get install lrzsz

  • 本机向远端传输(rz)

rz 之后跳出选框选择文件即可

  • 远端向本机传输(sz)

sz <文件路径>之后跳出选框选择要下载到的目录

使用scp

scp都是在本地操作,因此需要指明远端的信息,其实scp本质上也是基于ssh的,因此同样使用-i指定公钥.

需要注意的是scp有如下使用限制:

  1. 如果远程服务器防火墙有为scp命令设置了指定的端口,我们需要使用-P参数来设置命令的端口号
  2. 使用scp命令要确保使用的用户具有可读取远程服务器相应文件的权限,否则scp命令是无法起作用的。

用法:

  • 指明本地文件复制到远端

      scp local_file remote_username@remote_ip:remote_folder 
    
      scp local_file remote_username@remote_ip:remote_file 
    
      scp local_file remote_ip:remote_folder 
    
      scp local_file remote_ip:remote_file
    
    • 第1,2个指定了用户名,命令执行后需要再输入密码,第1个仅指定了远程的目录,文件名字不变,第2个指定了文件名
    • 第3,4个没有指定用户名,命令执行后需要输入用户名和密码,第3个仅指定了远程的目录,文件名字不变,第4个指定了文件名
  • 指明本地文件夹复制到远端

      scp -r local_folder remote_username@remote_ip:remote_folder 
    
      scp -r local_folder remote_ip:remote_folder
    
    • 第1个指定了用户名,命令执行后需要再输入密码
    • 第2个没有指定用户名,命令执行后需要输入用户名和密码
  • 从远程复制到本地

从远程复制到本地,只要将从本地复制到远程的命令的后2个参数调换顺序即可,比如scp -r remote_username@remote_ip:remote_folder local_folder

参数说明:

  • -1: 强制scp命令使用协议ssh1
  • -2: 强制scp命令使用协议ssh2
  • -4: 强制scp命令只使用IPv4寻址
  • -6: 强制scp命令只使用IPv6寻址
  • -B: 使用批处理模式(传输过程中不询问传输口令或短语)
  • -C: 允许压缩。(将-C标志传递给ssh,从而打开压缩功能)
  • -p:保留原文件的修改时间,访问时间和访问权限。
  • -q: 不显示传输进度条。
  • -r: 递归复制整个目录。
  • -v:详细方式显示输出。scp和ssh(1)会显示出整个过程的调试信息。这些信息用于调试连接,验证和配置问题。
  • -c cipher: 以cipher将数据传输进行加密,这个选项将直接传递给ssh。
  • -F ssh_config: 指定一个替代的ssh配置文件,此参数直接传递给ssh。
  • -i identity_file: 从指定文件中读取传输时使用的密钥文件,此参数直接传递给ssh。
  • -l limit: 限定用户所能使用的带宽,以Kbit/s为单位。
  • -o ssh_option: 如果习惯于使用ssh_config(5)中的参数传递方式,
  • -P port:注意是大写的P, port是指定数据传输用到的端口号
  • -S program: 指定加密传输时所使用的程序。此程序必须能够理解ssh(1)的选项。

中转

场景: 我们有两台互相没哟配置过连接的远端服务器A和B,我们需要在A上从A复制文件到B.

这也是一个很常见的场景,比如我们在一台远端服务器上编译好了一个程序,希望将它分发到多台服务器上时.这时就可以通过在本地设置

ForwardAgent yes

来实现,这个场景就可以使用命令

scp -pr A_folder B_username@B:B_folder