ecure Network (ssh端口映射)-----图详细可以使用

2011-08-21 14:54:44|  分类:rhel_ssh|字号订阅

实战 SSH 端口转发

https://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/

SSH的端口转发:本地转发Local Forward和远程转发Remote Forward

关于使用ssh portforwarding来进行×××的操作,网络上已经有很多很好的文章,我在这里只是画两个图解释一下。

首先要记住一件事情就是:

SSH 端口转发自然需要 SSH 连接,而 SSH 连接是有方向的,从 SSH Client 到 SSH Server 。

而我们所要访问的应用也是有方向的,应用连接的方向也是从应用的 Client 端连接到应用的 Server 端。比如需要我们要访问Internet上的Web站点时,Http应用的方向就是从我们自己这台主机(Client)到远处的Web Server。

如果SSH连接和应用的连接这两个连接的方向一致,那我们就说它是本地转发。

ssh -L <local port>:<remote host>:<remote port> <SSH hostname>
SSH的端口转发_Internet


如果SSH连接和应用的连接这两个连接的方向不同,那我们就说它是远程转发。

ssh -R <local port>:<remote host>:<remote port> <SSH hostname>
SSH的端口转发_Internet_02


本地转发在本地这台机器上监听一个端口,然后所有访问这个端口的数据都会通过ssh 隧道传输到远端的对应端口上,下面是例子。

本地端口转发绑定的是 lookback 接口,这意味着只有 localhost 或者 127.0.0.1 才能使用本机的端口转发 , 其他机器发起的连接只会得到“ connection refused. ”。要想让其他机器也能共享这个隧道来转发的话需要在配置文件中使用GatewayPorts 关键字,或者直接命令行下使用"-g"参数。

另外本地转发命令中的 <remote host> 和 <SSH hostname> 可以是不同的主机。

SSH的端口转发_主机_03


远程转发与本地转发正好相反,打开ssh隧道以后,在远端服务器监听一个端口,所有访问远端服务器指定端口都会通过隧道传输到本地的对应端口上,下面是例子。

SSH的端口转发_主机_04


这里是一篇很好的介绍SSH PortForwarding的文章http://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/


可以将远端服务器一个端口remote_port绑定到本地端口port,其中-C是进行数据压缩,-f是后台操作,只有当提示用户名密码的时候才转向前台。-N是不执行远端命令,在只是端口转发时这条命令很有用处。-g 是允许远端主机连接本地转发端口。-R表明是将远端主机端口映射到本地端口。如果是-L,则是将本地端口映射到远端主机端口。

ssh的三个强大的端口转发命令:

转发到远端:ssh -C -f -N -g -L 本地端口:目标IP:目标端口 用户名@目标IP

转发到本地:ssh -C -f -N -g –R 本地端口:目标IP:目标端口 用户名@目标IP

ssh -C -f -N -g -D listen_port user@Tunnel_Host

-C:压缩数据传输。

-f :后台认证用户/密码,通常和-N连用,不用登录到远程主机。

-N :不执行脚本或命令,通常与-f连用。

-g :在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。

-L 本地端口:目标IP:目标端口

将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有 root 才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport

-R本地端口:目标IP:目标端口

将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 工作原理是这样的, 远程主机上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有用 root 登录远程主机才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport

-p :被登录的ssd服务器的sshd服务端口。

-D port

指定一个本地机器 “动态的'’ 应用程序端口转发. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持 SOCKS4 协议, 将充当 SOCKS4 服务器. 只有 root 才能转发特权端口. 可以在配置文件中指定动态端口的转发.

应用举例

1.将发往本机的80端口访问转发到174.139.9.66的8080端口

ssh -C -f -N -g -L 80:174.139.9.66:8080     master@174.139.9.66

2.将发往174.139.9.66的8080访问转发到本机的80端口

ssh -C -f -N -g -R 80:174.139.9.66:8080            master@174.139.9.66


-N - 不使用Shell窗口,纯做转发的时候用,如果你在映射完成后继续在服务器上输入命令,去掉这个参数即可

例子A:我们想远程管理服务器上的MySQL,那么使用下面命令

ssh -L 3306:127.0.0.1:3306   user@emlog-vps    -N 

运行这个命令之后,ssh将会自动将服务器的3306映射到本机的3306端口,我们就可以使用任意MySQL客户端连接 localhost:3306即可访问到服务器上的MySQL了。



例子B:一次同时映射多个端口

ssh -L 8888:www.host.com:80 -L 110:mail.host.com:110 -L    25:mail.host.com:25 user@host -N  

这个命令将自动把服务器的80,110,25端口映射到本机的8888,110和25端口 以上命令在ubuntu 9.10 上测试通过...


端口映射让外部用户同时访问内部多个应用


如下图所示,这是企业部署NAT服务器的典型案例。如果现在企业内部有两台服务器,分别为WEB服务器(192.168.0.3)与ERP服务器(192.168.0.2)。现在企业想让出差在外的员工,也可以通过互联网访问企业内部的这两个应用,该如何设计呢?

SSH的端口转发_主机_05

 一、基于端口访问的一般原理。

  在讲解NAT服务器的具体端口映射配置之前,笔者觉得读者有必要先了解一下基于端口访问的一般原理。这有利于读者了解下面的具体配置。下面笔者以员工访问WEB服务器为例,谈谈基于端口访问的基本步骤。假设现在某个用户需要访问WEB服务器,则客户端的浏览器(假设采用的端口为3000)与WEB服务器(假设采用的端口为80)是如何来进行通信的呢?

  第一步:发起连接请求。当用户需要查看公司网页时,用户所用的主机会像WEB服务器发送请求。在这个发起请求的过程中,会有一些参数传递。如在发送请求的过程中,用户所用的主机需要知道WEB服务器的IP地址、所采用的协议(HTTP)等。另外就是两个端口信息。一是用户浏览器所用的端口,即为3000。二是WEB服务器网站所用的端口(如果采用的是HTTP服务,则默认为80端口)。

  第二步:WEB服务器转发请求。当服务器接受到这个请求后,会分析数据包。他经过分析包发现,这个请求是要求端口为80的应用软件来负责的。服务器确定了负责人之后,就会把这个请求转发给具体的负责人,即WEB应用服务器来处理。

  第三步:服务器会把从WEB应用服务那边反馈回来的网页传送给用户所用的计算机。在传送的时候,其也会制定要把这个网页给你的那个3000端口(浏览器)对应的应用软件。

  第四步:用户的计算机收到数据包之后,也会对这个数据包进行分析,来判断需要把这个数据包转发给哪个端口(应用服务)。分析后发现是转交给3000端口的,就会把这个数据包转发给浏览器。

