ssh 和 scp 基础

OpenSSH 概览

SSH 是 Secure SHELL 的缩写,顾名思义,这是一种建立在应用层基础上的安全协议,是一种加密的网络传输协议

可在不安全的网络中为网络服务提供安全的传输环境(即端到端加密,即使流量被劫持,也无法解密),专为 Linux 远程登陆和其他服务提供的安全协议。

SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。

通过 SSH 可以对所有传输的数据进行加密,也能够防止 DNS 欺骗和 IP 欺骗。

人们通常利用 SSH 来远程登录到服务器上执行命令。(类似 Windows 上的 rdb 协议)

平时大家经常所讲的 SSH ,其实是 OpenSSH 。它是基于 SSH 协议的开源实现 ,基于 SSH 协议实现的工具中 OpenSSH 最为出名。

在嵌入式服务器中,用户通过远程主机通过OpenSSH连接服务器。在Linux下基于tty运行login程序供client程序连接。

openssh 是利用 OpenSSL 协议具体实现的开源软件,包括 ssh,ssh-copyid,ssh-keygen 等一系列套件,在 Linux 各大发行版基本上都已经预先安装好了。

可以使用 ssh -V 命令来查看 OpenSSH 版本。

在 Linux 中,sshd 是 OpenSSH SSH 的守护进程。用于在不可信网络上提供安全的连接通道。

sshd 守护进程通常由 root 用户启动,它监听来自客户端的连接,然后为每个连接派生一个子进程。

子进程负责处理密钥交换、加密、认证、执行命令、数据交换等具体事务。

Windows 下的 ssh

从 Win10 1809 和 Windows Server 2019 开始 Windows 开始支持 OpenSSH Server。

https://www.cnblogs.com/sparkdev/p/10166061.html

所以我们在 windows 10 上基本也可以不用安装什么 xshell ,只要 cmd 或 terminal 就可以 ssh 到远程服务器了。

OpenSSH 客户端程序默认已经被系统安装好了,打开 设置->应用->可选功能 面板就可以看到:

也可以添加功能,安装 openssh server,安装好后,在服务中启动 openssh server 就可以让 windows 被 ssh 远程连接。

Windows 系统中 OpenSSH 的安装目录为 C:\Windows\System32\OpenSSH,不管是客户端程序还是服务器端程序都这这个目录中:

OpenSSH 服务器端程序的默认配置文件 sshd_config_default 也在这个目录中。这个目录会被添加到 PATH 环境变量中:

本文只记录 ssh 基本组件的用法,关于 ssh-agent 和 ssh-add 等命令,这里没有记录。

openssh 的认证方式:

  • 密码认证
  • 密钥认证(非对称加密)

OpenSSL

OpenSSL 是用于传输层安全性(TLS)协议的健壮的,商业级,功能齐全的开源工具包,因 安全套接字层(SSL)协议 而闻名。

这个协议的实现是基于完整功能的通用密码库,该库也可以独立使用。

OpenSSL 代码库的地址是 https://github.com/openssl/openssl

用户可以从 www.openssl.org/source 或者 github 下载官方发行版的源代码压缩包 。OpenSSL项目不会以二进制形式分发工具包。

但是,对于各种各样的操作系统,可以使用 OpenSSL 工具包的预编译版本。(各大 Linux 发行版基本上都有带预编译好的 OpenSSL)

特别是在Linux和其他Unix操作系统上,通常建议与发行商或供应商提供的预编译共享库链接。一般不建议在 Linux 上自行编译安装 OpenSSL

这是一个操作系统很底层的加密库,很多应用层的软件都引用了它(比如nginx,python等),所以一般不建议在生产环境直接编译。

OpenSSL 工具包括:

  • libssl 是TLSv1.3(RFC 8446)之前的所有TLS协议版本的实现。
    我们平时在安装软件时,经常会安装这个依赖包,yum -y install openssl-dev openssl

  • libcrypto 一个功能全面的通用密码库。它构成了TLS实施的基础,但也可以独立使用。

  • openssl OpenSSL命令行工具,瑞士军刀,用于加密任务,测试和分析。它可以用于

    • 关键参数的创建
    • X.509证书,CSR和CRL的创建
    • 消息摘要的计算
    • 加密和解密
    • SSL / TLS客户端和服务器测试
    • 处理S / MIME签名或加密的邮件
    • 和更多…

