精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● Java>>JAVA编程>>网络编程>>RMI>>ifeelyou(gz):如何使RMI通过防火墙

主题:ifeelyou(gz):如何使RMI通过防火墙
发信人: ifeelyou()
整理人: consultant(2000-09-30 14:26:31), 站内信件
  这个问题应该分为两部分,一是如何调用防火墙外部方法(outgoing calls)
,一是如何调用防火墙内部的方法(incoming calls)。

  1.通过防火墙调用外部方法。
  
  通过防火墙调用外部方法,是指客户程序在防火墙之后的内部网上,而要调用
的远程方法在Internet上。主要有三种途径达到这个目的:HTTP隧道、SOCKS和下
载套接字代理。
  
  HTTP隧道
  
  这是一种比较老的方法,但是仍然比较流行,因为它几乎不需要什么设置。他
在允许通过代理服务器使用HTTP请求的环境中工作的很好,但是不支持一般的TC
P连接。
  
  如果RMI通过一般的连接(或SOCKS)到特定的服务器失败了,而且它发现已经配
置了HTTP代理服务器,那么它会通过“隧道”使RMI请求通过代理服务器。
  
  有两种格式的HTTP隧道将会被依次尝试,首先是HTTP到端口,然后是HTTP到CG
I。
  
  在HTTP到端口的隧道方式中,RMI直接尝试到目的主机和目的端口的HTTP POST
请求,该HTTP POST请求包含单个的RMI请求。如果HTTP代理服务器接受了这个UR
L,那么它会把该请求转发到正在侦听的RMI服务器,RMI服务器会识别该HTTP PO
ST请求并把它解包成RMI请求。而结果会被包装成一个HTTP响应,通过代理服务器
返回。
  
  通常代理服务器会拒绝任意的端口访问。在这种情况下,RMI会转换到HTTP到C
GI隧道方式。就像上面那样,RMI请求会被先包装成HTTP POST请求,但该请求的
URL格式是form http://hostname:80/cgi-bin/java-rmi.cgi?port=n (其中hos
tname和n使目的主机的名字和端口)。目的主机上必须要有一个在端口80侦听的
HTTP服务器,该服务器会运行java-rmi.cgi脚本(由JDK提供),该服务器会逐一
转发请求到RMI所侦听得端口n。RMI可以在不依靠HTTP服务器、CGI脚本或其他外
部实体的帮助下解包通过HTTP隧道传过来的RMI请求。因此,如果客户程序的代理
服务器可以直接连接到服务器端口,你就根本不需要java-rmi.cgi脚本。
  
  为了触发对HTTP隧道的使用,标准的系统属性http.proxyHost必须被设置到本
地HTTP服务器的主机名。(据说某些Netscape用户不必设置该属性。)
  
  HTTP隧道最大的缺点是不允许向内的请求和多元连接。第二个缺点是HTTP到CG
I打开了服务器端的安全漏洞,因为不需要任何更改就可以重定向外来请求到任何
端口。
  
  SOCKS
  
  JDK中套接字的缺省实现是通过可用的配置过的SOCKS服务器。系统属性socksP
roxyHost必须设置到本地SOCKS服务器的主机名;如果SOCKS服务器的端口号不是
1080的话,还要配置socksProxyPort属性。
  
  这个方法看起来是最有用处的解决方案。但是至今ServerSockets仍然没有使用
SOCKS服务器,因此处理外来请求仍然需要其他的机制。
  
  下载套接字代理(downloaded socket factoris)
  
  这是JDK1.2Beta4的创新,允许服务器指定客户必须使用的套接字代理。客户端
必须运行在JDK1.2Beta4或更高版本下。此方法将在将来的某个时候译给大家(S
orry!)。
  
  这种方法的缺点是穿过代理服务器必须通过RMI服务器端提供的代码实现,它不
必知道穿过怎样被完成,而且它也没有自动获得足够的权限穿过防火墙。
  
  2.通过本地防火墙接受外来RMI方法调用。
  
  共有四种主要方法:已知端口、传输层桥、应用层代理和连接多路复用技术。

  
  已知端口
  
  如果输出的对象都在同一主机的同一端口输出,那么该主机和端口可以在防火
墙上明确许可。一般来说,RMI请求端口0(代表“任意端口”)。在JDK1.2中,
exportObject方法用一个额外的参数指定端口号。在JDK1.1中,服务器必须子类
化RMISocketFactory并截取请求到createServerSocket(0),用指定到特定端口的
请求替换它。
  
  这个方法的缺点是需要管理本地代理服务器的网络管理员的支持。如果输出的