二、基于端口映射的NAT服务器配置。

  其实基于端口映射的NAT服务器其工作原理就跟上面这个基于端口访问的工作过程类似。只是这里的NAT服务器就相当于用户主机,而用户相当于内部的服务器。由于用户需要通过外网访问企业内部应用的话,通常情况下要求内网服务器也要求有合法的外网IP。只有私网IP地址的服务器是无法直接跟外部客户进行通信的。为此,如果没有端口映射的话,用户如果要同时访问内部的WEB服务器与ERP服务器,则就需要有两个公网IP地址。但是,大家都知道现在公网IP地址严重缺乏。在没有足够多的IP地址的情况下,该如何实现这种需求呢?那就知道通过端口映射来完成。

  如上图所示,用户需要访问企业内部的WEB服务与ERP服务器,他只需要知道NAT服务地址与WEB服务器与ERP服务器所采用的端口即可。如果

WEB服务器采用的端口为80,

ERP服务器所采用的端口为5050。

而NAT服务器的IP地址假设为202.96.92.100的话,


那么当用户访问WEB服务器时,只需要输入http:// 202.96.92.100即可。由于HTTP协议默认采用的是80端口,故这里不用配置端口号。如果WEB服务器中把这个端口改为了3000,则在访问的时候就需要使用http:// 202.96.92.100:3000(地址+端口号)的形式了。用户要访问内部的ERP服务器也是类似的,只要把NAT服务器的地址以及ERP服务器所采用的端口在客户端上进行配置即可。

  可见通过NAT服务器的端口映射功能,可以让外部用户同时访问企业内部的WEB服务器与ERP服务器。

那要实现这个需求具体该如何配置呢?

  NAT服务器让内部的局域网用户可以连接到互联网,以便用户能够收发互联网邮件、浏览互联网上的网站等等。但是默认情况下外部用户是不能够访问内部的服务器。如果需要实现以上功能的话,就需要进行专门的配置。

  如上图中,

内部局域网计算机(192.168.0.2)为WEB服务器,其采用的端口为80。

如果现在外部用户需要访问这个WEB服务器站点,则用户只知道这个WEB服务器的地址为202.96.92.100(NAT服务器的地址)。

而WEB服务器默认采用的端口为80。当外部用户通过浏览器访问企业内部的WEB服务器时,

他会在浏览器中输入http:// 202.96.92.100路经来连接网站。

NAT服务器会将此请求发送给内部的计算机WEB服务器(192.168.0.2),并由WEB服务器将这个请求转发给端口为80的软件来负责。WEB服务器会将网页传送给NAT服务器,再由NAT服务器负责将网页传送给外部用户的计算机。

如果用户要访问内部的ERP服务器,其过程也是如此。

那么现在的问题是,NAT服务器怎么判断要把用户HTTP请求发送给服务器(192.168.0.2)而不是发送给(192.168.0.3)呢?

  这主要是根据端口来判断的。也就是说在NAT服务器中有一个端口映射的规则,只要用户访问的目的端口是80,就把这个请求转发给WEB服务器;若请求的端口是5050,则就把这个请求发送给ERP服务器。这就是端口映射的实质。了解这个内容之后,那么了解下面的配置也就简单多了。打开路由和远程访问主控制窗口,选择要配置的服务器。然后选择IP路由选择、NAT/基本防火墙。并双击右方对外连接的网络接口(注意这里不要选择连接内网的网络接口),选择服务和端口标签。然后直接从服务列表中选取要对外开发的服务,如选择WEB服务器。在公用地址中选择在此接口,表示由互联网服务提供商指派的NAT服务器的公网IP地址。然后再设置,如果把这个服务请求转发给内部的IP地址为192.168.0.2的WEB服务器。通过这个简单的配置,就实现基于端口的映射。


三、改善NAT服务器的性能与便利性。

  可见这个端口映射配置是很简单的。但是其难点在于如何提高这个NAT服务器的性能,如何让用户使用的更加方便。这是网络管理员所需要考虑的。对此笔者有如下几个建议可供大家参考。

  1、利用域名来代替IP地址。当用户访问企业内部的网站服务器时,如果让他们输入服务器的IP地址,对普通用户来说可能有点难度。要记住这202.96.92.100十一个没有丝毫关系的数字有很大的难度。如果能够把这个IP地址转换为有实际意义的网址那就最好了。在企业内部,可以自己部属一个DNS服务器,把IP地址转换为网址。那么内部员工可以直接通过网址来访问WEB服务器。但是在互联网上,企业可不能自己随便定义域名。为了提高用户访问的便捷性,企业网络管理员最好能够像当地的域名注册机构,申请一个合适的域名并关联到自己的NAT服务器公网IP地址。那么以后外部用户访问内部WEB服务器时,只需要输入像新浪那样的地址就可以了。而不用输入这些难以记忆的地址。

  2、如果企业可以申请到多个IP地址的话,那么最好能够分开来部署。即企业可以申请两个ADSL帐号。其中一个专门用来连接内部的服务器;而另外一个用来内部员工跟互联网的通信。这么做主要是为了减轻NAT服务器的压力,提高其性能。如企业只有一个ADSL帐号的话,那么无论是外部用户访问企业内部服务器;还是企业内部员工访问互联网,其数据流都要通过这台NAT服务器来处理。为此,如果企业数据流量比较大或者NAT服务器配置不怎么理想的话,那么很可能这个NAT服务器就成为了企业网络访问的瓶颈资源。如果把他们分开,则可以减轻NAT服务器的压力,提高外部用户访问企业内部服务器的效率。

  3、配置合适的ICMP数据包策略,以加强阻挡黑客利用ICMP的攻击行为。使用ICMP攻击的原理实际上就是通过Ping大量的数据包使得NAT服务器的CPU使用率居高不下而崩溃。一般情况下黑客通常在一个时段内连续向计算机发出大量请求而导致CPU占用率太高而死机。而且会使用多台肉鸡同时向NAT服务器发送数据包。基于ICMP的攻击可以分为两大类,一是ICMP攻击导致拒绝服务;另外一个是基于重定向的路由欺骗技术。无论是哪一类攻击,都会给NAT服务器产生致命的影响。为此为了NAT服务器的安全,最好配置合适的ICMP包策略。如可以拒绝响应别人的ICMP请求。如此攻击者就无法对NAT服务器发起ICMP攻击了。


