SSH 教程-1 客户端 配置 [MD]

博文地址

我的GitHub 我的博客 我的微信 我的邮箱
baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

目录

SSH 教程 -1

本文改编自 网道的 SSH 教程,主要为了精简大量本人不感兴趣的内容。

本教程约定,大写的 SSH 表示协议,小写的 ssh 表示客户端软件。

SSH 基本知识

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

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

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

它还能对操作者进行认证(authentication)和授权(authorization)。明文的网络协议可以套用在它里面,从而实现加密。

SSH 发展历史

  • 1995年,芬兰赫尔辛基工业大学的研究员 Tatu Ylönen 设计了 SSH 协议的第一个版本 SSH 1,同时写出了第一个实现 SSH1。
  • 1996年,又提出了 SSH 2 协议,这个协议与1.0版不兼容,1998年推出了软件实现 SSH2。但是,官方的 SSH2 软件是一个专有软件,不能免费使用。
  • 1999年,OpenBSD 的开发人员写了一个 SSH 2 协议的开源实现,这就是 OpenSSH 项目。目前,Linux 的所有发行版几乎都自带 OpenSSH。

SSH 软件架构

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

  • 向服务器发出请求的部分,称为客户端,OpenSSH 的实现为 ssh
  • 接收客户端发出的请求的部分,称为服务器,OpenSSH 的实现为 sshd

OpenSSH 还提供一些辅助工具软件(比如 ssh-keygen 、ssh-agent)和专门的客户端工具(比如 scp 和 sftp)。

SSH 客户端

OpenSSH 的客户端是二进制程序 ssh。Linux 系统一般都自带 ssh,如果没有就需要安装。

where ssh   # 文件位置【C:\Windows\System32\OpenSSH\ssh.exe】
ssh -V      # 查看版本【OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2】

sudo apt install openssh-client   # Ubuntu 和 Debian 上安装
sudo dnf install openssh-clients  # CentOS 和 Fedora 上安装

连接流程

ssh 最常见的用途就是登录服务器,这要求服务器安装并正在运行 SSH 服务器软件。

ssh -l user host  # 登录服务器,host 可以是主机名、网站域名、IP 地址,等价于【ssh user@host】
ssh host          # 不指定用户名时,将使用客户端的当前用户名($USER),作为远程服务器的登录用户名
ssh -p 8821 host  # 指定服务器端口,不指定时默认连接服务器的22端口

首次连接确认

ssh 连接远程服务器后,首先有一个验证过程,验证远程服务器是否为陌生地址。

如果是第一次连接某一台服务器,命令行会显示一段文字,表示不认识这台机器,提醒用户确认是否需要连接。

ssh -T git@github.com   # 测试连接服务器

The authenticity of host 'github.com (20.205.243.166)' cannot be established 确定的.
ECDSA key fingerprint is SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

其中的 fingerprint 指的是 SSH 服务器公钥的哈希值。每台 SSH 服务器都有唯一一对密钥,用于跟客户端通信,其中公钥的哈希值就可以用来识别服务器。

查看公钥的指纹

下面的命令可以查看某个公钥的指纹。

ssh-keygen -l -f ~/.ssh/id_rsa.pub  # 查看公钥的指纹

3072 SHA256:H28XXrWfd9GCnV8wpWI9p51SlgdaOnzS/kOJsrLIhpA baiqiantao@sina.com (RSA)

保存公钥的指纹

ssh 会将本机成功连接过的所有服务器公钥的指纹,都储存在本机的~/.ssh/known_hosts文件中。每次连接服务器时,通过该文件判断是否为陌生主机(陌生公钥)。

在上面这段文字后面,输入yes,就可以将当前服务器的指纹也储存在本机~/.ssh/known_hosts文件中,并显示下面的提示。以后再连接的时候,就不会再出现警告了。

Warning: Permanently added 'github.com,20.205.243.166' (ECDSA) to the list of known hosts.
Hi baiqiantao! You have successfully authenticated 认证, but GitHub does not provide shell access.

