阅读 4634

我偷偷挖了一条网络隧道,差点被公司激活

(更多更好看文章,关注公众号: 编程三分钟 )

今天用公司环境在测试网络隧道,在写一半文章的时候突然老板来找我了,我真的好苦啊!

老板的聊天记录

告警邮件

自己好苦命,希望明天不要被怼的太惨。

好了,让我们开始今天的内容。 你是否常常遇到这些个麻烦,因为公司安全策略的问题,每次要通过跳板机而不能直接连开发环境,使用上面已经搭建好的数据库服务。为了方便发布,自己电脑上的服务别人,不能让开发环境的机器直接连上测试。还有我们在星巴克喝着咖啡连着免费wifi的时候,会不会网络请求都被黑客抓包下来?

概述

SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。但是,SSH 还同时提供了一个非常有用的功能,这就是端口转发。它能够将其他 TCP 端口的网络数据通过 SSH 链接来转发,并且自动提供了相应的加密及解密服务。这一过程有时也被叫做“隧道”(tunneling)。这是因为 SSH 为其他 TCP 连接提供了一个安全的通道,避免了用户名,密码以及隐私信息的明文传输。例如,Telnet,SMTP,LDAP 这些 TCP 应用。

如果工作环境中的防火墙限制了一些网络端口的使用,但是允许 SSH 的连接,那么也是能够通过将 TCP 端口转发来使用 SSH 进行通讯。总的来说 SSH 端口转发能够提供两大功能:

  • 加密 SSH Client 端至 SSH Server 端之间的通讯数据。
  • 突破防火墙的限制完成一些之前无法建立的 TCP 连接。

隧道

本地转发

当开发机的Mysql只能从跳板机连上,我怎么才能跳过跳板机来访问远程Mysql呢?

访问远程服务器的Mysql
如上图,我们要明确的是现在有三个角色,客户端(SSH Client)、跳板机(SSH Server)、和服务器。

客户端只能通过ssh连接到跳板机上,跳板机可以直接访问服务器的全部端口,服务器中安装了Mysql服务并监听了3306端口。

这个时候,我们肯定是要用本地转发来连接,命令规则如下

ssh -L [local host:]<local port>:<remote host>:<remote port> <SSH hostname>
复制代码

看起来非常的令人费解,不清楚的问题不过就是三个,what? where? how?

  • what : 使用本地转发,监听本地的某个端口,当应用访问这个端口的时候,ssh会将请求截取到,通过跳板机作为中间媒介,转发到服务器上。 服务器处理完成后,数据再原路返回完成整个链路。ssh服务在这个过程中完成了加密,转发,解密,通讯的操作。
  • where : 在客户端(也称本地、SSH Client)上做这个事情
  • how : 使用以下命令配置,就可以达到访问本地9527端口转发到服务器的3306端口啦
ssh -L 9527:服务器:3306 root@跳板机
复制代码

解释为,当访问本机的9527的端口时,被加密后转发到跳板机的ssh服务,服务器的3306端口

注意的点

  1. SSH 端口转发是通过 SSH 连接建立起来的,我们必须保持这个 SSH 连接以使端口转发保持生效。一旦关闭了此连接,相应的端口转发也会随之关闭。
  2. 我们只能在建立 SSH 连接的同时创建端口转发,而不能给一个已经存在的 SSH 连接增加端口转发。
  3. 好了,我们已经在本地 建立了端口转发,那么既然我们在监听本地的9527端口,那么其他机器也访问本地的9523端口会不会自动转发呢?比如能否新增加一台客户端2来直接连接客户端的9527 端口?答案是不行的,在主流 SSH 实现中,本地端口转发绑定的是 lookback 接口,这意味着只有 localhost 或者 127.0.0.1 才能使用本机的端口转发 , 其他机器发起的连接只会得到“ connection refused. ”。好在 SSH 同时提供了 GatewayPorts 关键字,我们可以通过指定它与其他机器共享这个本地端口转发。
ssh -g -L <local port>:<remote host>:<remote port> <SSH hostname>
复制代码
  1. 当然了,你可以随意的指定remote host,假如你要访问的服务就在跳板机上,因为防火墙又不能直接访问到,那么remote hostSSH hostname可以是同一台

远程转发

我的开发机上部署了一个mysql服务,我想回家以后还是连上我处于内网开发机上的mysql服务,这个时候我们怎么弄呢?

远程转发图示
我们需要借助一台公网的服务器讲远程的流量转发过来,由于安全策略内网机器可以连通外网机器,但是外网不能访问内网机器。我们只要转发远程的请求到正确的内网的服务上就可以了。它的命令格式是:

ssh -R [ssh server host:]<SSH server port>:<local host>:<local port> <SSH hostname>
复制代码
  • what :使用远程转发,监听公网服务器的某个端口,当应用访问这个端口的时候,ssh会将请求截取到,通过ssh客户端作为中间媒介,转发到真实提供服务的服务器上。 服务器处理完成后,数据再原路返回完成整个链路。
  • where : 在内网服务器上运行此命令
  • how :使用以下命令配置,就可以达到访问外网机器9527端口转发到内网服务器的3306端口啦
ssh -R 9527:内网机器:3306 root@公网机器
复制代码

让公网服务器监听9527端口的访问,如有访问,就加密后通过ssh服务转发请求到内网机器ssh客户端,再由内网机器ssh客户端解密后转发到内网机器3306端口。这听起来有点奇怪,因为这个时间内网服务器充当了两个角色,就是ssh客户端和server端。用下图的展示看起来更直观一点

有跳板机的远程转发
这个时候我们就可以在跳板机上使用命令

ssh -R 9527:内网机器:3306 root@公网机器
复制代码