SSH隧道与端口转发及内网穿透

大家都知道SSH是一种安全的传输协议,用在连接服务器上比较多。不过其实除了这个功能,它的隧道转发功能更是吸引人。下面是个人根据自己的需求以及在网上查找的资料配合自己的实际操作所得到的一些心得。

SSH/plink命令的基本资料:

首先,认识下这三个非常强大的命令:

ssh -C -f -N -g -L listen_port:DST_Host:DST_port user@Tunnel_Host
ssh -C -f -N -g -R listen_port:DST_Host:DST_port user@Tunnel_Host
ssh -C -f -N -g -D listen_port user@Tunnel_Host

相关参数的解释:
-f Fork into background after authentication.
后台认证用户/密码,通常和-N连用,不用登录到远程主机。

-L port:host:hostport
将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有 root 才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport

-R port:host:hostport
将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 工作原理是这样的, 远程主机上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有用 root 登录远程主机才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport

-D port
指定一个本地机器 “动态的’’ 应用程序端口转发. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持 SOCKS4 协议, 将充当 SOCKS4 服务器. 只有 root 才能转发特权端口. 可以在配置文件中指定动态端口的转发.

-C Enable compression.
压缩数据传输。

-N Do not execute a shell or command.
不执行脚本或命令,通常与-f连用。

-g Allow remote hosts to connect to forwarded ports.
在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。注:这个参数我在实践中似乎始终不起作用。

以上摘录自:http://chenweiguang.blogspot.com/2009/03/ssh.html

建立本地SSH隧道例子

在我们计划建立一个本地SSH隧道之前,我们必须清楚下面这些数据:

  1. 中间服务器d的IP地址  

  2. 要访问服务器c的IP地址  

  3. 要访问服务器c的端口

现在,我们把上面这张图变得具体一些,给这些机器加上IP地址。并且根据下面这张图列出我们的计划:

SSH的端口转发_主机_06


  1. 需要访问234.234.234.234的FTP服务,也就是端口21  

  2. 中间服务器是123.123.123.123

现在我们使用下面这条命令来达成我们的目的(192.168.0.100上执行)

1.ssh -N -f   -L    2121:234.234.234.234:21    123.123.123.123

2.ftp://localhost:2121        # 现在访问本地2121端口,就能连接234.234.234.234的21端口了

这里我们用到了SSH客户端的三个参数,下面我们一一做出解释:

  • -N 告诉SSH客户端,这个连接不需要执行任何命令。仅仅做端口转发  

  • -f 告诉SSH客户端在后台运行  

  • -L 做本地映射端口,被冒号分割的三个部分含义分别是  

    • 需要使用的本地端口号

    • 需要访问的目标机器IP地址(IP: 234.234.234.234)  

    • 需要访问的目标机器端口(端口: 21)


  • 最后一个参数是我们用来建立隧道的中间机器的IP地址(IP: 123.123.123.123)


我们再重复一下-L参数的行为。-L X:Y:Z的含义是,将IP为Y的机器的Z端口通过中间服务器映射到本地机器的X端口。

在这条命令成功执行之后,我们已经具有绕过公司防火墙的能力,并且成功访问到了我们喜欢的一个FTP服务器了。

如何建立远程SSH隧道

通过建立本地SSH隧道,我们成功地绕过防火墙开始下载FTP上的资源了。那么当我们在家里的时候想要察看下载进度怎么办呢?大多数公司的网络是通过路由器接入互联网的,公司内部的机器不会直接与互联网连接,也就是不能通过互联网直接访问。通过线路D-B-A访问公司里的机器a便是不可能的。也许你已经注意到了,虽然D-B-A这个方向的连接不通,但是A-B-D这个方向的连接是没有问题的。那么,我们能否利用一条已经连接好的A-B-D方向的连接来完成D-B-A方向的访问呢?答案是肯定的,这就是远程SSH隧道的用途。

与本地SSH一样,我们在建立远程SSH隧道之前要清楚下面几个参数:

  • 需要访问内部机器的远程机器的IP地址(这里是123.123.123.123)  

  • 需要让远程机器能访问的内部机器的IP地址(这里因为是想把本机映射出去,因此IP是127.0.0.1)  

  • 需要让远程机器能访问的内部机器的端口号(端口:22)

在清楚了上面的参数后,我们使用下面的命令来建立一个远程SSH隧道

1.ssh -N -f -R 2222:127.0.0.1:22      123.123.123.123

现在,在IP是123.123.123.123的机器上我们用下面的命令就可以登陆公司的IP是192.168.0.100的机器了。

1.ssh -p 2222 localhost

-N,-f 这两个参数我们已经在本地SSH隧道中介绍过了。我们现在重点说说参数-R。该参数的三个部分的含义分别是:

  • 远程机器使用的端口(2222)  

  • 需要映射的内部机器的IP地址(127.0.0.1)  

  • 需要映射的内部机器的端口(22)

例如:-R X:Y:Z 就是把我们内部的Y机器的Z端口映射到远程机器的X端口上。

建立SSH隧道的几个技巧

自动重连

隧道可能因为某些原因断开,例如:机器重启,长时间没有数据通信而被路由器切断等等。因此我们可以用程序控制隧道的重新连接,例如一个简单的循环或者使用 djb’s daemontools . 不管用哪种方法,重连时都应避免因输入密码而卡死程序。关于如何安全的避免输入密码的方法,请参考我的 如何实现安全的免密码ssh登录 。这里请注意,如果通过其他程序控制隧道连接,应当避免将SSH客户端放到后台执行,也就是去掉-f参数。

保持长时间连接

有些路由器会把长时间没有通信的连接断开。SSH客户端的TCPKeepAlive选项可以避免这个问题的发生,默认情况下它是被开启的。如果它被关闭了,可以在ssh的命令上加上-o TCPKeepAlive=yes来开启。

另一种方法是,去掉-N参数,加入一个定期能产生输出的命令。例如: top或者vmstat。下面给出一个这种方法的例子:

1.ssh -R 2222:localhost:22 123.123.123.123 "vmstat 30"

