# Schon wieder: RMI hinter Firewall/Router



## tuxedo (19. Okt 2007)

Hallo zusammen,

ich weiß, das ist ein leidiges Thema, aber auch die Suche hat mich nicht weiter gebracht. 
Ich habe also folgendes Szenario:

Server hinter einem Router am DSL-Anschluss:
interne Adresse: 192.168.0.249
externe Adresse: meindyndnsname.homelinux.org
RMI Registry läuft auf Port 2000 (bedingt durch andere Tools)
Port 2000 im Router entsprechend unter Port-Forwarding auf IP 192.168.0.249 weiterleiten lassen

Sooo. Befindet sich ein Client lokal im Netzwerk (192.168.0.x) des RMI-Servers, kann er problemlos eine Verbindung mit 192.168.0.249 aufnehmen. Klappt bestens.

Befindet sich der Client irgendwo im Internet und versucht nun unter meindyndnsname.homelinux.org den RMI Server zu erreichen haut das für's erste hin:


```
mServerSessionFactory = (ServerSessionFactory) Naming.lookup("//"+mServerHost+":"+mServerPort +"/Serverprogramm");
```

mServerHost => meindyndnsname.homelinux.org
mServerPort => 2000

Hier gibts noch keinen Fehler. Ich kann das Objekt prima bei der Registry abholen. Aber jetzt kommts:
Sobald ich eine Methode in diesem Server-Objekt versuche aufzurufen bekommt mein Client folgende Exception:



> java.rmi.ConnectException: Connection refused to host: 192.168.0.249; nested exception is:
> java.net.ConnectException: Connection timed out: connect



Ich deute das mal so:
Das bei der Registry abgeholte Objekt weiß dass die Registry auf 192.168.0.249 zu erreichen ist. Und der Client hält sich da auch dran. Nur dumm dass ich von außen nicht an die interne Adresse ran komme. 

Wieso nimmt der Client nicht die Adresse die ich ihm beim Naming.lookup mitgegeben habe? 

Eine Lösung wäre vermutlichdem Server zu sagen: Hör zu, die Registry ist nicht unter 192.168.0.249 zu erreichen, sondern unter meindyndnsname.homelinux.org. Dann würde der Server-Objekt-Methodenaufruf des Clients vermutlich auch klappen.

Aber 

1) hab ich kein Plan wie ich das anstelle
und
2) wäre das ganze für mich flexibler wenn ich am Server nicht erst die externe Adresse definieren müsste und der Client einfach die Adresse nimmt die ich ihm bei Naming.lookup gegeben hab.

Kann mir da jmd. weiterhelfen ?

- Alex

P.S. An einer Security-Einstellung kanns ja fast nicht liegen, da der Client tatsächlich die falsche Adresse benutzt



_L-ectron-X hat diesen Beitrag am 19.10.2007 um 12:51 editiert._
_Code-Tags eingefügt._


----------



## tuxedo (19. Okt 2007)

Okay,

wenn ich beim starten des Servers folgendes mit angebe:


```
-Djava.rmi.server.hostname=meindyndnsname.homelinux.org
```

...dann bekommt der Client im Server-Objekt diese Adresse mitgeteilt und benutzt die dann auch.

Im Normalfall funktioniert das ja. Aber ich hab da immer noch das "Problem" dass ich dem Server die öffentlich erreichbare Adresse geben muss und eine getunnelte Verbindung nicht funktioniert:

Ich tunnle vom Client-PC via SSH den Port 2000 zum Server (geht nur um einen speziellen Client, die anderen brauchen den Tunnel nicht). Die Verbindung muss ich am Client deshlab mit "localhost" aufbauen. Der erste Schritt geht wieder. Aber beim Aufrufen einer Servermethode will der sich ja zu "meindyndnsname.homelinux.org" verbinden (was ich ja am Server mit -D so angegeben habe). Aber das haut dann mit dem Tunnel nicht hin.

Hmmpf. Any ideas ?


[update]

Hier wird das gleiche Problem beschrieben.

Habe ich nur Clients die meindyndnsname.homelinux.org direkt erreichen -> Kein Problem
Habe ich nur Clients die meindyndnsname.homelinux.org via ssh-tunnel erreichen -> Kein Problem
Habe ich eine Mischung aus beidem: --> großes Problem