对象正在别处的机器上运行(因为代码DL到该机器上),那么本地代理服务器的
管理员可能并不知道你是谁。
  
  传输层桥
  
  传输层桥是从一个TCP连接读取字节流并把他们写到另外的TCP连接的程序,这
个程序并不知道那些字节流代表什么。
  
  这个想法是以这样的途径输出对象:任何想在防火墙外调用该对象的方法的客
户程序改为连接一个另外的端口(或许也是一台另外的主机),这个另外的端口
上运行着一个程序,该程序建立第二个连接到真正的服务器,然后把字节流像“
泵”一样抽取过来。
  
  技巧性的部分是使客户程序信任地连接到桥。可下载的套接字代理(download
able socket factory)(JDK1.2)可以有效的完成这个任务;另外,可能需要设
置java.rmi.server.hostname属性来命名桥主机并同时设置端口。
  
  应用层代理
  
  这个方法比较费功夫,但这会是一种比较安全的做法。代理程序运行在防火墙
所在的主机上(即可在外部又可在内部访问)。当内部的服务器准备使输出的对
象可用时,它连接代理服务器并给它一个引用。然后代理服务器建立一个代理对
象(位于代理服务器上的新的远程对象),这个代理对象就像原对象一样实现相
同的远程接口。代理服务器向内部的服务器返回一个新代理对象的一个远程引用
,内部服务器通过它和外界交流(不知何故)。
  
  当外界调用代理时,代理立即转发该调用到内部服务器原来的对象。代理的使
用对外界来说是透明的(但对内部服务器并不透明,在和任何对象交流时它必须
决定是传送原对象的引用还是代理对象的引用)。
  
  不用说,这需要考虑设置和与本地网管的协作。
  
  连接多路复用技术
  
  因为JDK1.0.2不允许非授权代码侦听TCP端口(即使该端口大于1023这些匿名端
口),所以即使JDK1.1的代码没有那些限制,JDK1.0.2代码也不能输出对象到JD
K1.1。因此,传输层的代码被改变了,从而允许连接多路复用:即,连接可以是
多路复用的,每一路都可以做实际工作。连接多路复用不会超时,但它们是不可
升级的。
  
  然而,可以使用连接多路复用绕过防火墙的特殊规则:那些允许在一个方向上
连接而不可在相反方向上连接的防火墙。
  
  这项技术是要防止RMI侦听TCP端口,因此导致连接多路复用技术。这样做的唯
一途径是安装安全管理器,在checkListen内部抛出SecurityException异常。
  
  如果你能这样做,你同样也可以安装一个套接字代理来替代它。
  
  3.如何使RMI穿越两层防火墙?
  
  首先,你需要客户端的防火墙如何合作呢?
  
  做糟糕的情况是客户端的防火墙只有HTTP代理服务器并且不允许直接连接TCP端
口,这样防火墙后的客户只能做网上冲浪。在这种情况下,你的服务器主机会收
到在端口80的连接,这些连接包含内嵌有RMI请求的HTTP请求。你可以使用带有j
ava-rmi.cgi程序的HTTP服务器,或者直接在端口80上运行RMI服务器。在任何一
种情况下,服务器都无法使用客户端输出的回调对象。
  
  比较乐观的情况是客户端可以直接连接到服务器,但是不能接受由服务器传来
的外来连接。这种情况下,回调对象一般也是不可能的(有一种特殊情况,就是
有些环境下的applet可以触发与JDK1.0.2兼容的连接多路复用模式——这会允许
回调对象,但这是不可升级的,一般不支持这样做。)。
  
  假设没有客户端防火墙管理员的帮助,最保守的方法是:
  
      * 避免使用回调对象;
      * 在公共端口上运行服务器,如80,81,8001,443等。
      * 如果服务器没有运行在80端口上,那么:
          - 在端口80上运行一个有CGI能力的HTTP服务器,它可以使用java-rm
i.cgi,或者
          - 在80端口上运行一个端口转向器,它可以接受连接并立即连接到真
正的服务器端口并传送数据。这会导致getClientHost()返回容易让人误解的信息
,因此除非在不同的主机上,否则尽量不要使用这种方法使注册器(Registry)
可用。
 

--
灌水的时候想想我,想我的时候来看我...
看什么看,没见过鱼吗?!

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.104.86.90]

[关闭][返回]