检查隧道状态

有些时候隧道会因为一些原因通信不畅而卡死,例如:由于传输数据量太大,被路由器带入stalled状态。这种时候,往往SSH客户端并不退出,而是卡死在那里。一种应对方法是,使用SSH客户端的ServerAliveInterval和ServerAliveCountMax选项。 ServerAliveInterval会在隧道无通信后的一段设置好的时间后发送一个请求给服务器要求服务器响应。如果服务器在 ServerAliveCountMax次请求后都没能响应,那么SSH客户端就自动断开连接并退出,将控制权交给你的监控程序。这两个选项的设置方法分别是在ssh时加入-o ServerAliveInterval=n和-o ServerAliveCountMax=m。其中n, m可以自行定义。

如何将端口绑定到外部地址上

使用上面的方法,映射的端口只能绑定在127.0.0.1这个接口上。也就是说,只能被本机自己访问到。如何才能让其他机器访问这个端口呢?我们可以把这个映射的端口绑定在0.0.0.0的接口上,方法是加上参数-b 0.0.0.0。同时还需要打开SSH服务器端的一个选项-GatewayPorts。默认情况下它应当是被打开的。如果被关闭的话,可以在/etc /sshd_config中修改GatewayPorts no为GatewayPorts yes来打开它。

通过SSH隧道建立SOCKS服务器

如果我们需要借助一台中间服务器访问很多资源,一个个映射显然不是高明的办法(事实上,高明确实没有用这个方法)。幸好,SSH客户端为我们提供了通过SSH隧道建立SOCKS服务器的功能。

通过下面的命令我们可以建立一个通过123.123.123.123的SOCKS服务器。

1.ssh -N -f -D 1080 123.123.123 # 将端口绑定在127.0.0.1上

2.ssh -N -f -D 0.0.0.0:1080 123.123.123.123 # 将端口绑定在0.0.0.0上

通过SSH建立的SOCKS服务器使用的是SOCKS5协议,在为应用程序设置SOCKS代理的时候要特别注意。

以上摘录自:http://blog.jianingy.com/content/…

@@@@@@@@@@@@@@@@@@@@@@@@@@@

1 > 反向隧道技术

情景:节假日需要回公司加班。但是公司是内网,使用NAT,所以没办法连回去。

现在公司机器(LAN_ip)上执行

ssh -NfR 2222:localhost:22 home_ip

-R : 建立反向连接 将 home_ip port转发

现在,到home_ip上面
ssh localhost -p 2222
就跑在NAT后面的公司机器。就是后门了。灰鸽子木马用的也是反向链接。

Destination (LAN_ip) <- |NAT| <- Source (home_ip)

2>端口转发

情景:本机不允许访问www.xxx.com这个网站,但是远程主机(remote_ip)可以。

ssh -f -N -L 31609:www.xxx.com:80 user@remote_ip

现在我们就可以在本地打开 http://localhost:31609 访问www.xxx.com了。

3> SOCKS代理

情景: 本机不允许访问某些网站,但是远程主机(remote_ip)可以,并且公司没有组织你连接remote_ip。

ssh -NfD 8888 user@remote_ip

现在在浏览器socks 5 proxy设置为localhost:8888,所有之前无法访问的网站现在都可以访问了。

@@@@@@@@@@@@@@@@@@@

古人以“夜不闭户”、“路不拾遗”来形容大治之世。他们认为大治时,人们的道德水平已经很高了。而早期Internet的形成似乎也是符合这种思想的。Internet的初衷是相互信任和相互分享,它的这种“信任”建立在“大治”甚至“天下大同”的假想上。随着互联网的商业化和平民化,Internet的安全性就显得越来越脆弱了,不仅网络攻击、网络诈骗盛行,也有一些网络管理者肆意检测、更改、阻断用户通信的行为SSH的一些特性在很多场合可以解决这些问题。