Die Idee mit dem geänderten hosts-File wäre eine Lösung. Hat nur einen Haken:
Das funktioniert nur bei Servern mit statischer IP. Grund:

Den Tunnel muss ich via IP-Adresse und nicht via Hostname aufbauen (weil sonst wird der hostname ja auch auf 127.0.0.1 umgelenkt). Und wenn ich einen Server mit dynamischer IP hab, dann weiß  ich die IP nur anhand des hostnamens, welcher aber via hosts-file auf 127.0.0.1 umgelenkt wird. --> schon wieder ein Problem.

Vielleicht hat ja noch jemand eine "geschickte" Lösung ?!


----------



## tuxedo (19. Okt 2007)

Kleine Verständnisfrage am Rande:




			
				JavaInsel hat gesagt.:
			
		

> Damit der Server jedoch Informationen an den Client zurückschicken kann, muss der Client selbst als Server auftreten.



WANN trifft das zu?

1) Client ruft eine Nicht-Void Methode am Server auf und erhält ein Ergebnis zurück
2) Client übergibt bei einem Servermethodenaufruf eine "Callback-Klasse" die von UnicastRemoteObject erbt und vom Server für Antworten an den Client genutzt werden kann

In beiden Fällen hab ich nur ein Objekt in der Registry stehen (sagt mir zumindest mein RmiRegistryInspector).

- Alex


----------



## L-ectron-X (19. Okt 2007)

alex0801 hat gesagt.:
			
		

> Eine Lösung wäre vermutlichdem Server zu sagen: Hör zu, die Registry ist nicht unter 192.168.0.249 zu erreichen, sondern unter meindyndnsname.homelinux.org. Dann würde der Server-Objekt-Methodenaufruf des Clients vermutlich auch klappen.


Das hatte ich auch schon versucht - vergebens. Ich habe bisher keine Möglichkeit gefunden, den Server von außen anzufragen.


----------



## tuxedo (20. Okt 2007)

Mir steht's mittlerweile bis hier *mit dem finger zeig*

RMI ist zwar ne schicke Sache, einfach zu programmieren. Aber in Sachen Netzwerke, Firewall und Tunnel ist das ganze ein Graus. 

Gibts alternativen zu RMI die da nicht so pingelig sind? 

Stehe nämlich kurz davor doch nen kleinen Socketserver und Client zu schreiben mit dem ich die paar Steueraufgaben meines Konferenzsystems erledige. Dem Socketserver ist das nämlich alles "Schnuppe". Port-Forwarding reicht da ja vollkommen aus. 

RMI ist für mich für's erste gestorben.

- Alex, der sich jetzt nach schicken alternativen umsieht


----------



## tuxedo (26. Okt 2007)

Also, ich hab das Problem weiter "analysiert"....


Sofern man offensichtlich keine Callback-Features mit RMI nutzt und nur vom Client zum Server die Remote-Methodenaufrufe stattfinden, scheint das ganze mit 


```
-Djava.rmi.server.hostname=meindyndnsname.homelinux.org
```

als Argument im JVM aufruf zu funktionieren. 

Gibt der Client dem Server jedoch ein Callback-Objekt mit, und sitzt der Client selbst hinter einem Router (NAT), dann kann der Server dem Client nicht antworten.

Doofe Sache. Scheinbar wird da eine neue Verbindung aufgebaut und nicht die bereits bestehende, die der Client geöffnet hat, benutzt.

Ich hab angefangen eine eigene RMI-Variante zu schreiben. Das delegieren der Methodenaufrufe zum Server funktioniert prima. 
Was noch fehlt sind die Callbacks.

Dazu muss ich aber Methoden-Argumente vor dem versenden "überwachen" und erkennen, wenn ein Callback-Objekt versendet wird. Bin da noch dran. Weioß nicht ob's ichs in einem Annahmbaren Zeitraum fertig kriege. Meine Diplomarbeit muss zuerst fertig werden.

Hätte jemand interesse an einer NAT-tauglichen, Callback-fähigen RMI-Alternative?

- Alex

- Alex


----------



## maki (26. Okt 2007)

Hi alex, bin gerade in einem Artikel über JERI gestolpert, vielleicht ist das ja was du suchst.

http://www.javaworld.com/javaworld/jw-12-2003/jw-1219-jiniology.html


----------

