2011-11-26 78 views
1

我正在通過SSH隧道隧道傳輸cajo rmi流量。通過SSH隧道傳輸所有RMI流量

爲此,我有一臺運行SSH deamon(apache Mina)的服務器和一臺運行SSH客戶端(Trilead SSH)的客戶端。

可以建立這些機器之間的shh連接,並通過應用本地和遠程端口轉發我可以隧道rmi流量,但是這隻適用於延長(到服務器)方向。

的設置:

主動SSH連接(端口22)
客戶端:轉發本地端口4000,遠程主機端口第1198(此流量實際上去trhough隧道) 服務器:轉發服務器端口4000到客戶端端口1198(隧道的這部分沒有被使用cajo)

服務器出口使用對象:

Remote.config(null, 1198, null, 0); 
ItemServer.bind(new SomeObject(), "someobject"); 

客戶端不會使用對象查找:

ObjectType someObject = (ObjectType)TransparentItemProxy.getItem(
          "//localhost:4000/someobject", 
          new Class[] { ObjectType.class }); 
logger.info(someObject.getName()); 

端口轉發是使用在客戶端的三鉛SSH庫調用:

conn.createLocalPortForwarder(4000, "Server-IP", 1198); 
conn.requestRemotePortForwarding("localhost" 4000, "Client-IP", 1198); 

當使用Wireshark分析兩個機器之間的IP通信,我發現通過隧道將查詢重定向,但迴應不是。 負責人通常發送到客戶端的1198端口。

如何強制服務器將遠程調用的響應發送到本地端口,以便將其傳回客戶端?

UPDATE:這裏的問題是,對RMI對象的端口不同,那麼註冊表端口,因此還需要進行轉發。

簡而言之,客戶端10.0.0.1會查找到//10.0.0.1:4000,並將其轉發到服務器上的RMI端口(通過隧道)。 隨後,服務器響應10.0.0.1:1198,我希望服務器將其流量發送到其本地端口4000,以便使用隧道。

我試圖擺弄cajo Remote.config(ServerAddress,ServerPort,ClientAddress,ClientPort)設置,但是當我將clientaddress設置爲10.0.0.1或127.0.0.1這個方法時,我無法獲取響應回來,我沒有看到任何響應的交通...

+0

將響應發送回請求發送到的相同連接。你在談論一個*回調*? – EJP

+0

他在這裏回答了答案中的細節嗎? http://stackoverflow.com/questions/1734558/java-rmi-via-ssh-v2-protocol - 好像他可能錯過了至少一次轉移 – Petesh

+0

謝謝Petesh和EJP,我正在重新思考我的設計。 RMI註冊表可能運行在與RMI服務器不同的端口上。定製RMI服務器端口我想我需要實現一個自定義套接字facktory,如下所述:http://www.javaranch.com/journal/2003/10/rmi-ssh_p1.html –

回答

2

我找到了解決這個問題的方法,其中我從設置中省略了cajo框架並使用純java rmi。這使事情更加透明。

在客戶端和服務器上,我都放置了一個安全策略文件:C:\ server。政策

grant { 
permission java.security.AllPermission; 
}; 

然後在服務器上,設置安全權限並開始所需的端口上的註冊表:

System.setProperty("java.rmi.server.hostname", "127.0.0.1");    
System.setProperty("java.security.policy","C:\\server.policy"); 
System.setSecurityManager(new RMISecurityManager()); 
new SocketPermission("*:1024-", "accept,connect,listen");  
createRMIRegistry(Property.getProperty("rmi.registry.port")); 

注意主機名127.0.0.1,這樣可以確保我們始終指向localost,

  • 這招騙客戶端認爲從遠程註冊表獲得的對象是本地的,然後連接到它的本地f轉發端口。

在客戶端上,我給出了與上面相同的權限,但我不啓動註冊表,但綁定了一個額外的套接字工廠用於註冊表查找。

RMISocketFactory.setSocketFactory(new LocalHostSocketFactory()); 

此套接字工廠創建一個到本地主機ssh端口(到遠程註冊表)的SSHClientSocket。

遠程對象使用自定義ClientSocketFactory導出,因此在客戶端實現。 (在服務器端,它需要被禁用,否則你將ssh到你自己的機器:$)

然後它創建一個ssh套接字和端口轉發器。

public class SSHClientSocketFactory implements RMIClientSocketFactory, Serializable { 

public Socket createSocket(String host, int port) throws IOException { 
    try {  
    Connection conn = new Connection(hostname, 22); 
    conn.connect(); 
    boolean isAuthenticated = conn.authenticateWithPassword(username, password); 
    LocalPortForwarder lpf1 = conn.createLocalPortForwarder(port, serverAddress, port); 
     return new Socket(host, port); 
    catch (Exception e) {System.out.println("Unable to connect")}; 
} 

}

這種自動端口formwarding確保被用於結合的RMI對象的任何端口,它通過SSH通道和點爲localhost了點。

此設置不需要遠程端口轉發。

+0

我現在修改了上面的方法。我在服務器端需要一些額外的可配置性。所以我更改了sshd的ChannelDirectTcpip,以編程方式將我的主機地址名稱解析爲127.0.0.1。 –