ssh的基本用法在命令行也强大之ssh一文中做了最基本的介绍。ssh是安全的远程登录工具,在与远程主机进行交互时,ssh协议把原始数据进行了加密并压缩,从而保证了数据在网络传输过程的安全。利用这一原理,我们也可以用ssh把其它的明文传输的TCP数据流通过ssh的连接传输,这就是本文要讲到的ssh转发/隧道技术。下图表示一个ssh连接(图片来自http://www.ssh.com)

SSH的端口转发_Internet_07

ssh的转发有四类:远程转发、本地转发、动态转发和X转发。把TCP流重定向到ssh连接叫做“转发”,这个ssh连接叫做“隧道”。

假设场景:受限网络内主机A,受限网络防火墙F,受限网络外主机B,受限网络外主机C、D、E。用户为主机A的管理者且拥有主机B的ssh账号,B、C、D、E可以正常连接。因为防火墙F的策略,A与C、D、E完全不能连接,A与B受限连接(当A与B的连接内有关键字“SB”则阻断连接,且只能由A与B连接,不能由B主动连接,可类比为NAT)。
下图为场景图(用Dia v0.96.1绘制)

SSH的端口转发_Network_08

一、远程转发

将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 工作原理是这样的, 远程主机上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有用 root 登录远程主机才能转发特权端口.--摘自ssh的中文Manual
命令格式为:

?[Copy to clipboard]View Code BASH
ssh-R ::

假设主机A提供了HTTP服务,即在受限网络内部可以访问的网页服务器。但这个服务因为防火墙策略或者NAT路由的原因导致在Internet无法访问。那么我们就可以将本地的HTTP服务远程转发到Internet上的主机B

?[Copy to clipboard]View Code BASH
ssh-fNgR80:localhost:80 root@host-B

然后在Internet上可以通过访问 http://host-B来访问主机A上的HTTP服务了

如果没有主机B的root账号,则只能远程转发到1024以后的端口号

?[Copy to clipboard]View Code BASH
ssh-fNgR8080:localhost:80 lige@host-B

然后在Internet上可以通过访问http://host-B:8080来访问主机A上的HTTP服务。
值得注意的是搭建了wordpress的主机只能运行在80端口,如果转发后的端口不是80,那么将无法使用,这应该算是wp的bug吧

而且因为主机A到主机B之间是通过隧道连接的,即使网页中含有关键字“SB”,也无法被大防火墙检测到(泪流满面,终于讲到关键了)

附加参数简要说明:

?[Copy to clipboard]View Code BASH
-N      不执行远程命令. 用于转发端口.  -n      把 stdin 重定向到 /dev/null (实际上防止从 stdin 读取数据).  ssh在后台运行时一定会用到这个选项. 它的常用技巧是远程运行 X11 程序.  -f      要求 ssh 在执行命令前退至后台. 它用于当 ssh 准备询问口令或密语,但是用户希望它在后台进行. 该选项隐含了 -n 选项. 在远端机器上启动X11 程序的推荐手法就是类似于 ssh-f host xterm 的命令.  -C      要求进行数据压缩  -g      允许远端主机连接本地转发的端口

关于建立隧道和使用隧道的网络原理,见文章末尾

二、本地转发

将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和 host的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有 root 才能转发特权端口. --摘自ssh的中文Mannul

它的命令格式为

?[Copy to clipboard]View Code BASH
ssh-L ::

和远程转发原理类似但方向相反。假设主机B有HTTP服务,但因为受限网络内其它主机因憎恶“大防火墙”F而不愿意直接访问主机B(这种心理我也有)。那就可以通过本地转发了

?[Copy to clipboard]View Code BASH
ssh-fNgL80:localhost:80 root@host-B

因为和远程转发类似,后面就不再详述。

三、动态转发

指定一个本地机器 “动态的” 应用程序端口转发. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接,该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持 SOCKS 协议, ssh 将充当 SOCKS 服务器.只有 root 才能转发特权端口. --摘自ssh的中文manual

可以这样理解,远程转发和本地转发都是在隧道上传输一个服务,比如例子中的HTTP数据流。而动态转发则是为了在隧道上传输多种不确定的网络服务。它的表现就把远端ssh服务器当作了一个安全的代理服务器。

命令格式为

?[Copy to clipboard]View Code BASH
$ ssh-D

假设主机A想要访问受限网络所限制访问的主机C、D、E等,或者想要访问主机B上的“SB”内容。则可有D选项建立动态隧道

?[Copy to clipboard]View Code BASH
ssh-CfNg-D8888 lige@host-B

然后你就有了一个安全的socks 5代理。这个代理ip是127.0.0.1,端口为刚才指定的8888。如何使用socks 5代理在本文就不再讲了。大防火墙可能还存在一些技术来防止socks 5代理,可以参考socks代理的远端DNS解析一文

还有一个plink工具,包含在PuTTY软件包,可以在windows和linux下使用,它的格式为:

?[Copy to clipboard]View Code CMD
PLINK.EXE -C -D 127.0.0.1:7777 -N -pw SSH密码 SSH用户名@SSH的IP地址

四、X转发

X转发是一个令人惊奇但实际上用处不大的功能。因为我所能管理的远端主机都是无图形界面的,所以本部分内容我不保证正确。

大家都知道GUI软件与X之间也是通过TCP连接的,所以X转发与其它转发也没有本质区别,甚至它简单得都不应该和其它几种转发相提并论。X转发用的选项为”-X”

首先要在客户端指定X Server的位置

?[Copy to clipboard]View Code BASH
exportDISPLAY=:.

然后执行

?[Copy to clipboard]View Code BASH
ssh-X lige@hot-B

补充:可能的问题:

1. ssh的基本用法
http://blog.lilinux.net/2010/02/command-ssh/以及ssh的man文档

2. windows下的ssh客户端
PuTTY和其中的plink

3. 如何查看隧道是否建立完善
查看进程:

?[Copy to clipboard]View Code BASH
ps aux |grepssh

查看端口:

?[Copy to clipboard]View Code BASH
netstat-ntl

4. 因为F,连接还是不稳定,隧道经常无法使用
去除-N,-n,-f选项,进入远程shell,输入一些需要频繁交互数据的命令,使连接一直处于活动状态。比如

?[Copy to clipboard]View Code BASH
top

我更推荐用这样的命令,对系统的负载消耗更小(而且更加美观)

?[Copy to clipboard]View Code BASH
watch -n1"date"

5. 更多的实例
本文写的例子都是假设场景,近期将写一个实例应用。预计网址为http://blog.lilinux.net/2010/02/ssh-instance/


附ssh隧道原理


对网络原理不太懂或不感兴趣的可以忽略此部分

总的来说:Tunnel实际上是一个TCP连接,这个连接和普通的SSH登录的连接并没有本质上的区别

假设有两台主机A和B,IP分别是IP_A和IP_B,是要把主机A的22端口映射到主机B的10022端口

连接的建立过程是这样的:

1. 建立TUNNEL (在A主机上执行命令)
ssh命令,把A的端口映射到B主机(ssh -NfR 10022:localhost:22 USER_B@IP_B)
这个步骤实际上是这样的:
(1)ssh命令是ssh客户端,这条命令是指在A主机上登录B主机,并且A主机请求将A主机的22号端口映射到B主机的10022端口。
(2)B主机接受远程登录请求后,检测发现用户的权限足以创建10022端口,且10022端口并未使用。则B主机开启一个监听端口:10022
(3)这条命令成功结束后,A主机有了一个后台进程登录到B主机,这个登录的连接正是“TUNNEL”。
而B主机相应也有这么一个后台进程,此外B主机还增开了一个监听端口:10022
(4)在这个过程中,B是Server,A是Client。那么A是以一个任意端口连接到B的ssh监听端口。所设这个连接是
IP_A:12345 —— IP_B:22

2. 连接映射端口 (在B主机上执行命令)
连接映射端口 ( ssh USER_A@localhost -p 10022)
这个步骤实际上是这样的:
(1)主机B连接自己的一个监听端口10022
于是主机B以一个任意的端口连接10022: IP_B:23456 ——- IP_B:10022
(2)10022端口实际是由主机B的sshd来维护的,sshd发现有连接到10022的端口的数据。
将数据封装成ssh包,通过已经建立好的TUNNEL传输到对端主机A的12345端口(TUNNEL建立时的初始端口)
(3)主机A的12345端口收到数据后,经过TUNNEL的建立进程的处理(解开ssh包),把数据转到主机A的端口22(建立TUNNEL时指定的端口)
(4)因此,这个反向的连接就建立起来了

3. TUNNEL与TCP连接的关系
(1)TUNNEL本质是一个TCP连接
(2)TUNNEL的作用用于传输其它TCP连接的数据
(3)对用户而言,TUNNEL就是它们可见的TCP连接传输的一个“隧道”

SSH的端口转发_网络_09

如需转载,请注明出处:http://blog.lilinux.net/2010/02/ssh-tunnel/

题目有点长
其实来自于一个朋友的问题
他的oracle跑在linux服务器上
远程的linux服务器并没有跑在图形界面下(runlevel=5)
而是跑在字符模式下(runlevel=3)
而他又想用图形界面来管理oracle
我翻了翻资料
找出一种方法
在一台图形界面的linux下(虚拟机也行,其实不是linux也行,关键是本地得有X server)起一个控制台
用命令行ssh加参数”-X”连上远程的linux服务器
像这样
ssh -X oracle@1.1.1.1
这里”1.1.1.1″是远程linux服务器的ip地址
这样连上去之后
直接就可以用以前只有在图形界面上才能用的命令
如oracle管理的图形程序”dbca”

这个原理很简单
因为远程的sshd支持x11 forward
那么他起x程序的时候
就会把x的包通过ssh转回来到ssh客户端的机器上来
而ssh客户端这边跑得有x server
所以就能正确接收x包并显示出来

其实在windows下也可以通过安装x server软件来实现一样的效果
比如x manager就可以
具体用法不在详述

这里的关键在于
远程的sshd需要支持x11 forward
不过不要担心
一般情况下
缺省是支持的


SSH端口转发(本地端口转发、远程端口转发、动态端口转发)工作原理、应用详解

实验条件:
1.本文所述之实验,本地主机操作系统基于Ubuntu 10.04,远程主机操作系统基于BSD发行版
2.本地主机安装了ssh client(ssh),也安装了ssh server(sshd)
基础知识:
文章中客户端指ssh,用于发出连接请求;服务端指sshd,监听端口22。
安全通道是指ssh与sshd之间已建立的连接通道,该连接是加密的。

SSH 端口转发格式[1]

[-L [bind_address:]port:host:hostport]
[-R [bind_address:]port:host:hostport]
[-D [bind_address:]port]


动态端口转发
-D <port>
这会使本地主机监听端口port,一旦与该端口建立连接,经过该端口的数据会被转发到安全通道发送到远程主机。远程主机的sshd会根据数据包的应用层协议(如HTTP)自动建立对应的连接。

$ ssh -D 7070 sisca@216.194.70.6

登陆前本地主机端口监听状态:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  

登陆后本地主机端口监听状态:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp        0      0 127.0.0.1:7070          0.0.0.0:*               LISTEN      5205/ssh  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  tcp6       0      0 ::1:7070                :::*                    LISTEN      5205/ssh

登陆后远程主机端口监听状态:

$ sockstat -4l  USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS  (什么都没有)  

小结:我们发现,动态端口转发的时候确实是本地主机的ssh在监听端口7070的


本地端口转发
-L <local_port>:<host>:<host_port> <ssh_server>
这会使本地主机监听端口local_port,一旦与该端口建立连接,经过该端口的数据会被转发到安全通道,同时远程主机会与主机host的端口host_port建立连接。

$ ssh -L 7001:localhost:7070 sisca@216.194.70.6

登陆前本地主机端口监听状态:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  

登陆后本地主机端口监听状态:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp        0      0 127.0.0.1:7001          0.0.0.0:*               LISTEN      3475/ssh  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  tcp6       0      0 ::1:7001                :::*                    LISTEN      3475/ssh

登陆后远程主机端口监听状态:

$ sockstat -4l  USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS  (什么都没有)  

小结:我们从中可以看出,本地端口转发的时候确实是本地主机的ssh在监听端口7001


远程端口转发
-R <remote_port>:<host>:<host_port> <ssh_server>
这会使ssh_server(远程端)监听端口remote_port,一旦与该端口建立连接,经过该端口的数据会被转发到安全通道,并且本地主机会与主机host的端口host_port建立连接。

$ ssh -R 7001:localhost:7070 sisca@216.194.70.6

登陆前本地主机端口监听状态:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  

登陆后本地主机端口监听状态:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  

登陆后远程主机端口监听状态:

$ sockstat -4l  USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS  sisca    sshd       66196 7  tcp4   127.0.0.1:7001        *:*

小结:很明显,使用远程端口转发时,本地主机的端口监听并没有发生变化,相反远程主机却开始监听我们指定的7001端口

小提示:
这里的remote_port,local_port可以归并为listen_port,因此我们得到这样的助记格式:

ssh [-L|-R] <listen_port>:<host>:<host_port>



本地端口转发应用:[2]
背景:在实验室里有一台 LDAP 服务器(LDAP Server),但是限制了只有本机上部署的应用才能直接连接此 LDAP 服务器。现在我们想临时从本地机器(LDAP Client)直接连接到这个 LDAP 服务器,只需要在LDAP Client上运用本地端口转发:

$ ssh -L 7001:localhost:389 LdapServerHost

图1 本地端口转发
SSH的端口转发_Network_10
数据流向:
该命令首先使本地主机(LDAP Client)与远程主机(LDAP Server)建立一个SSH安全连接(安全通道)
然后本地主机会监听端口7001(注意是ssh在监听)
一旦本地LDAP客户端程序将数据发送到端口7001(即建立连接),远程主机上的sshd将主动与端口389(LDAP服务的端口)建立连接
从而来自LDAP客户端的请求转发到该端口389上(当然是通过安全通道)
注意:
本地主机有两个客户端:
1) ssh – 用于与远程主机建立ssh连接
2) LDAP客户端 – 用于与远程主机的LDAP服务程序进行通讯
远程主机对应地有两个服务进程:
1) sshd – 监听端口22
2) ldapd -监听端口389


