SSH使用小记
0、是什么
SSH(Secure Shell)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。(更多详情可参阅维基百科 https://zh.wikipedia.org/wiki/Secure_Shell)
SSH协议基于的传输层协议为TCP,默认端口22。(与Telnet的区别,Telnet明文传输内容故不安全。默认端口FTP 21、SSH 22、Telnet 23)
大多数现代操作系统(包括macOS、大部分Linux、OpenBSD、FreeBSD、Solaris等系统)都提供了SSH协议的实现程序,但Windows系统未自带SSH程序。Windows用户可以使用Cygwin来建立SSH服务。(补注:从 Win10 1809 和 Windows Server 2019 开始 Windows 已支持 OpenSSH Server)
SSH命令参数说明:Linux下可通过 man ssh 命令查看(中文翻译版可参阅 http://linux.51yip.com/search/ssh)
1、SSH登录原理及免密登录设置
先验知识
ssh登录需要用到公钥、秘钥,它们用于对文本内容进行加密或解密。通常用RSA加密方式,其是一种对称加密,由公钥加密的内容私钥可解密、由私钥加密的内容公钥也可解密。公钥可以对外公开,私钥则不能。关于RSA加密可参阅:RSA算法原理-阮一峰
通过ssh登录远程主机通常有两种登录方式:
1、输密码登录:每次登录都要输密码。内部原理:登录时服务端发送服务端自己的公钥给客户端,客户端用该公钥加密密码并发送到服务端,服务端用对应的私钥解密,检查密码是否正确以确定是否登录成功。
第一次登录时会警告公钥是否可信任,以防止中间人攻击返回的是中间人的公钥,若用户确认信任之则公钥会保存到客户端的$HOME/.ssh/known_hosts文件里,以后再登录就不会有警告了。
2、秘钥登录(免密码登录):预先配置好秘钥,之后每次登录无需输密码。方法是在一台机器上生成公钥/私钥对并将其中一个秘钥放到另一个机器上。有两种:
2.1、公钥登录:事先将客户端的公钥放到服务端上(本质上相当于配置免密登录白名单)。内部原理:登录时服务端发送一个随机字符串给客户端,客户端用自己的私钥加密并发送到服务端,服务端根据是否有事先存储的公钥能进行解密以确定是否登录成功。
2.2、私钥登录:事先将服务端的私钥放到客户端上,每次登录时需要指定私钥,可见此时私钥相当于服务端的临时密码。
前一种方式需要对服务端进行配置,若要免密登录的客户端很多,则需要频繁修改服务端配置;后一种可以避免频繁更改服务端,但比较不安全因为私钥是不宜外泄的,这种模式只要有私钥的人就能访问服务器,但是例如阿里云服务器就是这种访问方式。
这里介绍公钥登录的配置方法(假设机器A登录机器B需要密码,但不想每次登录都需输密码):
1、A上生成密钥对: ssh-keygen ,会在当前用户目录 ~/.ssh/ 下生成 id_rsa、id_rsa.pub 两个文件,里面内容分别为私钥、公钥
2、将公钥(id_rsa.pub里的内容)追加到到B上 ~/.ssh/authorized_keys 文件中,文件不存在则新建。也可在A上通过命令完成该效果: ssh-copy-id -i ~/.ssh/id_rsa.pub <username of B>@<host of B>
3、重启B上的ssh服务: sudo service sshd restart
4、之后若还不行,可检查B上的/etc/ssh/sshd_config文件,确认如下内容没被注释:
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
参考资料:http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html
2、SSH远程操作
可通过SSH执行远程命令而不需要登录远程主机,示例:(更多可参阅:https://www.cnblogs.com/sparkdev/p/6842805.html)
# 主要命令格式
ssh user@10.5.6.47 "ls /home; pwd " # 执行基本命令,可有多个
ssh -t user@10.5.6.47 " top " # 对于需要交互(需要tty)的命令,通过ssh远程执行时不会为此会话分配tty,故ssh立即退出远程主机从而需要交互的命令立即结束。通过 -t 参数显示声明需要为会话分配tty以解决之
ssh user@10.5.6.47 " bash -s " < test.sh helloworld # 远程执行本地主机上的脚本,参数为往脚本传的参数
ssh user@10.5.6.47 /home/user/test.sh helloworld # 远程执行远程主机上的脚本,参数为往该脚本传的参数 # 其他trick示例
cd && tar czv src | ssh user@host 'tar xz' # 将$HOME/src/目录下面的所有文件,复制到远程主机的$HOME/src/目录
ssh user@host 'tar cz src' | tar xzv # 将远程主机$HOME/src/目录下面的所有文件,复制到用户的当前目录
3、SSH端口转发
3.1、是什么
SSH是安全的,会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。此外,SSH 还提供了一个非常有用的功能——端口转发:它能够将其他 TCP 端口的网络数据通过 SSH 连接来转发,并自动提供了相应的加密及解密服务。因 SSH 为其他 TCP 连接提供了一个安全的通道来进行传输,故也被称作SSH隧道(SSH Tunnel)。例如,Telnet,SMTP,LDAP 这些 TCP 应用均能够从中得益,避免了用户名,密码以及隐私信息的明文传输。而与此同时,如果工作环境中的防火墙限制了一些网络端口的使用但允许 SSH 连接,则也可通过 TCP 端口转发来使用 SSH 进行通信。
总的来说,SSH 端口转发能提供两大功能:
1、加密SSH Client与SSH Server间传输的数据
2、突破防火墙限制以间接完成一些之前无法建立的 TCP 连接
从效果上看,端口转发相当于是反向代理。
3.2、类型
SSH端口转发为无法直接任意互通但能通过SSH访问的两个网络或机器间提供了一个互通的桥梁。分为 本地端口转发、远程端口转发、动态端口转发三种。
- 本地端口转发与远程端口转发的区别在于负责执行端口转发的是所建立的SSH会话中的SSH Client还是SSH Server(SSH Client指执行SSH命令的机器,下同)。
- 前两种把对转发端口的请求转发到目的机的特定端口、而最后一种则相当于一个代理功能——设置为该代理后会把对任意端口的请求转发到目的机的相应端口。
这里设想一种场景,假设有机器A、B、C、D,其间关系为:A、B间可互通,C、D间可互通,AB与CD间不能自由互通(因设置了防火墙、白名单等,只有B能通过SSH访问C、反之则不可。(想象AB、CD分别在不通的网段、两个网段间只有B能通过SSH访问到C且C只对B开放SSH的22端口)。
3.2.1、本地端口转发
命令: ssh -L <forward port>:<target host>:<target port> <SSH server addr>
- 四个参数分别表示转发的端口(注意非管理员无权绑定熟知端口0~1023)、目标host、目标主机端口、SSH server地址(如 zsm@10.5.6.47)。若target host与SSH Server是同一个机子则target host可写为 "localhost",原因见下面的原理部分
- 对于IPV4,前三个参数用冒号 ":" 分隔,对于IPv6则用斜杠 "/" 分隔。
- 为了允许其他机子连接转发端口(否则只有转发端口所在机器能连接该端口),可以加 -g 参数(listen 0.0.0.0:tarport和listen 127.0.0.1:tarport的区别);SSH连接默认会登录到SSH server(退出登录后转发功能会失效),可加 -fN 参数让命令在后台执行以避免登录到SSH server。
功能:将对SSH Client所在机器<forward port>端口的请求转发到指定机器的指定端口(即 <target host>:<target port> )
原理:SSH Client所在机器分配一个 socket 监听 <forward port> 端口,一旦此端口上有了连接,该连接就经安全通道转发出去,同时SSH server所在机器和 <target host>:<target port> 建立连接。(请求的内部走向是SSH Client -> SSH Server -> 目标机,返回时原路返回)
应用场景:使得“内网”(SSH Client所在的)能访问到不能直接访问的其他"网络"
示例:假设D上有个web服务监听8080端口,显然,A、B都无法直接访问到该服务但C可以。而B可以通过SSH访问C,此时在B上执行: ssh -g -fN -L :hostD: hostCSshAddr ,则A或B通过访问B的1000端口就能访问到D的web服务(内部走向是B -> C -> D)。
若没有-g参数,则A访问不了B的1000端口,只有B自己可以。
若web服务在SSH server上(即目标主机与SSH服务端是同一个),则命令可简为: ssh -g -fN -L :localhost: hostCSshAddr ,可见这里的localhost是相对于SSH server而言的。
3.2.2、远程端口转发
(与本地端口转发几乎一样,只不过转发端口在SSH Server且请求的内部走向相反)
命令: ssh -R <forward port>:<target host>:<target port> <SSH server addr> ,注:不支持 -g 参数
- 若target host与SSH Client是同一个机子则target host可写为 "localhost",原因见下面的原理部分
功能:将对SSH Server所在机器<forward port>端口的请求转发到指定机器的指定端口(即 <target host>:<target port> )
原理:SSH Server所在机器分配一个 socket 监听 <forward port> 端口,一旦此端口上有了连接,该连接就经安全通道转发出去,同时SSH Client所在机器和 <target host>:<target port> 建立连接。(请求的内部走向是SSH Server -> SSH Client -> 目标机,返回时原路返回)
应用场景:使得"外网"能访问到"内网"(SSH Client所在的)
示例:若上述web服务在A,显然,C、D无法直接访问该服务但B可以。而B可以通过SSH访问C,此时在B上执行: ssh -fN -R :hostA: hostCSshAddr ,则C可通过访问其1000端口就能访问到A的web服务(内部走向是C -> B -> A)。
注:远程端口转发不支持-g参数故这里无法像本地端口转发那样通过 -g 参数让D能访问到A的web服务。解决:在SSH Server(即C)的/etc/ssh/sshd_config添加一行并重启SSH服务: GatewayPorts yes
3.2.3、动态端口转发
命令: ssh -D <foward port> <SSH server addr> ,可用参数与本地端口转发的一样
功能及原理:与本地端口转发一样,将对SSH Client所在机器<forward port>端口的请求转发到SSH Server上,只不过设置时不用指定目的机器的host和port。SSH Client成为一个反向代理,应用设置代理为SSH Client后,应用发起请求时请求的内部走向也是SSH Client -> SSH Server -> 目标机,收到SSH Client转发来的请求时SSH Server会与该请求的目标机连接。SSH 动态端口转发是通过 Socks 协议实现的,创建动态端口转发时 SSH 服务器就类似一个 Socks 代理服务器,所以这种转发方式也叫 Socks 转发。
应用场景:
作为代理:把所有请求都转发到目的机,以突破防火墙等限制。
提高安全性:让那些不加密的网络连接,全部改走SSH连接,从而提高安全性。
示例: 作为反向代理——在本节首所述场景下,在B执行: ssh -g -fN -D hostCSshAddr ,相当于启动了个反向代理服务。之后在A或B上设置Sockets代理(如在浏览器设置Sockets代理),地址为 hostB:1000,则C、D上的服务均能被A或B访问到。如A访问服务hostD:8080,请求会通过 SSH Client B -> SSH Server C -> hostD:8080,由C完成对D的请求后原路返回结果。
注:
SSH 端口转发是通过 SSH 连接建立起来的,故必须保持这个 SSH 连接以使端口转发保持生效。一旦关闭了此连接,相应的端口转发也会随之关闭。
只能在建立 SSH 连接的同时创建端口转发,而不能给一个已经存在的 SSH 连接增加端口转发。
参考资料:
https://www.cnblogs.com/sparkdev/p/7497388.html ssh端口转发
http://www.ruanyifeng.com/blog/2011/12/ssh_port_forwarding.html
SSH使用小记的更多相关文章
- ssh学习小记
ssh 为Secure SHell 的缩写.OpenSSH: ssh协议的开源实现. SSH协议版本 v1: 基于CRC-32做MAC,不安全:man-in-middle v2:双方主机协议选择安全 ...
- SSH 正向/反向代理小记
上周因为玩耍Minecraft的原因,折腾了下ssh的正向.反向代理,不得不说,科技改变命运..了解了基础的用法之后,很多跨域的事情都可以通过代理解决,而且只需要ssh帐号权限即可. 那么就简单来介绍 ...
- ssh动态转发小记
ssh,一般常用来做远程登录管理,也就是连上远程机器,得到一个shell,然后交互式地在上面敲命令-看结果-再敲命令. 偶尔也会用在脚本里,做些自动化批处理上传下载的操作,但本质上也是用shell来执 ...
- 【日常小记】统计后缀名为.cc、.c、.h的文件数【转】
转自:http://www.cnblogs.com/skynet/archive/2011/03/29/1998970.html 在项目开发时,有时候想知道源码文件中有多少后缀名为.cc..c..h的 ...
- Ubuntu server搭建vsftpd小记
Ubuntu server中搭建vsftpd小记 <h1> 在Ubuntu server中安装vsftpd</h1> sudo apt-get install vsftpd & ...
- linux expect, spawn用法小记
linux expect, spawn用法小记_IT民工_百度空间 linux expect, spawn用法小记 版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://sys ...
- [转载]expect spawn、linux expect 用法小记
原文地址:expect spawn.linux expect 用法小记作者:悟世 使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄.收藏.可是为什么要这么写 ...
- Jenkins小菜初次使用小记
title: Jenkins自动集成小记 Jenkins是用来自动构建任务的,也许你还不知道什么叫自动构建任务,它的意思是可以针对某个任务进行自动化,比如你开发的某个软件,每次写完代码提交到githu ...
- NodeJS+Express+MySQL开发小记(2):服务器部署
http://borninsummer.com/2015/06/17/notes-on-developing-nodejs-webapp/ NodeJS+Express+MySQL开发小记(1)里讲过 ...
随机推荐
- mysql case when then else end 的用法
case when then end 改语句的执行过程是:将case后面表达式的值与各when子句中的值进行比较,如果两者相等,则返回then后的表达式的值,然后跳出case语 句,否则返回else子 ...
- IntelliJ IDEA配置Springboot2.x 通过devtools实现代码热部署,提高调试效率
1.pom.xml添加依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifa ...
- Android AsyncTask将讲解
原型:AsyncTask<Params, Progress, Result> Params 表示传入参数类型 Progress表示处理参数类型 Result表示返回类型 new Async ...
- 受欢迎的牛 [HAOI2006] [强连通] [传递闭包(划)]
Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛 A 认为牛 B受欢迎.这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A ...
- GMA Round 1 三视图
传送门 三视图 该几何体如图所示,是一个边长为$2\sqrt{3}$的正四面体,高是$h=2\sqrt{2}$,内切球半径是$r=\frac{h}{4}=\frac{\sqrt{2}}{2}$,则体积 ...
- iOS WKWebview 网页开发适配指南【转】
微信iOS客户端将于2017年3月1日前逐步升级为WKWebview内核,需要网页开发者提前做好网站的兼容检查和适配.如有问题,可参考文末联系方式,向我们咨询. 背景 WKWebView 是苹果在iO ...
- u-boot-2018-09 分析 v1
下载地址: https://pan.baidu.com/s/1YcQ1XpFyzmNcr1afw1RhgQ 或者:
- python测试开发django-56.模板渲染markdown语法+代码高亮
前言 上一篇已经实现在xadmin后台编辑markdown语法的文档,编辑完成之后发布博客,在前端html能把markdown语法显示出来. 主要思路是先从数据库把markdown的代码读出来,导入m ...
- 弄懂JDK、JRE和JVM到底是什么 关系区别
首先是JDKJDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK).在JDK的安装目录下有一个jre目录,里面有两个文件夹bin和lib,在这里可以认为bin ...
- Android: Avoid passing null as the view root
在做一个应用时把Android SDK从4.4换成6.0,使用LayoutInflater的inflate方法时出现以下情 LayoutInflater.inflate(int resource, V ...