作为一个基于密码学的安全开发包,OpenSSL 提供的功能相当强大和全面,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及 SSL 协议,并提供了丰富的应用程序供测试或其它目的使用。

https://blog.csdn.net/naioonai/article/details/80984032

ssh命令组件

命令 作用
ssh 登陆远程主机
ssh-keygen 生成密钥对
ssh-copy-id 传输公钥到远程主机
scp 远程传输文件
ssh-agent

ssh 用法

  1. # -p 端口 -i 密钥
  2. # 这个命令会利用密钥认证,直接免密登陆,如果没有用密钥,那么会交互式弹出密码输入
  3. $ ssh user@host -p port -i /path/private_key
  4. # 查看帮助
  5. $ ssh --help

SSH命令格式

  1. usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
  2. [-D [bind_address:]port] [-e escape_char] [-F configfile]
  3. [-I pkcs11] [-i identity_file]
  4. [-L [bind_address:]port:host:hostport]
  5. [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
  6. [-R [bind_address:]port:host:hostport] [-S ctl_path]
  7. [-W host:port] [-w local_tun[:remote_tun]]
  8. [user@]hostname [command]

主要参数说明

  1. -l 指定登入用户
  2. -p 设置端口号
  3. -f 后台运行,并推荐加上 -n 参数
  4. -n 将标准输入重定向到 /dev/null,防止读取标准输入。如果在后台运行ssh的话(-f选项),就需要这个选项。
  5. -N 不执行远程命令,只做端口转发
  6. -q 安静模式,忽略一切对话和错误提示
  7. -T 禁用伪终端配置
  8. -t tty)为远程系统上的ssh进程分配一个伪tty(终端)。如果没有使用这个选项,当你在远程系统上运行某条命令的时候,ssh不会为该进程分配tty(终端)。相反,ssh将会把远端进程的标准输入和标准输出附加到ssh会话上去,这通常就是你所希望的(但并非总是如此)。这个选项将强制ssh在远端系统上分配tty,这样那些需要tty的程序就能够正常运行。
  9. -v verbose)显示与连接和传送有关的调试信息。如果命令运行不太正常的话,这个选项就会非常有用。

在远程主机上直接执行命令

远程执行命令,ssh 可以直接在远程的目标主机上执行命令,而不用登陆上去后再来执行,就好像在本地执行一样。

例如下面这条命令,命令就直接在远程终端执行了,也直接返回到本地了。

  1. root@fengzhao-work:~# ssh db-master-139 "df -h"
  2. Filesystem Size Used Avail Use% Mounted on
  3. /dev/mapper/centos-root 793G 13G 780G 2% /
  4. devtmpfs 47G 0 47G 0% /dev
  5. tmpfs 47G 0 47G 0% /dev/shm
  6. tmpfs 47G 3.5G 44G 8% /run
  7. tmpfs 47G 0 47G 0% /sys/fs/cgroup
  8. /dev/sda2 494M 157M 338M 32% /boot
  9. /dev/sda1 200M 12M 189M 6% /boot/efi
  10. /dev/sdb1 11T 1.4G 11T 1% /data
  11. /dev/mapper/centos-home 50G 38M 50G 1% /home
  12. /dev/sdc1 7.3T 4.5T 2.9T 62% /backup
  13. tmpfs 9.4G 12K 9.4G 1% /run/user/42
  14. tmpfs 9.4G 0 9.4G 0% /run/user/0
  15. /dev/sde1 7.3T 33M 7.3T 1% /DBbackup
  16. root@fengzhao-work:~#

如果是简单执行几个命令,则:

  1. ssh user@remoteNode "cd /home ; ls"

基本能完成常用的对于远程节点的管理了,几个注意的点:

  1. 双引号,必须有。如果不加双引号,第二个ls命令在本地执行
  2. 分号,两个命令之间用分号隔开

对于脚本的方式:

