zoukankan      html  css  js  c++  java
  • 图解再谈ssh port forwarding-ssh隧道技术

    https://www.ramkitech.com/2012/04/how-to-do-ssh-tunneling-port-forwarding.html

    https://www.cnblogs.com/popsuper1982/p/3875420.html

    本文我将谈到ssh是怎么工作的,到底什么是ssh tunneling隧道技术,ssh隧道到底有什么重要意义,以及如何搭建ssh tunnel.正常情况下,ssh server只要安装了,那么默认情况下就允许ssh tunneling.

    SSH tunneling(port forwarding)

    tunneling是这样一种概念:将一种网络协议报文(这里更多指应用层协议)封装到另外一个协议中传输,这里我们就是ssh,也就是说将其他协议的报文封装到ssh中,由于ssh本身是加密的,因此所有的应用层网络通信都是加密安全的. 在ssh tunneling的技术中,我们会绑定一个local port,并且所有targeted到这个local port的报文都将透明的加密并通过隧道转发到remote system,正因为如此,SSH tunneling也被称为端口转发。

    为什么需要ssh tunneling?

    SSH虽然对于管理远端系统是足够了,但是ssh并不足以用于访问所有远端系统所提供的服务。

    需要注意的是:在上面的3个系统中,ssh server daemon service都运行着并监听22端口,而防火墙允许使用ssh client连接这个22端口.

    在上面的网络架构中101可以和PrivateServer 102直接通信,因为两个系统都直接和internet相连接,但是101却不能和intranet 10.10.1.11通信,因为从101系统的角度来说,10.10.1.11是一个non routeable的IP地址,该IP地址本身只是一个local ip,而不是公网的IP,因此无法路由dest addr是该私有网络的报文.

    现在的需求是我希望从101访问到intranet 10.10.1.11的机器,怎么办?

    一个可行的方案是首先ssh登录到privateserver(102机器)然后从102再ssh到intranet 10.10.1.11上.嗯,这是一个办法,至少我们现在可以管理到10.10.1.11机器了,执行一些shell命令.但是问题是,如果10.101.1.11机器上也提供了其他的服务,比如VNC, apache web server, smtp, pop3, squid proxy等服务,我们如何从101机器上访问这些服务呢,比如在101的机器上使用firefox来访问10.10.1.11上的web server?仅仅使用ssh传统的log/shell就无法满足了。

    真正的解决方案就是使用:ssh tunneling或者说ssh port forwarding

    SSH是如何工作的?

    在terminal中,当我们敲入ssh someone@private-server.org时,terminal application将调用ssh client,ssh client则连接到private-server.org机器的22端口(由ssh server监听).然后client和server交换Identitiy,public key, cipher suite info并且在server端创建一个新的shell process.随后client和server之间就建立了安全的通道了,这样之后的所有command及response都通过这个secure channel来传递。

    比如当ssh连接建立后,我将执行ls命令。那么ls命令将由ssh client加密封装通过该通道发往server.server则解密取出命令'ls'并且在shell(该shell就是ssh链接创建时所创建的)中执行,所有的输出将被redirect到该隧道的另一端-ssh client上,最后ssh client则解密取出output消息打印在terminal application上。

    这里需要说明的是ssh本身只使用了22端口(也就是ssh server监听的那个端口)

    ssh tunneling

    ssh协议本身要求对远程机器上服务的访问请求是通过channels来传递的。一个ssh connection可以包含多个channels,这有点类似于有线电视同轴电缆上可以同时传输多个信道的电视节目一样。每一个channel则代表着单一的那个service.比如,你通过Net::ssh的方式激活了一个远程主机上的一个进程时,就将创建一个channel专门用于服务于那个invocation,和那个process有关的所有的input和output都将经由那个channel来传输.而ssh connection本身则管理着该connection中所有已开的channels上流动的packets.这也意味着,虽然我们只有一个ssh connection,但是我们却可以同时执行:运行新的进程,sftp下载文件,端口转发port forwarding等。一个channel就是一个流

    https://net-ssh.github.io/ssh/v1/chapter-3.html#s1

    通常情况下我们就是用shell channel.但是在ssh tunneling模式下,我们准备使用data channel.需要了解的基础概念是:在101机器上ssh client绑定了一个端口并且和server(102)建立了secure connection,并且创建一个data channel和一个shell channel(实际上我们可以通过-N选项来忽略shell channel的创建)。这样,在101机器上任何应用如果发送数据到那个端口(就是ssh client绑定的那个端口),那么ssh client将透明地截取数据加密后转发给server(应该是通过所谓shell channel,不确定).而在server上(102)则接收并且解密这个数据并且做本地调用(这块随后就将讨论)

    ssh tunneling types

     ssh提供3种类型的隧道, 

    • Dynamic Tunneling(SOCKS proxy)
    • Local Port Forwarding
    • Remote Port Forwarding

    Dynamic Tunneling(Socks proxy)

    ssh     -D 8080     ramki@192.168.56.102

    这里-D 8080可以解读为SOCKS V5 Proxy代理将在client side上绑定8080端口.

    使用Dynamic Tunneling可以解决 Websense blocks your intended sites: websense是一个局域网代理解决方案

    现在101的ssh client将在client side创建an一个SOCKS proxy server并且绑定一个local port 8080.随后使用ramki这个用户的信息去登录远程102服务器并且建立secure channel.

    随后client application比如firefox,chrome需要配置proxy使用SOCKS proxy server localhost:8080.然后在我们101机器的firefox地址栏输入http://localhost,尽管在我们的101机器上并没有任何web服务开启着,我们却可以看到来自server 102返回的web页面!!!(注意:在102机器和10.10.1.11上都有apache绑定在其80端口上提供服务,而101机器并无web服务运行)

    这到底发生了什么?

    由于我们配置了proxy在浏览器中,因此浏览器将所有的http请求(甚至是localhost本身的http请求)都会送往8080端口,而SOCKS proxy正在这里监听着8080端口,随后SOCKS proxy将会把我们的http request打包并且送给ssh client加密后送往server.在server端则解密并且extract出来http request。这样在server端,http request中的http://localhost/实际上上指向的是server机器本身,并且是80端口(因为http协议中如果不明确指明端口则意味着默认80端口)。因此server将invoke这个request,而我们的102机器中apache正好在监听这个80端口并且提供服务,因此返回页面内容并通过相同的secure channel返回到client side的应用(firefox)

    还有一点需要说一下,本来从client机器101上,10.10.1.11是不可路由的,但是现在如果在101机器firefox浏览器上输入http://10.10.1.11则可以正确访问到10.10.1.11这个机器上部署的apache服务!!原因是该请求实际上是由102这台ssh server代为请求的,而102是可以访问该10.10.1.11机器的哦!

    优势: 只要使用client机器上创建的proxy server就能够访问remote machine以及其身后子网机器上的任何服务;

    缺点:我们需要在client application上配置这个proxy,但是如果应用本身并不支持proxy的配置选项,则我们仍然无法通过这种方式来访问到对应的service。

    可以参考以下博客文章搭建自己的proxy server:

    https://bugthinking.com/bypass-internet-censorship-using-aws-and-shadowsocks/

    验证可用:

     随后必须使用firefox使能socks proxy,并且使用remote dns

    local port forwarding

    ssh   -L  8000:localhost:80     ramki@192.168.56.102

    注意这里的语法是: -L   <local port> : <remote hostname> : <remote service port> user@sshserver

    以上命令执行后,将在client side绑定了8000本地端口。任何发往8000端口的traffic将被redirect到ssh client(因为ssh client监听绑定了8000端口),随后加密送往server端,随后server将直接deliver数据到localhost的80端口.在Dynamic tunnel(SOCKS)模式下,server会检查packet并且决定我们要将该packet最终发往何处(比如,http://localhost则送往80, smtp则送往25)但是在local port forwarding模式下,目的地永远是在建立这个local port forwarding命令中指定的remote service port! <remote hostname> : <remote service port>

    这种模式下,101机器的firefox中不再需要配置proxy选项(如果有的话,你需要清除掉proxy配置),随后在地址栏输入 http://localhost:8000,那么http request将会送往local port 8000,随后redirect并送往server.server则直接将报文送往server 102机器的port 80(注意这里的host及port是由 <remote hostname> : <remote service port>决定的,也就是localhost=102,80为目标端口)

    如果你希望访问10.10.1.11上的http service则必须创建一个新的local port forwarding,也就是说local port forwarding是点对点一对一的!我们不能使用前面已经创建好的隧道,因为老的隧道总是指向localhost:80,也就是102这台机器的80端口!

    使用以下命令:

    ssh   -L  8000:10.10.1.11:80   ramki@192.168.56.102

    以上命令执行后,则101 localhost的8000端口将再被重定向到10.10.1.11:80这个机器,via(通由)192.168.56.102

    在firefox中,我们输入http://localhost:8000,那么我们就将访问到10.10.1.11的http service

    好处: 不必配置proxy

    缺点: 对于每个service我们都需要配置一个不同的Local port forwarding(即:对于192.168.56.102和10.10.1.11两台机器上的http service,我们需要分别创建两个local port转发隧道)

    下面是自己做实验验证的结果截图

    Remote Port Forwarding

    remote port forwarding和local port forwarding是类似的,但是区别在于,我们将在server端创建port forwarding(102机器),而不是在101 ssh client side上

    ssh    -R 8000:localhost:80       ramki@192.168.56.101

    这里非常重要的区别是:我们将从server连接到client,因此这里是ramki@192.168.56.101注意是101而不是102.(值得怀疑)当执行这条命令后将会连接到client并且在client side创建8000端口.

    随后client使用本地8000端口来连接server,就像是local port forwarding一样.

    为何remote port forwarding是重要的?

    一般来说,计算机会在NAT之后,因此从外部是无法访问到计算机的.

    windows上使用实例

     在windows机器上,如果希望运行ssh server,则有很多选择,比如winsshd,freesshd,openssh等。如果只使用ssh client,则可以使用putty.

    假设192.168.56.101机器上运行这windows系统,我们来演示如何使用ssh tunneling.打开putty并且输入host ramki@192.168.56.102并选择connection->ssh->tunnels,输入8080到source port并选择Dynamic,这就相当于启动了sock proxy等价于-D 8080命令

    如果希望使用local port forwarding则任意选择一个未使用的port 6000到source port并且在destination中输入localhost:80选择local模式,等价于-L 6000:localhost:80

    如果你希望访问10.10.1.11机器的远程桌面vnc,那么就创建一个local port forwarding,并且选择destination是10.10.1.11:5900,因为5900端口是11这台机器的vnc server监听的端口。随后使用任何vnc client,比如我们使用tightvnc client连接到local port 6000

  • 相关阅读:
    软件架构模式
    经济学基础
    使用vue-cli3新建一个项目,并写好基本配置
    vue+iview+less实现主题切换功能
    ivew table组件二次封装,解决slot-scope跨组件传递的问题
    vue-cli3使用less全局变量,不用每个组件引入less文件(亲测有效)
    vscode开发vue项目使用eslint+prettier格式化:保存时自动执行lint进行修复(升级篇,保存时可格式化模板和css)
    切换子路由时,父路由的组件会重新渲染
    更换路由时页面实现左右滑动的效果
    div设置为inline-block后,两个div之间有空隙
  • 原文地址:https://www.cnblogs.com/kidsitcn/p/11090252.html
Copyright © 2011-2022 走看看