远程端口转发应用:[2]
背景:这次假设由于网络或防火墙的原因我们不能用 SSH 直接从 LDAP Client 连接到 LDAP 服务器(LDAP Server),但是反向连接却是被允许的。那此时我们的选择自然就是远程端口转发了。我们这次在LDAP Server上运用远程端口转发,因此LDAP Client必须安装了sshd

$ ssh -R 7001:localhost:389 LdapClientHost

图2 远程端口转发
SSH的端口转发_Network_11
数据流向:
该命令首先使LDAP Server与 LDAP Client 建立一个SSH安全连接(安全通道)
然后LDAP Client开始监听端口7001(注意是sshd在监听)
一旦LDAP Client将数据发送到端口7001(即建立连接),LDAP Server上的ssh将主动与端口389(LDAP服务端口)建立连接
从而来自LDAP客户端的请求转发到该端口389上(当然是通过安全通道)


本地转发与远程转发的对比与分析
本地端口转发:ssh客户端发起ssh连接,并且监听指定端口
远程端口转发:ssh客户端发起ssh连接,但是由远程主机上的sshd监听指定端口


多主机转发应用[2]
图3 多主机端口转发
SSH的端口转发_主机_12

$ ssh -g -L 7001:<B>:389 <D>

注意:我们在命令中指定了“ -g ”参数以保证机器(A)能够使用机器(C)建立的本地端口转发。