有些远程执行的命令内容较多,单一命令无法完成,考虑脚本方式实现:

  1. #!/bin/bash
  2. ssh user@remoteNode > /dev/null 2>&1 << remotessh
  3. cd /home
  4. touch abcdefg.txt
  5. # 执行一大堆命令
  6. exit
  7. remotessh
  8. echo done!
  9. #  远程执行的内容在 "<< remotessh " 至 "remotessh " 之间,在远程机器上的操作就位于其中,注意的点:
  10. # << remotessh,ssh后直到遇到remotessh这样的内容结束,remotessh可以随便修改成其他形式。
  11. # 重定向目的在于不显示远程的输出了
  12. # 在结束前,加exit退出远程节点

ssh的-t参数

  1. -t Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.

中文翻译一下:就是可以提供一个远程服务器的虚拟tty终端,加上这个参数我们就可以在远程服务器的虚拟终端上输入自己的提权密码了,非常安全。

命令格式

  1. ssh -t -p $port $user@$ip 'cmd'
  1. #!/bin/bash
  2. # 变量定义
  3. ip_array=("192.168.1.1" "192.168.1.2" "192.168.1.3")
  4. user="test1"
  5. remote_cmd="/home/test/1.sh"
  6. # 本地通过ssh执行远程服务器的脚本
  7. for ip in ${ip_array[*]}
  8. do
  9. if [ $ip = "192.168.1.1" ]; then
  10. port="7777"
  11. else
  12. port="22"
  13. fi
  14. ssh -t -p $port $user@$ip "remote_cmd"
  15. done

ssh-keygen 用法

ssh-keygen 命令是用来生成一对新密钥对的。

  1. # -t 算法 -b 密钥长度 -C 标识(一般设为邮箱) -f 密钥对名称
  2. # 这个命令会生成 /path/keyname.pub(传到远程主机的公钥)和 /path/keyname(登陆远程主机的私钥)
  3. ssh-keygen -t rsa -b 2048 -C "comment" -f /path/keyname
  4. # 清除ssh私钥中的phrase,交互式弹出让输入老密码,然后新密码置空,即可清除老密码
  5. ssh-keygen -f ~/.ssh/kc_id_rsa -p
  6. # 语法
  7. ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]

ssh-copy-id 用法

  1. # 这个命令会交互式提示输入密码,把公钥传入远程主机中的user用户的家目录下:~/.ssh/authorized_keys
  2. $ ssh-copy-id -i /path/publice_key user@host -p port
  3. -f: force mode -- copy keys without trying to check if they are already installed
  4. -n: dry run -- no keys are actually copied

scp 用法

  1. # 把本地文件上传到远程主机
  2. $ scp /path/filename user@host:/path
  3. # 从远程主机下载文件到本地
  4. $ scp user@host:/path/filename /var/www/local_dir

OpenSSH 详解

OpenSSH 也是一种 C/S 架构的模式,客户端和服务端分别是 ssh/sshd 。

一般 Linux 启动后默认都会启动服务端的 sshd 服务,sshd 服务端默认端口一般是22,可以服务端配置文件修改。所以我们可以在某台 Linux 上以 ssh 客户端登陆到远程的 Linux 服务器上。命令大致如下:

  1. # 使用 root 用户,私钥验证 登陆远程的 192.1668.1.102(ssh默认是用22端口,可以省略)
  2. $ ssh root@192.168.1.102 -p 22 -i ~/.ssh/id_rsa
  1. # 使用 root 用户,密码验证 登陆远程的 192.1668.1.102 (会弹出密码输入提示)
  2. $ ssh root@192.168.1.102 -p 22

ssh 相关文件

