如何通过SSH隧道所有RMI流量

时间:2011-11-26 15:25:57

标签: java ssh rmi tunnel cajo

我正在通过SSH隧道挖掘cajo rmi流量。

为此,我有一台运行SSH deamon的服务器(apache Mina)和一台运行SSH客户端的客户端(Trilead SSH)。

可以建立这些机器之间的shh连接,通过应用本地和远程端口转发,我可以隧道传输rmi流量,但这只能在外包(到服务器)方向上工作。

设置:

活动SSH连接(端口22)
客户端:将本地端口4000转发到远程主机端口1198(此流量实际上是通过隧道)     服务器:转发服务器端口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());

使用客户端的trilead ssh库调用端口转发:

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

在使用WireShark分析两台计算机之间的IP流量时,我看到通过隧道重定向查找,但响应不是。 响应通常发送到客户端的端口1198。

如何强制服务器将远程调用的响应发送到本地端口,以便将其隧道传送回客户端?

更新:此处的问题是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时,我无法得到响应回来了,我根本没有看到任何响应的流量...

1 个答案:

答案 0 :(得分:2)

我确实找到了解决这个问题的方法,我从设置中省略了cajo框架并使用了纯java rmi。这使事情变得更加透明。

在客户端和服务器上,我放置了一个安全策略文件:C:\ server.policy

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,

  • 这使得客户端认为从远程注册表获取的对象是本地的,然后连接到其本地转发端口。

在客户端上,我提供与上面相同的权限,我不启动注册表,但绑定一个额外的套接字工厂用于注册表查找。

RMISocketFactory.setSocketFactory(new LocalHostSocketFactory());

此套接字工厂创建一个到localhost 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")};
}

}

这种自动端口格式化可确保无论使用哪个端口绑定RMI对象,它都会通过SSH隧道并指向localhost。

此设置不需要远程端口转发。