这个时候就是让公网服务器监听9527端口的访问,如有访问,就加密后通过ssh服务转发请求到跳板机ssh客户端上,再由ssh客户端解密后转发到内网机器3306端口上。

注意的点

  1. 必须保持ssh client到ssh server的 SSH 连接以使端口转发保持生效。一旦关闭了此连接,相应的端口转发也会随之关闭。

  2. 我们只能在建立 SSH 连接的同时创建端口转发,而不能给一个已经存在的 SSH 连接增加端口转发。

  3. 对于远程转发来说,/etc/ssh/sshd_config里要把AllowTcpForwarding选项设置为yes,否则-R远程端口转发会失败。把/etc/sysctl.conf里的net.ipv4.ip_forward = 0设置为1

  4. 默认转发到远程主机上的端口绑定的是127.0.0.1,如要绑定0.0.0.0需要把/etc/ssh/sshd_config里的GatewayPorts选项设置为yes。这个选项如果由于权限没法打开也有办法,可配合ssh -L将端口绑定到0.0.0.0,如下

ssh -R 127.0.0.1:9527:内网机器:3306 root@公网机器
ssh -L 0.0.0.0:9527:127.0.0.1:9527 root@127.0.0.1
复制代码

本地转发与远程转发的区别与共同点

共同点:

  1. 都要保持ssh不要断掉
  2. 都是在建立链接的同时创建端口转发
  3. 都是转发请求
  4. 都是在ssh client上运行

区别:

  1. 本地转发是ssh client就是client,远程转发ssh client是server
  2. 本地转发是本地请求远程的服务,远程转发是远程请求本地的服务
  3. 实在理不清,听我的,转发是指转发请求,本地转发就是把本地的请求转发出去;远程转发就是把远程的请求转发过来。

动态转发

我有一台香港服务器能上外网,凭什么我自己不能上外网!还真就可以。

前面我们已经讨论过了本地转发,远程转发,但是前提都是要求有一个固定的应用服务端的端口号。那如果没有端口号怎么办?等等,什么样的应用会没有这个端口号呢?嗯,比如说用浏览器,比如说 MSN 等等。

同时当我们在一个不安全的 WiFi 环境下上网,用 SSH 动态转发来保护我们的网页浏览及 MSN 信息无疑是十分必要的。

让我们先来看一下动态转发的命令格式:

 ssh -D <local port> <SSH Server>
复制代码

动态转发
实际使用如下

ssh -qTfnN  -D 127.0.0.1:9527 root@香港服务器
复制代码

怎么使用

  1. 在浏览器里设置使用socks5代理127.0.0.1:9527,然后浏览器就可以访问host1所在网络内的任何IP了。推荐chrome浏览器switchyOmega插件设置为下就可以了。

switchyOmega
2. 如果是普通命令行应用,使用proxychains-ng,参考命令如下:

   brew install proxychains-ng
   vim /usr/local/etc/proxychains.conf # 在ProxyList配置段下添加配置 "socks5 	127.0.0.1 9527"
   proxychains-ng wget http://host2 # 在其它命令行前添加proxychains-ng即可
复制代码
  1. 如果是ssh,则用以下命令使用socks5代理:
   ssh -o ProxyCommand='/usr/bin/nc -X 5 -x 127.0.0.1:5000 %h %p' user@host2
复制代码

转发常用的参数

用法

ssh -qTfnN -D 127.0.0.1:12345 test@222.333.444.555
复制代码

-f 要求 ssh在执行命令前退至后台.它用于当ssh准备询问口令或密语,但是用户希望它在后台进行.该选项隐含了-n选项.

-N 不执行远程命令.用于转发端口.

-C 要求进行数据压缩 (包括stdin, stdout, stderr以及转发X11和TCP/IP连接 的数据).压缩算法和gzip(1)的一样,协议第一版中,压缩级别 “level” 用CompressionLevel选项控制.压缩技术在modem线路或其他慢速连接上很有用,但是在高速网络上反而 可能降低速度.可以在配置文件中对每个主机单独设定这个参数.

-g 允许远端主机连接本地转发的端口

-q 安静模式.消除所有的警告和诊断信息

-T 禁止分配伪终端

-n 把 stdin重定向到/dev/null (实际上防止从stdin读取数据). ssh在后台运行时一定会用到这个选项.它的常用技巧是远程运行X11程序.

引用

实战 SSH 端口转发

jeremy的技术点滴

ssh 端口转发

ssh隧道与代理

ssh 记ssh的几种玩法

(本故事纯属虚构,如有雷同纯属巧合)

如何使用Xshell在windows机器上动态转发

想不到大家这么热情,有的朋友问了,windows的机器中xshell可以配置代理吗?各种IDE,各种可视化工具是怎么用的,我来给大家说说。

首先创建一个连接到你的跳板机,将属性中的隧道(tunnel)中添加本地转发,将跳板机的1080端口映射到本地。这样子你可以在本地用代理软件控制你的流量到此端口就可以了。如下图:

本地转发

OK,然后本地下载一个代理软件,我比较喜欢用的是proxifier,这个软件非常的强大,只要添加代理规则,就可以讲流量分发到不同的地方去,比如下图:

上图有三条规则意思分别是:

规则二:访问的主机ip为10.77.0.*的时候触发此规则,使用socks5 转发到1080端口(这里看不到转发到哪个端口,编辑的时候就有让选了)

规则三:没有匹配到目标主机的,direct 直接连接

规则一:匹配到localhost一类的直接连接

应用程序字段也可以用正则表达式,比如你的是PyChram或者QQ你可以写成PyChram*; QQ*,具体看你的进程名。

忽略我知乎上自动加的水印,实在懒得改了。

关注下面的标签,发现更多相似文章
评论