References:
[1] man 1 ssh
[2] IBM DeveloperWorks –
实战 SSH 端口转发

Please support us if you feel this post is useful.


SSH 名为 secure shell, 是专门用来进行安全远程访问的协议。它无论从功能上、系统兼容性上、还是从安全上和TelnetRSH相比都是足以取而代之。

在这个ARP欺骗横行,网上盗窃泛滥的年代,还有什么比安全更为重要的?

在这个遍地都是防火墙的年代,还有什么比通过一个端口就能访问所有业务更为重要的呢?

在矛和盾同样发达的年代,SSH可以给我们什么样的方便?

现代的UNIX类操作系统,无一例外地将SSH,作为默认系统软件包进行安装。

基本的连接方式:SSH Hostname

     SSH 提供了多种不同的接入认证方式:

           Password

           Hostkey

                       .....

                       .....

其中常用的有 passwordhost public key如果使用password,则会产生用户交互的密码输入,如果使用host key, 则可以直接登录或直接执行远程命令。

           SSH Client Server的交互,能实现很多其他非常有用的功能:

最基本的功能有如下选项:

SSH 会话内容的压缩,可以使用gzip压缩级别进行指定,以提高在慢速线路上数据传输效率。

SSH 本地端口转发,可以将本地某个端口和远程SSH服务器上、或SSH远程服务器可达的地址端口建立一种映射关系,使对本地端口的访问请求会透明地转发到远程服务器上。从远程服务器上所看到的来访请求源地址将是SSH服务器的地址。

SSH的端口转发_Internet_13

SSH 远程端口反向转发,与上列相反, 远程端口反向转发建立后,远程客户机访问远程SSH服务器的某端口,SSH服务器将把来访请求通过SSH安全通道转发到SSH客户端或SSH客户端可达的服务器地址端口上,从而使远程客户机,可以正常访问内部服务器所提供的服务。

SSH的端口转发_主机_14

这样,SSH客户端D,就可以通过访问SSH服务器B的端口D,从而达到访问业务服务器C上端口D的目的。

高级功能/用法有:

SSH 端口转发的接续。

由于现代的UNIX系统都默认带有SSH服务和客户端,所以当网络变得比较复杂、层次很多的时候,使用多台机器的端口转发接续,可以将在层次很深的内网服务,在不改变当前网络结构和防火墙配置的情况下,层层转发出来从而可以使外网用户很方便地使用该内网服务,而无须对现有网络构架和甚至防火墙配置作任何变动。而对最外层的防火墙只需要开放一个22端口(默认ssh服务端口)就能使授权的客户端访问全网业务。

SSH 动态端口转发。

SSHv2,同时还支持内置的SockS4 Server,将ssh 客户端的指定端口,作为一个远程SOCKS4 Server的端口。对SockS4Server的访问请求将通过,SSH Protocol 传输到 SSH 服务器, SSH服务器将请求转发到用户应用的真正目的服务器。

SSH PPP通道。

结合UNIX PPPD,还可以在SSH PTS 通道上建立PPP LINK从而非常灵活的实现 IP over SSH ×××。这种方法,可谓SSH的终极用法,因为它解决了所有由于地址翻译而带来的应用层协议不兼容的问题(多播问题是否能解决尚未测试)。

SSH产品实战。

SecureCRT

VanDyke Software 的经典力作,几乎囊括了所有SSH客户端的功能,在此,SSH的标准功能就不多说了。说一些windows上的特色功能使SCRT变得非常灵活。

1、它拥有端口转发安全过虑器,可以灵活地允许或禁止其他客户机访问被SecureCRT所转发的本机端口。

2、同时还拥有VBSCript/Jscript/Perl 脚本功能,可以通过这三类脚本语言和远程服务器进行自动交互式执行。

3、可以自动和服务器上的Zmodem进行交互,实现基于TTY/PTSZmodem 文件传输(这个功能可在任何类型的会话中进行,并不局限于SSH类型的会话)。

4、自动和SecureFX匹配实现SFTP的文件传输功能(无需输入用户名密码,因为是基于已建立的SSH Session的,所以登录速度是非常快的)由于SecureFx带有拖放功能,和类似文件夹的拷贝粘贴功能,所以会给文件传输带来很大方便性(FTP还是很不方便的)。

5、支持命令行方式,可在CMD中实现一步登录并将端口转发作为参数输入(和UNIXSSH基本没区别了)。

功能太多了,就不一一列举了。详细请查看VanDyke Software的主页和SecureCRT的帮助文件。

UniTTY

A Pure Java Based SSH 客户端。居然实现了几乎所有的SSH功能。而且更牛的是,实现了端口转发的动态加载。而且默认实现了SFTP over SSH的文件传输。只是字体有待改进。看惯了SecureCRT的优雅美观的字体,再用UniTTY可能就有些不习惯了。它的多协议支持能力也很特别,居然将VNC的客户端协议也加进来了。

UNIX SSH 客户端

    完全基于OpenSSH,最标准的客户端。能完成所有SSH协议支持的功能,同时结合UNIX的脚本,能完成其他操作系统无法完成的很多任务。或配合完成前面所提到的一些用法!

NetSarang XSHELL

           韩国人写的多协议客户端,和他另外一个在国内很流行的产品(Xmanager)配合使用很好。默认支持TAB窗口的SFTP,使用也比较方便,也同时支持双向的端口转发。

     MindTerm

            纯java的ssh客户端,非常著名的开源软件mindterm。

         mindterm,居然提供了源代码真是不错,以后可以将expect也扔了。

         而且该有的都有了(sockserver, 端口转发,反向转发,scp,telnet,zlib compression,keepalive等),还额外提供了ftp 协议桥接sftp的功能,就是有一点不方便,在哑终端方式启动,需要X11Display支持。

   zenith 2007.9.10