ssh 的配置文件一般在 ~/.ssh 目录中,由于安全原因,该目录的权限一般要设置为 700 。

  1. # 查看ssh有哪些包
  2. $ rpm -qa | grep -i ssh
  3. openssh-clients-7.4p1-16.el7.x86_64
  4. libssh2-1.4.3-12.el7_6.2.x86_64
  5. openssh-7.4p1-16.el7.x86_64
  6. openssh-server-7.4p1-16.el7.x86_64
  7. # 查看openssh-client安装了哪些包
  8. $ rpm -ql openssh-clients
  9. /etc/ssh/ssh_config
  10. /usr/bin/scp
  11. /usr/bin/sftp
  12. /usr/bin/slogin
  13. /usr/bin/ssh
  14. /usr/bin/ssh-add
  15. /usr/bin/ssh-agent
  16. /usr/bin/ssh-copy-id
  17. /usr/bin/ssh-keyscan
  18. /usr/lib64/fipscheck/ssh.hmac
  19. /usr/libexec/openssh/ssh-pkcs11-helper
  20. /usr/share/man/man1/scp.1.gz
  21. /usr/share/man/man1/sftp.1.gz
  22. /usr/share/man/man1/slogin.1.gz
  23. /usr/share/man/man1/ssh-add.1.gz
  24. /usr/share/man/man1/ssh-agent.1.gz
  25. /usr/share/man/man1/ssh-copy-id.1.gz
  26. /usr/share/man/man1/ssh-keyscan.1.gz
  27. /usr/share/man/man1/ssh.1.gz
  28. /usr/share/man/man5/ssh_config.5.gz
  29. /usr/share/man/man8/ssh-pkcs11-helper.8.gz
  30. # ssh客户端全局配置文件,所有用户公用的配置文件。
  31. /etc/ssh/ssh_config
  32. # ssh客户端用户配置文件,针对某个用户的具体配置文件,可以覆盖全局配置文件
  33. ~/.ssh/config
  34. # ssh服务端配置文件,用来配置认证方式,是否启用root登陆,加密方式
  35. /etc/ssh/sshd_config
  36. # 客户端用户私钥,从客户端登陆服务端需要提供这个私钥证明合法登陆。为了安全,这个文件的权限必须是600。~/.ssh 目录的权限必须是700
  37. ~/.ssh/id_rsa
  38. # ssh服务端公钥,公钥与私钥是一对密钥对,一般要设置为600,防止其他用户把自己的公钥注入进来
  39. # 这个文件可以存放多个公钥
  40. ~/.ssh/authorized_keys
  41. # 你访问过远程主机的公钥指纹都记录在~/.ssh/known_hosts。当下次访问相同计算机时,OpenSSH 会核对公钥指纹。如果公钥不同,OpenSSH 会发出警告。
  42. ~/.ssh/known_hosts
  43. # SSH中文手册和配置文件
  44. http://www.jinbuguo.com/openssh/sshd.html
  45. http://www.jinbuguo.com/openssh/sshd_config.html
  46. http://www.jinbuguo.com/openssh/ssh-keygen.html

关于 ssh 的公钥认证详细原理,可以参考阮一峰的博客。

http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html

  1. # ~/.ssh/config 配置示例
  2. # 这个例子配置了三个主机。端口,用户,私钥这些可以共用的配置都被 * 号这个主机段匹配。
  3. Host server1
  4. Hostname 192.168.1.101
  5. Host server2
  6. Hostname 192.168.1.102
  7. Host server3
  8. Hostname 192.168.1.103
  9. Host *
  10. Identityfile /home/fengzhao/.ssh/server
  11. port 22
  12. User root

以后在本地,可以直接使用 ssh server1 这种形式直接登陆 192.168.1.101

  1. # /etc/ssh/sshd_config sshd 服务端常用配置选项
  2. port 22 # ssh端口,Linux一般都是22端口做为ssh服务
  3. PermitRootLogin yes # 允许root远程登录
  4. PasswordAuthentication no  # 不允许密码方式登录
  5. RSAAuthentication yes # 允许RSA认证,只针对SSH1
  6. PubkeyAuthentication yes # 允许公钥认证
  7. AuthorizedKeysFile .ssh/authorized_keys #保存公钥的认证文件

SSH 常用场景

使用密钥认证方式登陆

前提条件,已经可以用密码方式登陆远程主机。

  1. 在本地用 ssh-keygen 命令生成密钥对,它会提示你输入密钥保存路径,确认短语(相当于私钥的密码,只要保证私钥不泄露,一般没太大必要再为私钥设密码),-t 指明加密算法(dsa,ecdsa,ed25519,rsa),-b 指明密钥长度(2048,4096),-f 指明存储路径和文件名。
  1. fengzhao@fengzhao-work:/$ ssh-keygen -t rsa
  2. Generating public/private rsa key pair.
  3. Enter file in which to save the key (/home/fengzhao/.ssh/id_rsa):

生成的两个文件 id_rsa 和 id_rsa.pub 分别是私钥(私钥自己保留)和公钥(传到远程主机)。

