一. 内网穿透

SSH 隧道常用于把本地服务映射到外网,通常把这种方法叫内网穿透。SSH 反向通道有以下可用场景等:

  • 开发微信公众号等应用时把本地服务映射到外网,加速调试流程.
  • 把你正在开发的本地服务分享给互联网上其它人访问体验.
  • 在任何地方通过互联网控制你家中在局域网里的电脑.

原理也比较简单, 这里不做详细介绍.

从外网访问内网的主机, 你所必须的是需要一个有ssh登录权限的公网主机。

步骤如下(将内网主机称作A,公网ssh主机地址为hostP ):

1. 建立隧道

在内网A上执行

ssh -NTf -R  [remoteListenIp:]:localhost: [userP@]hostP    #需要身份验证,根据你的情况:无密码、-i 秘钥文件、输入密码

其中remoteListenIp指在hostP上监听22222端口的ip,可以省略。在没有对hostP上的GatewayPorts参数进行设置时不起作用,默认只绑定到本地回环,这可能导致只能在hostP上才能访问自己的22222端口。

-f: 表示后台运行。

-N: 告诉SSH客户端,这个连接不需要执行任何命令(不打开远程shell),仅仅做端口转发。

-T:表示不为这个连接分配TTY。为了让hostP端的监听服务一直生效, 此选项时必须的, 否则在建立一次连接并退出时对应的 SSH 进程也会跟着退出(一次性).

-R: Reverse tunnel。

分别在两台主机上执行ps aux | grep ssh可以看到上述命名的ssh进程在后台运行.

查看hostP上端口是否监听:

方式一:ssh登录hostP,执行netstat -an | grep 22222  #查看监听的地址是127.0.0.1还是0.0.0.0(全部地址)

方式二:nmap -p 22222 hostP   #open或close状态

2. 穿越隧道

ssh -p  [userA@]hostP

在没有设置GatewayPorts时应该是拒绝访问,那可以先登录hostP,再从hostP登录A

ssh [userP@]hostP  ---->  ssh -p  [userA@]localhost

如果你想直接使用ssh -p 22222 [userA@]hostP 参考3.

3. 在hostP上/etc/ssh/sshd_config中添加一行GatewayPorts yes可以使hostP上的sshd服务监听所有ip,显示为0.0.0.0 或者GatewayPorts clientspecified

(注意在修改配置后重载ssh服务, 之后再次在在内网A上重新建立隧道)

参考man手册,ssh的-R参数、sshd_config的GatewayPorts说明:

-R

By default, the listening socket on the server will be bound to the loopback interface only. This may be overridden by specifying a bind_address.
An empty bind_address, or the address ‘*’, indicates that the remote socket should listen on all interfaces. Specifying a remote bind_address
will only succeed if the server’s GatewayPorts option is enabled (see sshd_config(5)). GatewayPorts Specifies whether remote hosts are allowed to connect to ports forwarded for the client. By default, sshd(8) binds remote port forwardings to the
loopback address. This prevents other remote hosts from connecting to forwarded ports. GatewayPorts can be used to specify that sshd should allow
remote port forwardings to bind to non-loopback addresses, thus allowing other hosts to connect. The argument may be “no” to force remote port
forwardings to be available to the local host only, “yes” to force remote port forwardings to bind to the wildcard address, or “clientspecified” to
allow the client to select the address to which the forwarding is bound. The default is “no”.

4. 自启动

SSH 隧道是不稳定的,在网络恶劣的情况下可能随时断开。如果断开就需要手动去本地开发机再次向外网服务器发起连接。
AutoSSH 能让 SSH 隧道一直保持执行,他会启动一个 SSH 进程,并监控该进程的健康状况;当 SSH 进程崩溃或停止通信时,AutoSSH 将重启动 SSH 进程。

使用AutoSSH 只需在本地开发机上安装,方法如下:

安装成功后,在本地开发机上执行:

autossh -N -R 8080:127.0.0.1:8080 username@12.34.56.78