然后,客户端就会跟服务器建立连接。接着,ssh 就会要求用户输入所要登录账户的密码。用户输入并验证密码正确以后,就能登录远程服务器的 Shell 了。

服务器密钥变更

如果服务器的密钥发生变更(比如重装了 SSH 服务器),客户端再次连接时,就会发生公钥指纹不吻合的情况。这时,客户端就会中断连接,并显示一段警告信息。

这时,你需要确认是什么原因使得公钥指纹发生变更,到底是恶意劫持,还是管理员变更了 SSH 服务器公钥。

如果新的公钥确认可以信任,你可以执行下面的命令,将原来的公钥指纹从~/.ssh/known_hosts文件删除。

ssh-keygen -R github.com  # 删除 known_hosts 中指定主机公钥的指纹,也可以手动修改此文件

删除了原来的公钥指纹以后,重新执行 ssh 命令连接远程服务器,将新的指纹加入known_hosts文件,就可以顺利连接了。

执行远程命令

SSH 登录成功后,用户就进入了远程主机的命令行环境,所看到的提示符,就是远程主机的提示符。这时,你就可以输入想要在远程主机执行的命令。

另一种执行远程命令的方法,是将命令直接写在ssh命令的后面。

采用这种语法执行命令时,ssh 客户端不会提供互动式的 Shell 环境,而是直接将远程命令的执行结果输出在命令行。但是,有些命令需要互动式的 Shell 环境,这时就要使用-t参数。

ssh user@host command     # 登录远程主机成功后,立刻在远程主机上执行命令
ssh -t user@host command  # 在 ssh 直接运行远端命令时,提供一个互动式 Shell

加密参数集

SSH 连接的握手阶段,客户端必须跟服务端约定 加密参数集(cipher suite)。

加密参数集格式

加密参数集包含了若干不同的加密参数,它们之间使用下划线连接在一起,下面是一个例子。

例如:TLS_RSA_WITH_AES_128_CBC_SHA

  • TLS:加密通信协议
  • RSA:密钥交换算法
  • AES:加密算法
  • 128:加密算法的强度
  • CBC:加密算法的模式
  • SHA:数字签名的 Hash 函数

确认加密参数集

下面是一个例子,客户端向服务器发出的握手信息。

Handshake protocol: ClientHello
    Version: TLS 1.2
    Random
        Client time: May 22, 2030 02:43:46 GMT
        Random bytes: b76b0e61829557eb4c611adfd2d36eb232dc1332fe29802e321ee871
    Session ID: (empty)
    Cipher Suites
        Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        Suite: TLS_RSA_WITH_AES_128_GCM_SHA256
        ...
    Compression methods ...
    Extensions ...

上面的握手信息(ClientHello)之中,Cipher Suites字段就是客户端列出可选的加密参数集,服务器在其中选择一个自己支持的参数集。

服务器选择完毕之后,向客户端发出回应。

Handshake protocol: ServerHello
    Version: TLS 1.2
    Random
        Server time: Mar 10, 2059 02:35:57 GMT
        Random bytes: 8469b09b480c1978182ce1b59290487609f41132312ca22aacaf5012
    Session ID: 4cae75c91cf5adf55f93c9fb5dd36d19903b1182029af3d527b7a42ef1c32c80
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    Compression method: null
    Extensions ...

上面的回应信息(ServerHello)中,Cipher Suite字段就是服务器最终选定的加密参数。

ssh 命令行配置项

配置项解释

-c:指定加密算法
-C:表示压缩数据传输
-D:指定本机的 Socks 监听端口,该端口收到的请求,都将转发到远程的 SSH 主机,又称动态端口转发
-f:表示 SSH 连接在后台运行
-F:指定配置文件
-i:指定私钥,默认值为~/.ssh/id_dsa~/.ssh/id_rsa,对应的公钥必须存放到服务器
-l:指定远程登录的账户名
-L:设置本地端口转发
-m:指定校验数据完整性的算法(MAC,message authentication code)
-N:表示建立的 SSH 只用于端口转发,不能执行远程命令,这样可以提供安全性
-o:用来指定一个配置命令
-p:指定 SSH 客户端连接的服务器端口
-q:表示安静模式(quiet),不向用户输出任何警告信息
-R:指定远程端口转发
-t:在 ssh 直接运行远端命令时,提供一个互动式 Shell
-v:显示详细信息
-V:输出 ssh 客户端的版本
-X:表示打开 X 窗口转发