注意保存好私钥文件,开启私钥认证之后,就可以直接凭私钥登陆。

  1. 通过 ssh-copy-id 命令将公钥传到远程主机。(ssh-copy-id 拥有到远程机器的home, ~./ssh , 和 /.ssh/authorized_key文件中,所以也可以手动复制写进去)。
  1. fengzhao@fengzhao-work:~$ ssh-copy-id -i /home/fengzhao/.ssh/id_rsa.pub root@192.168.8.23
  2. /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/fengzhao/.ssh/id_rsa.pub"
  3. /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
  4. /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
  5. root@192.168.8.23's password:
  6. Number of key(s) added: 1
  7. Now try logging into the machine, with: "ssh 'root@192.168.8.23'"
  8. and check to make sure that only the key(s) you wanted were added.
  9. fengzhao@fengzhao-work:~$
  1. 在远程主机 ssh 配置文件中开启允许密钥认证,确认可以用密钥登陆后再关闭密码登陆。

SSH端口转发

SSH 端口转发也被称作 SSH 隧道(SSH Tunnel),因为它们都是通过 SSH 登陆之后,在 SSH客户端SSH服务端 之间建立了一个隧道,从而进行通信。

SSH隧道是非常安全的,因为SSH是通过加密传输数据的。

SSH有三种端口转发模式

  • 本地端口转发(Local Port Forwarding)

  • 远程端口转发(Remote Port Forwarding)

  • 动态端口转发(Dynamic Port Forwarding)

本地端口转发

应用场景:远程云主机 192.168.0.1 运行了一个服务,端口为3000,但是远程主机的3000端口没办法对外开放,只有 SSH 的 22 端口可以对外开放,这个时候可以在本地的一台服务器 中开启本地端口转发功能,使得访问本地服务器的请求被转发到远程云主机上,就好像直接访问一样。

所谓本地端口转发:是针对进行 SSH 操作的主机来说的,如下面的例子:端口转发命令是在 192.168.0.2 上执行的,所以 192.168.0.1 就叫本地,本地端口转发就是将发送到本地主机端口(192.168.0.2:8000)的请求,转到到远程主机端口(192.168.0.1:3000)。仿佛是通过 ssh 建立一个中间隧道一样。

Linux-ssh-scp-foundmentals - 图1

  • 192.168.0.1——类比为远程的公网服务器,运行了 node 占用3000端口,仅对外开放 SSH 的 22 端口。
  • 192.168.0.2——类比为本地的端口转发服务器,将访问 192.168.0.1:8000 的请求转发到 192.168.0.2:8000
  • 192.168.0.3——类比为本地一个客户端,需要访问 192.168.0.1 上的 node 服务

在 192.168.0.1 上部署 node 项目并启动:

  1. root@fengzhao-linux-server:/tmp# cat demo.js
  2. var http = require('http');
  3. var server = http.createServer(function(request, response)
  4. {
  5. response.writeHead(200,
  6. {
  7. "Content-Type": "text/plain"
  8. });
  9. response.end("Hello fengzhao\n");
  10. });
  11. server.listen(3000);
  12. root@fengzhao-linux-server:/tmp# forever start demo.js
  13. warn: --minUptime not set. Defaulting to: 1000ms
  14. warn: --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
  15. info: Forever processing file: demo.js
  16. root@fengzhao-linux-server:/tmp# curl -i http://localhost:3000
  17. HTTP/1.1 200 OK
  18. Content-Type: text/plain
  19. Date: Fri, 26 Jul 2019 06:41:54 GMT
  20. Connection: keep-alive
  21. Transfer-Encoding: chunked
  22. Hello fengzhao
  23. root@fengzhao-linux-server:/tmp#

在 192.168.0.2 上访问这个项目:

  1. root@fengzhao-work:~# curl -i http://192.168.0.1:8000
  2. HTTP/1.1 200 OK
  3. Content-Type: text/plain
  4. Date: Fri, 26 Jul 2019 06:42:23 GMT
  5. Connection: keep-alive
  6. Transfer-Encoding: chunked
  7. Hello fengzhao
  8. root@fengzhao-work:~#

在 192.168.0.2 上执行如下命令进行端口转发:

  1. # -L [bind_address:]port:host:hostport 将发到本地端口的请求转发到远端的端口请求
  2. ssh -NTfL 192.168.0.2:8000:192.168.0.1:3000 root@192.168.0.1