就能完成和上面一样的效果,但本方法能保持 SSH 隧道一直运行。
可以看出这行命令和上面的区别在于把 ssh 换成了 autossh,并且少了 -f 参数,原因是 autossh 默认会转入后台运行。

5. ssh 保持连接

用 ssh 命令连接服务器之后,如果一段时间不操作,再次进入 Terminal 时会有一段时间没有响应,然后就出现错误提示:

Write failed: Broken pipe

只能重新用 ssh 命令进行连接。

解决方法

方法一:只需在客户端的 ~/.ssh/config 文件添加下面的配置(心跳包的频率):

注意config文件的权限要求是非owner(group和other成员)不能有写权限.

ServerAliveInterval 60

方法二:如果你不想在每个客户端进行设置,需在服务器的 /etc/ssh/sshd_config 中添加如下的配置:

ClientAliveInterval 60

配置之后需重启sshd服务, 这样所有客户端建立的连接均会生效.

方法三:临时方案. 如果你只想让当前的 ssh 保持连接,可以使用以下的命令:

$ ssh -o ServerAliveInterval=60 user@sshserver

二. ssh 跳板机 / 堡垒机

越过跳板机(堡垒机)登录开发机; PyCharm 跳板机登录

这是一般的内网环境的使用场景, 即先登录跳板机, 然后再从跳板机登录到内网的开发机. 为了加快我们登录的步伐, 将两步缩减为一步, 有以下两种简便方法:

1. 使用ssh的JumpHost功能. 在ssh的config文件(~/.ssh/config)中使用ProxyCommand调用netcat进行端口转发.

# 跳板机

Host hop

User hop_user
HostName hop
Port 222

# 开发机

Host x
User dev_user
HostName dev
Port 22
ProxyCommand ssh hop nc %h %p

# ProxyCommand: 登录hop之后再登录x

# 运行 ssh x 将直接登录开发机

2. 在跳板机上进行ssh端口转发.

ssh -g -L local_port:localhost:remote_port -f -N dev_user@dev

比如在跳板机上执行 ssh -g -L 22000:localhost:22 -f -N dev_user@dev 会在跳板机上监听22000端口, 并将接收到的ssh请求转发到开发机.

现在,我们可以在客户端直接登录我们的开发机了: ssh -p 22000 dev_user@dev

注意 -g 选项:  Allows remote hosts to connect to local forwarded ports.

没有该选项则无法远程连接跳板机上新开放的端口。

PyCharm的2018版中增加了对ssh config配置文件中ProxyCommand的支持,但是依然较难使用. 推荐使用第二种端口转发的形式.

这样在使用PyCharm等远程开发IDE时会方便不少.

三. ssh 示意图

参考链接

https://github.com/gwuhaolin/blog/issues/11

https://unix.stackexchange.com/questions/10428/simple-way-to-create-a-tunnel-from-one-local-port-to-another

https://unix.stackexchange.com/questions/115897/whats-ssh-port-forwarding-and-whats-the-difference-between-ssh-local-and-remot