配置项案例

ssh -c xx,yy host   # 指定使用加密算法 xx 或 yy,等价于【ssh -c xx -c yy host】
ssh -C host         # 压缩数据传输
ssh -F ~/.ssh/xx    # 使用指定的配置文件
ssh -i my-key host  # 指定私钥
ssh -l user host    # 指定远程登录的账户名,等同于【ssh user@host】
ssh -m xx,yy host   # 指定数据校验算法(MAC)为xx 或 yy
ssh -o "Key Value"  # 指定一个配置命令,等价于【ssh -o Key=Value】,等号前后不能有空格
ssh -p 2035 host    # 指定连接服务器的2035端口
ssh –q host         # 安静模式,不向用户输出任何警告信息
ssh -t host cmd     # 在 ssh 直接运行远端命令时,提供一个互动式 Shell
ssh -v host         # 可以重复多次,表示信息的详细程度,比如【-vv】和【-vvv】
ssh -V              # 输出 ssh 客户端的版本:OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2
ssh -X host         # 打开 X 窗口转发
ssh -2 host         # -1 参数指定使用 SSH 1 协议,-2 参数指定使用 SSH 2 协议
ssh -4 host         # -4 指定使用 IPv4 协议(默认值),-6 指定使用 IPv6 协议

端口转发相关

ssh -N host                     # 表示建立的 SSH 只用于端口转发,不能执行远程命令,这样可以提供安全性
ssh -D 1080 host                # 动态端口转发:将本机 1080 端口收到的请求,都转发到服务器 host
ssh -L 9999:server:80 user@host # 本地端口转发
# 所有发向本地 9999 端口的请求,都会经过 host 发往 server 的 80 端口,相当于直接连上了 server 的 80 端口
ssh -R 9999:server:902 local    # 远程端口转发,需在跳板服务器(即 local)执行此命令
# 指定本地计算机 local 监听自己的 9999 端口,所有发向这个端口的请求,都会转向 server 的 902 端口

配置文件

  • /etc/ssh/ssh_config:全局对 SSH 客户端的配置文件
  • ~/.ssh/config:用户个人对 SSH 客户端的配置文件,优先级高于全局配置文件
  • ~/.ssh/known_hosts:用户信任的 SSH 服务器的公钥指纹
  • ~/.ssh/id_rsa~/.ssh/id_rsa.pub:用于 SSH 协议版本2 的 RSA 私钥/公钥
  • ~/.ssh/identity~/.ssh/identity.pub:用于 SSH 协议版本1 的 RSA 私钥/公钥
  • ~/.ssh/id_ecdsa~/.ssh/id_ecdsa.pub:用户的 ECDSA 私钥/公钥

配置文件语法

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

# 以 # 开头的行表示注释,空行等同于注释,不允许行尾注释
# Host 的值可以使用通配符,【*.edu】表示下面的设置只对一级域名为 .edu 的主机有效
# Host 命令后面的所有配置,都是针对该主机的,直到下一个 Host 命令为止

Host *                 # 表示下面的配置对所有的主机都有效,值可以被单个主机的设置覆盖
  Port 8022            # 表示所有主机的默认连接端口都是8022,这里的缩进并不是必需的
  User = baiqiantao    # 配置命令与值之间,可以使用空格或等号(等号前后的空格是可选的)

Host github            # 表示下面的设置只对主机 github(这只是一个别名) 生效
  HostName github.com  # 具体的主机由 HostName 指定
  User git             # 像 github、gitlab、gitee 等 git 系统,用户名都是 git
  Port 22              # 指定端口,会覆盖上面的设置
  IdentityFile ~/.ssh/id_rsa_github   # 指定私钥文件