在 192.168.0.3 上访问 192.168.0.2:

  1. root@fengzhao-work:~# curl -i http://192.168.0.2:8000
  2. HTTP/1.1 200 OK
  3. Content-Type: text/plain
  4. Date: Fri, 26 Jul 2019 06:48:27 GMT
  5. Connection: keep-alive
  6. Transfer-Encoding: chunked
  7. Hello fengzhao
  8. root@fengzhao-work:~#
  • N: 表示连接远程主机,不打开 shell,不执行命令
  • T: 表示不为这个连接分配 TTY
  • f: 表示连接成功后,转入后台运行
  • L:表示本地端口转发,-L [bind_address:]port:host:hostport

SSH 本地端口转发的命令如下:

  1. ssh -L 本地地址:本地端口:远程地址:远程端口 user@remote-host-ip

远程端口转发

应用场景:本地主机A1运行了一个服务,端口为3000,远程云主机B1需要访问这个服务。正常情况外网的云主机是无法访问本地服务的。

所谓远程端口转发:是针对进行 SSH 操作的主机来说的,如下面的例子:端口转发命令是在 192.168.0.1 上执行的,所以 192.168.0.1 就叫本地,远程端口转发就是将发送到远程主机端口(192.168.0.2:4000)的的请求,转发到本地主机端口(192.168.0.1:3000)。

Linux-ssh-scp-foundmentals - 图2

在 192.168.0.1 上运行 node 服务,占用 3000 端口。

在 192.168.0.1 上执行如下命令:

  1. ssh -NTfR 192.168.0.2:4000:localhost:3000 root@192.168.0.2

然后在 192.168.0.2 上访问 localhost:4000 ,其实就是在访问 192.168.0.1:3000

上面说了,这种情况下,在远程主机上只能监听本地环回地址,只能本机访问,假设第三台机器也想通过远程主机(192.168.0.2)来访问这个服务呢,这就需要在远程主机(192.168.0.2)上开启 sshd 服务的 GatewayPorts 参数,这个参数默认是 no,所以需要在远程主机(192.168.0.2)上修改为 yes 后,再在本地主机(192.168.0.1)上重新执行远程端口转发命令,这样就可以在远程主机上监听所有网卡的端口了。

SCP 远程传输

scp 就是 secure copy,是用来进行远程文件复制的,整个复制过程是加密的,数据传输使用的是 ssh,并且使用和 ssh 相同的认证方式,提供相同的安全保证。所以 scp 也可以同时使用 密码认证 和 密钥认证 两种方式。

上传本地文件到远程主机

  1. # 上传本地文件到远程主机
  2. $ scp /path/filename username@servername:/path/

从远程主机下载文件到本地

  1. # 从远程主机下载文件到本地
  2. $ scp username@servername:/path/filename /var/www/local_dir(本地目录)

scp -r 可以递归上传或者下载,用于对于目录的传输。

scp -i 指定私钥文件。(如果公钥已经传到远程主机,并且开启密钥认证)

如果本地ssh客户端配置好了主机,也可以直接用 scp server1 这种格式。

sftp文件传输

sftp是Secure FileTransferProtocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的加密方法。

sftp与 ftp有着几乎一样的语法和功能。

SFTP为 SSH 的一部分,是一种服务器之间文件传输的安全方式。SCP和SFTP的共同之处在于「使用SSH将文件加密才传输的」

使用「WinSCP」或者「FileZilla」之类的客户端,还可以和Windows之间进行文件传输。

批量分发公钥到多台主机

如果有多台远程主机时,一个一个去远程复制比较麻烦,所以考虑需要一次性把公钥复制到多个主机,之前的过程存在两个问题需要人工输入:

  1. ssh 第一次登陆一台主机时,会弹出远程主机的公钥指纹,需要手动输入 yes 确认。
  2. ssh 协议不支持在命令中直接输入密码,一般都是弹出 prompt 来手动输入密码。

第一个问题,可以在本地 ssh 客户端配置文件(~/.ssh/config)中配置 StrictHostKeyChecking=no 或在 ssh 命令中使用 -o StrictHostKeyChecking=no 来关闭公钥提示。