ssh reverse tunnel的更多相关文章

  1. [daily] 比端口转发更高级的ssh device tunnel转发

    没有什么能够阻挡,你对自由的向往. 场景: 我有一台设备Server100,在某一个f复杂的内网里,需要多次ssh跳转可以访问到.但是它不能直接访问internet. 我现在需要在我的ssh路径上,搭 ...

  2. ssh的tunnel设置+autossh设置

    tunnel设置 一.说明 用于通过ssh转发数据 二.设置 编辑ssh server的'2Fetc/ssh/sshd_config 加入下面: #反向遂道 GatewayPorts  yes #正向 ...

  3. ssh的tunnel隧道打洞

    分正向和反向. 假设,本地机器可以ssh连上远程机器.本地机器在下面叫做SSHClient, 远程机器叫做SSHServer. 一. 正向代理(本地转发) 在SSHClient机上执行: : SSHS ...

  4. SSH Tunneling Explained

    转载: http://chamibuddhika.wordpress.com/2012/03/21/ssh-tunnelling-explained/ March 21, 2012 by Buddhi ...

  5. SSH做反向代理

    说实话,我对反向代理这个概念并不熟悉,只是感觉以下要做的事是一个代理的逆向过程,故借此名词一用. 问题场景是这样的:我有两套Linux集群的访问权限,分别为A和B,它们互相独立.其中A.B集群均能访问 ...

  6. 通过socks tunnel设置http代理

    1. 在服务器上使用ssh创建tunnel -f -C -q -N milton@112.34.113.35 # -D: 让ssh在指定的端口(-)上建立一个 SOCKS tunnel # -f: 让 ...

  7. ssh in depth

    前两天写了一篇关于ssh的相对比较入门的文章,重点介绍了ssh在免密登录场景下的应用. 本文试图对ssh更高级的话题做一下探讨,重点探讨一下ssh tunneling https://www.ssh. ...

  8. Gravitational Teleport简单使用

    使用官方提供的二进制包进行快速启动测试,详细细节还需要在学习 下载软件包 mac 系统 https://gravitational.com/teleport/download/ wget https: ...

  9. 【山外笔记-工具框架】SVN版本控制系统

    [山外笔记-框架工具]SVN版本控制系统 学习资料: 1.本文打印版下载地址:[山外笔记-框架工具笔记]SVN版本控制工具-打印版.pdf 2.SVN和TortoiseSVN在线中文文档:http:/ ...

随机推荐

  1. mysql 基本

    mysql -u root -p 输入密码进入数据库 show database; 查询当前库 use databasename 切换到某个库 show tables; 列出当前数据库的表 desc ...

  2. yii2 实战教程之如何安装

    作者:白狼 出处:http://www.manks.top/document/install.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  3. netty3升netty4一失眼成千古恨

    老项目是netty3的,本来想直接改到netty5,但是netty5居然是只支持jdk1.7,很奇怪jdk1.6和jdk1.8都不行..为了兼容jdk1.6加上netty4本来和netty5就差别不大 ...

  4. 区块链是伟大的,比特币则不然。《FinTech,金融科技时代的来临》。3星。

    本书讲技术给金融业带来的变革和可能的趋势.作者认为区块链是伟大的发明,因为他可以让金融交易免费且实时地进行.比特币则可能会被其他区块链技术取代.书中有至少一半的内容涉及到了区块链和比特币.总体评价3星 ...

  5. 旧文备份:CANopen协议PDO的几种传输方式

    (于2007.1.22) 由于PDO所传输的数据内容是无协议的且分配的标识符范围较SDO靠前,因此,其效率和优先级都是较高的,通常用于实时过程数据的传输. PDO是生产/消费类型的通讯方式,数据只有一 ...

  6. HOLOLENS程序发布,这个界面调用的图片

    SplashScreen.scale-200.png 1240 x 600

  7. http协议进阶(三)http报文

    一.报文流 http报文是在http应用程序之间发送的数据块(也可称为数据包).这些数据块以一些文本的元信息(meta-information)开头,描述了报文的内容及含义,后面跟着 可选的数据部分, ...

  8. c# 传递Null的string值导致的调用C++的dll报错 Attempted to read or write protected memory.

    c# 调用C++的dll报错 Attempted to read or write protected memory:   原因是:c# 传递Null的string值导致的,将Null改为string ...

  9. 【C#】【Thread】CountdownEvent任务并行

    System.Threading.CountdownEvent  是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定. CountdownEvent  专门用于以下情况:您必须使用 ...

  10. Linux 进程间通讯详解二

    消息队列 --消息队列提供了本机上从一个进程向另外一个进程发送一块数据的方法 --每个数据块都被认为有一个类型,接收者进程接收的数据块可以有不同的类型值 --消息队列也有管道一样的不足,就是每个消息的 ...