以后,登录github.com时,只要执行ssh github命令,就会自动套用 config 文件里面指定的参数。

ssh github   # 等同于【ssh -p 22 -i ~/.ssh/id_rsa_github git@github.com】

主要配置命令

下面是 ssh 客户端的一些主要配置命令,以及它们的范例值。

  • AddressFamily inet:表示只使用 IPv4 协议。如果设为inet6,表示只使用 IPv6 协议。
  • BindAddress 192.168.10.235:指定本机的 IP 地址(如果本机有多个 IP 地址)。
  • CheckHostIP yes:检查 SSH 服务器的 IP 地址是否跟公钥数据库吻合。
  • Ciphers blowfish,3des:指定加密算法。
  • Compression yes:是否压缩传输信号。
  • ConnectionAttempts 10:客户端进行连接时,最大的尝试次数。
  • ConnectTimeout 60:客户端进行连接时,服务器在指定秒数内没有回复,则中断连接尝试。
  • DynamicForward 1080:指定动态转发端口。
  • GlobalKnownHostsFile /users/smith/.ssh/my_global_hosts_file:指定全局的公钥数据库文件的位置。
  • Host host:指定连接的域名或 IP 地址,也可以是别名,支持通配符。
  • HostKeyAlgorithms ssh-dss,ssh-rsa:指定密钥算法,优先级从高到低排列。
  • HostName myhost:在Host命令使用别名的情况下,HostName指定域名或 IP 地址。
  • IdentityFile keyfile:指定私钥文件。
  • LocalForward 2001 localhost:143:指定本地端口转发。
  • LogLevel QUIET:指定日志详细程度。如果设为QUIET,将不输出大部分的警告和提示。
  • MACs hmac-sha1,hmac-md5:指定数据校验算法。
  • NumberOfPasswordPrompts 2:密码登录时,用户输错密码的最大尝试次数。
  • PasswordAuthentication no:指定是否支持密码登录。这里只是客户端禁止,真正的禁止需要在 SSH 服务器设置。
  • Port 2035:指定客户端连接的 SSH 服务器端口。
  • PreferredAuthentications publickey,hostbased,password:指定各种登录方法的优先级。
  • Protocol 2:支持的 SSH 协议版本,多个版本之间使用逗号分隔。
  • PubKeyAuthentication yes:是否支持密钥登录。这里只是客户端设置,还需要在 SSH 服务器进行相应设置。
  • RemoteForward 2001 server:143:指定远程端口转发。
  • SendEnv COLOR:SSH 客户端向服务器发送的环境变量名,多个环境变量之间使用空格分隔。环境变量的值从客户端当前环境中拷贝。
  • ServerAliveCountMax 3:如果没有收到服务器的回应,客户端连续发送多少次keepalive信号才断开连接。默认值为3。
  • ServerAliveInterval 300:客户端建立连接后,如果在给定秒数内,没有收到服务器发来的消息,客户端向服务器发送keepalive消息。如果不希望客户端发送,这一项设为0
  • StrictHostKeyChecking yesyes表示严格检查,服务器公钥为未知或发生变化,则拒绝连接。no表示如果服务器公钥未知,则加入客户端公钥数据库,如果公钥发生变化,不改变客户端公钥数据库,输出一条警告,依然允许连接继续进行。ask(默认值)表示询问用户是否继续进行。
  • TCPKeepAlive yes:客户端是否定期向服务器发送keepalive信息。
  • User userName:指定远程登录的账户名。
  • UserKnownHostsFile /users/smith/.ssh/my_local_hosts_file:指定当前用户的known_hosts文件(服务器公钥指纹列表)的位置。
  • VerifyHostKeyDNS yes:是否通过检查 SSH 服务器的 DNS 记录,确认公钥指纹是否与known_hosts文件保存的一致。

2021-12-11

上一篇:3.多线程.md


下一篇:md语法记录