第二个问题,考虑用第三方工具 sshpass 来解决,这个工具支持在 ssh 命令行直接使用密码,而不需要弹出 prompt 再手动输入密码。

直接用 yum 或者 apt 包管理器安装 sshpass 。

这个配置修改和安装软件,都是在本地进行,而不需要在远程进行。

自动传公钥到远程主机

  1. $ sshpass -p 'YOUR_PASSWORD' ssh-copy-id -o StrictHostKeyChecking=no root@192.168.1.102

实现自动传公钥之后,考虑多台主机的一次性上传,如果多台主机的端口密码均相同,可以把主机 ip 或域名 存放到文件中。循环遍历主机并上传公钥。

  1. for host in $(cat remote-hosts)
  2. do
  3. sshpass -p 'YOUR_PASSWORD' ssh-copy-id -i /path/id_rsa.pub -o StrictHostKeyChecking=no root@${host}
  4. done

如果主机密码和端口均不相同,可以考虑把主机ip密码端口按照一定格式存到文件中,使用 cut 命令切割获取相应记录。

主机文件格式:

  1. 10.10.10.11:2221:YOURPASSWORD1
  2. 10.10.10.12:2222:YOURPASSWORD2

因为ssh-copy-id使用非默认端口时,需要加双引号,没有找到地的办法,先将整个命令放至一个临时文件。再执行该临时文件,执行之后,再删除。

  1. for host in $(cat remote-hosts)
  2. do
  3. ip=$(echo ${host} | cut -f1 -d ":")
  4. port=$(echo ${host} | cut -f2 -d ":")
  5. password=$(echo ${host} | cut -f3 -d ":")
  6.   arg=$(echo -p ${port} -o StrickHostKeyChecking=no root@${ip})
  7.   echo sshpass -p ${password} ssh-copy-id '"'${arg}'"' >> tmp.sh
  8. done
  9. sh tmp.sh
  10. rm -f tmp.sh

ssh 和 scp 使用代理

连接国外 VPS 时,因为某些原因,ssh 连上了很卡,而且经常失去连接,因此需要让 ssh 走代理加速。

ssh 使用 socks5、http_connect 代理:

  1. # 通过 socks5 代理
  2. $ ssh -oProxyCommand="nc -X5 -x127.0.0.1:1080 %h %p" USER@SSH_SERVER
  3. # 通过 http_connect 代理
  4. $ ssh -oProxyCommand="nc -Xconnect -x127.0.0.1:1080 %h %p" USER@SSH_SERVER

有的时候你可能没法直接登录到某台服务器,而需要使用一台中间服务器进行中转,如公司内网服务器。首先确保你已经为服务器配置了公钥访问,并开启了agent forwarding,那么你需要添加如下配置到 ~/.ssh/config

  1. # github代理
  2. host github.com
  3. user git
  4. hostname github.com
  5. identityfile /root/.ssh/vultr
  6. # PreferredAuthentications publickey
  7. ProxyCommand nc -x 172.31.32.1:1080 %h %p

scp/sftp 使用 socks5、http_connect 代理:

  1. $ scp -Cpr -oProxyCommand="nc -X5 -x127.0.0.1:1080 %h %p" files USER@SSH_SERVER:/
  2. $ scp -Cpr -oProxyCommand="nc -Xconnect -x127.0.0.1:1080 %h %p" files USER@SSH_SERVER:/
  3. $ sftp -oProxyCommand="nc -X5 -x127.0.0.1:1080 %h %p" USER@SSH_SERVER
  4. $ sftp -oProxyCommand="nc -Xconnect -x127.0.0.1:1080 %h %p" USER@SSH_SERVER

如果你使用的是 XShell,也可以设置代理:

https://blog.csdn.net/DiamondXiao/article/details/52488628

ssh 批量分发密钥

ssh安全

火狐信息安全openssh—guidelines

https://infosec.mozilla.org/guidelines/openssh

https://github.com/jtesta/ssh-audit

ssh-audit审计

ssh-audit 是一款 ssh 安全审计工具,

jtesta/ssh-audit(v2.x) 是基于arthepsy/ssh-audit (v1.x) 进行fork的一个项目,由于后者已经不再更新,所以现在也有很多人用这个。