网的朋友苦于没有合法 ip,不能对外提供 internet 服务。解决方案很多,可以通过在网关做端口映射,或其他的辅助软件等。

本文介绍两种比较简单实用的方法,利用 ssh 这个强大的工具。
(以下方法不分平台,都适用)

案例一、
内网主机 A ,开了 http,ftp ,http ,vnc,sshd,socks5,cvs 等服务。无合法 ip 地址。


外网主机 B ,开了 sshd 服务。有合法 ip : 218.xxx.xxx.xxx


我们的目的是让 B 能访问 A 上的各种服务。

步骤:
1、A(内网服务器)  知道 B ip 后,先用 ssh client 连上 B,命令如下:
ssh -R 1234:localhost:21     -l root  218.xxx.xxx.xxx

解释:
关于 ssh 的参数,请看 ssh --help
-L listen-port:host:port Forward local port to remote address
-R listen-port:host:port Forward remote port to local address
-L local (本地) -R :remote (远程)

-R 1234:localhost:21 其实做了个“端口转发(forward)"。
意思是主机 A 把本地的 21端口(对应ftp服务)映射为 B 的1234 端口(任意未被占用),同时 A 监听 B 的1234 端口。
在 B 上用 netstat -al | grep 1234 ,你能看到这个监听连接。
任何发送到 B 1234 端口的请求将被传送到 A的 21 端口。

2、B 用 ftp 工具(任意,如gftp) 连本地的 1234 端口,输入 A 的 ftp 用户和密码。
ftp localhost 1234

千万不要觉的奇怪,为什么连的是本地的地址。
举个不恰当例子,相当于 A 在 B 的房间里装了个***(监听端口),那么 B 在房间里说的话就通过***传送到了 A。

3、推广:
如果 B 没占用 21 端口的话,那么可以写成:
A使用: ssh -R 21:localhost:21 -l root 218.xxx.xxx.xxx
B使用: ftp localhost

如果你想使用 A 上的 http 或其他服务,只需改变服务端口:
http服务 :
A使用:ssh -R 1234:localhost:80 -l root 218.xxx.xxx.xxx
B使用:w3m http://localhost:1234

sshd服务:
A使用:ssh -R 1234:localhost:22 -l root 218.xxx.xxx.xxx
B使用:ssh localhost -p 1234

vnc 服务:
A使用:ssh -R 1234:localhost:5901(其他) -l root 218.xxx.xxx.xxx
B使用:vncviewer localhost:1

socks5服务:
A使用:ssh -R 1234:localhost:1080 -l root 218.xxx.xxx.xxx
B 略

cvs 服务:
A使用:ssh -R 1234:localhost:2401 -l root 218.xxx.xxx.xxx
B使用:cvs -d :pserver:root@localhost:1234/home/cvsroot login

这里是否一定要用 root ,涉及到权限问题,具体还得靠大家来总结经验。

案例二、
部分朋友会问了,这样的话只是两台机器的互相通讯,如何让广域网的人都能访问呢?
聪明的你,这时候可能已经有了答案。

内网主机 A ,开了 http,ftp ,http ,vnc,sshd,socks5,cvs等服务。无合法 ip 地址。
外网主机 B ,开了 sshd 服务。有合法 ip : 218.xxx.xxx.xxx
我们的目的是让 internet 上的任何主机能访问 A 上的各种服务。

步骤:
1、首先,B 的sshd 服务端做点小小的设置:
vi /etc/ssh/sshd.config
加入 GatewayPorts yes
然后重启 sshd 服务: /etc /init.d/ssh restart 或 /etc/init.d/sshd restart
(解释:
不加,默认会把监听端口绑定在 localhost 或 lo(127.0.0.1),这样除了 B自身别人是没法访问监听端口的。
加入 GatewayPorts yes,把监听端口绑定到 0.0.0.0 ,这样外部的所有机器都能访问到这个监听端口。
主要是考虑安全性问题,默认情况,只允许本地访问。

这里才是真正的难点,实验了一个晚上,累人呀!给点鼓励吧 :)

2、A 知道 B ip 后,先用 ssh client 连上 B,命令如下:
ssh -R 21:localhost:21 -l root 218.xxx.xxx.xxx
(事先确定 B 的21 端口未被占用)

3、分布在 internet 的其它客户机使用 ftp 工具(任意),连 B 21端口。

ftp 218.xxx.xxx.xxx 21

你会发现自己连上了内网 A 的ftp 服务。

此法和案例一完全一样。

internet --------->> B 21 端口----------->>A 21端口
可以叫做端口转发,或隧道技术,也可以称之为跳板(B),或反* 。呵呵,我瞎说的。。。

可能遇到的问题:

Country:/etc# ssh localhost -p 1234
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
be:5f:d2:45:66:4d:0c:9e:2b:6b:45:65:a7:b2:85:28.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending key in /root/.ssh/known_hosts:11
RSA host key for localhost has changed and you have requested strict checking.
Host key verification failed.
Country:/etc# ssh localhost -p 1234
root@localhost's password:
Last login: Mon May 5 02:39:53 2003 from localhost
localhost root #

如上问题,请删除 ~/.ssh/known_hosts,然后再试。

点评:
当然 ssh 还有很多的功能没有用,如先用 ssh 连接 上去后,可以用 scp命令来存取文件,等等。
scp -P xxx user@host:path/file

其它突破网关传送文件的方式也千变万化。

优点是:
可以突破网关,一般情况下,向网管要求在网关上给你做端口映射是不现实的,但用此法你可以让要好的朋友给你做。
使用方案一:比较点对点传送文件比较方便,或使用ssh进行远程控制内网。
ssh本身是加密,保证安全可靠。

缺点也不少:
使用 ssh 加密,势必影响性能,可以用 -C 选项调节压缩率。
如果象方案二使用额外的服务器,数据都要服务器中转(我是这样认为,没跟踪过),势必影响速度。
公网的服务器不好找。

建议:恳请编程高手们根据类似得原理,做个端口转发小工具,效果会更好。

本文,雕虫小计,漏洞无数。旨在提供一种如何解决问题的思路,请大侠不要笑话。也请大家多多支持,共同提高。

特别感谢 :sleeve ,x11 兄,是他们帮助一起实现的。以及 irc.linuxfire.com 中的大伙:)