как туннелировать весь трафик RMI через SSH - PullRequest
1 голос
/ 26 ноября 2011

Я работаю над туннелированием трафика cajo rmi через туннель SSH.

Для этого у меня есть сервер под управлением SSH deamon (apache Mina) и клиент под управлением клиента SSH (Trilead SSH).

Тсс-соединение между этими машинами может быть установлено, и, применяя локальную и удаленную переадресацию портов, я могу туннелировать трафик 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);

При анализе трафика ip между двумя компьютерами с помощью WireShaЯ вижу, что поиск перенаправляется через туннель, но ответ - нет.Ответ обычно отправляется на порт 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), однако, когда я устанавливаю клиентский адрес на 10.0.0.1 или 127.0.0.1 для этого метода, я не могу получить ответ обратно и вообще не вижу отвечающего трафика...

1 Ответ

2 голосов
/ 04 декабря 2011

Я нашел решение этой проблемы, в котором я опустил инфраструктуру 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());

Эта фабрика сокетов создает SSHClientSocket для локального ssh-порта (в удаленный реестр).

Удаленные объекты экспортируются спользовательский 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.

Удаленная переадресация портов не требуется для этой настройки.

...