主要功能特性:

  • 支持 ssh1 和 ssh2 协议;
  • 可以分析 ssh 客户端配置;
  • 识别 ssh banner , 识别操作系统,软硬件等;
  • 输出算法信息 (available since, removed/disabled, unsafe/weak/legacy, etc等);
  • 输出算法建议(添加或删除基于公认的软件版本);
  • 输出安全信息(有关的问题,分配CVE列表等);
  • 没有依赖关系,与 Python 2.6+,Python的3.x和PyPy兼容;
  • 从OpenSSH的,Dropbear SSH和libssh历史信息;
  • 分析基于算法的信息SSH版本的兼容性;

install-and-usage


  1. # 通过 pip 安装
  2. pip install ssh-audit
  3. git clone https://github.com/jtesta/ssh-audit.git ~/ssh-audit
  4. usage: ssh-audit.py [options] <host>
  5. -h, --help print this help
  6. -1, --ssh1 force ssh version 1 only
  7. -2, --ssh2 force ssh version 2 only
  8. -4, --ipv4 enable IPv4 (order of precedence)
  9. -6, --ipv6 enable IPv6 (order of precedence)
  10. -b, --batch batch output
  11. -c, --client-audit starts a server on port 2222 to audit client
  12. software config (use -p to change port;
  13. use -t to change timeout)
  14. -j, --json JSON output
  15. -l, --level=<level> minimum output level (info|warn|fail)
  16. -L, --list-policies list all the official, built-in policies
  17. --lookup=<alg1,alg2,...> looks up an algorithm(s) without
  18. connecting to a server
  19. -M, --make-policy=<policy.txt> creates a policy based on the target server
  20. (i.e.: the target server has the ideal
  21. configuration that other servers should
  22. adhere to)
  23. -n, --no-colors disable colors
  24. -p, --port=<port> port to connect
  25. -P, --policy=<policy.txt> run a policy test using the specified policy
  26. -t, --timeout=<secs> timeout (in seconds) for connection and reading
  27. (default: 5)
  28. -T, --targets=<hosts.txt> a file containing a list of target hosts (one
  29. per line, format HOST[:PORT])
  30. -v, --verbose verbose output
  31. # 比如,我们在服务器上执行 ssh-audit 来解决
  32. ./ssh-audit.py 127.0.0.1
  33. # 一般会报ssh加密算法不安全问题。可以在 sshd_config 文件中设置为如下加密算法
  34. Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
  35. HostKeyAlgorithms rsa-sha2-512,rsa-sha2-256,ssh-ed25519
  36. KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
  37. MACs umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com

ssh漏洞及安全基线

https://github.com/cpandya2909/CVE-2020-15778/

https://www.cnblogs.com/canyezhizi/p/13537495.html

openssh 编译升级

<<<<<<< HEAD

ssh-deny

=======

https://blog.csdn.net/weixin_41305441/article/details/107108429

ssh 连接速度

How to Check the Speed of Your ssh Connection

https://webleit.info/how-to-check-the-speed-of-your-ssh-connection/

Have you ever wondered what is the speed of your ssh connection ?

For example you are connected to a server in Dubai but you live in London and now you want to know what is the speed if you need to scp something.

Well the solution to this problem is called PV.

PV is a terminal-based (command-line based) tool in Linux that allows the monitoring of data being sent through pipe. The full form of PV command is Pipe Viewer. PV helps the user by giving him a visual display of the following:

  • Time Elapsed
  • Completed Progress (percentage bar)
  • Current data transfer speed (also referred to as throughput rate)
  • Data Transferred
  • ETA (Estimated Time) (Remaining time)

pv命令是Pipe Viewer 的简称,由Andrew Wood 开发。意思是通过管道显示数据处理进度的信息。

这些信息包括已经耗费的时间,完成的百分比(通过进度条显示),当前的速度,全部传输的数据,以及估计剩余的时间。

显示与操作有关的有用信息,包括已经传输了的数据量,花费的时间,传输速率,进度条,进度的百分比,以及剩余的时间

https://www.linuxcool.com/pv

  1. apt install pv
  2. yes | pv | ssh remote_host "cat >/dev/null"
  3. 166MiB 0:01:01 [2.52MiB/s] [ <=>