1

SSH トンネルを介して cajo rmi トラフィックをトンネリングする作業を行っています。

そのために、SSH デーモン (apache Mina) を実行するサーバーと、SSH クライアント (Trilead SSH) を実行するクライアントがあります。

これらのマシン間の shh 接続を確立し、ローカルおよびリモート ポート フォワーディングを適用することで、rmi トラフィックをトンネリングできますが、これは送信 (サーバーへの) 方向でのみ機能します。

セットアップ:

アクティブな SSH 接続 (ポート 22)
クライアント: ローカル ポート 4000 をリモート ホスト ポート 1198 に転送します (このトラフィックは実際にはトンネルを通過します) サーバー: サーバー ポート 4000 をクライアント ポート 1198 に転送します (トンネルのこの部分は、カジョ)

サーバーは、以下を使用してオブジェクトをエクスポートします。

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 を使用して 2 台のマシン間の 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 に設定すると、応答が返されず、応答するトラフィックがまったく表示されません...

4

1 に答える 1

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());

このソケット ファクトリは、ローカルホストの 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 を指すようにします。

このセットアップでは、リモート ポート フォワーディングは必要ありません。

于 2011-12-04T00:13:39.800 に答える