Archived

This forum has been archived. Please start a new discussion on GitHub.

Ice connection through SSH tunnel

Hi all,
I'm new to Ice and want to write a client application. I have no control over the server part so I can't modify the source. All I have is a documentation about the implemented functions.

All I want to do now is tunnel my connection (not using glacier2) through SSH. The server endpoint port is 5000. If I forward my local port 5000 to the remote port 5000 everything works just fine. If I now want to bind remote port 5000 to local port 6000 my connection will fail after a short time (~1 function call). I monitored the connection with wireshark and somehow Ice changes the port from 6000 back to 5000 during communication.

I want to connect to multiple servers that all run on port 5000 through SSH tunnels . So I really want to use different ports on my local machine.

Is there a way to do this without using IceGrid(?) or anything that needs modification of the server part? Running glacier2 on the server host may not always be possible so that shouldn't be the optimal solution (except there is no other).

Thank you very much.

Comments

  • benoit
    benoit Rennes, France
    Hi Daniel,

    How do you create the proxies to invoke on the server? Does your client invoke on proxies returned by the server? Most likely, you need to ensure that the proxies the client uses contains the right port number. You can try printing out the proxies in your client to see if this is the case.

    Cheers,
    Benoit.
  • I create the proxies using the following code example:
    Ice.Communicator ic = Ice.Util.initialize();
    Ice.ObjectPrx base = ic.stringToProxy("Meta:tcp -h 127.0.0.1 -p 6000");
    prx = MetaPrxHelper.checkedCast(base);
    

    Remember:
    Server runs on port 5000. This port is tunneled through SSH to my local port 6000.
    Telnet confirms a connection can be established:
    $ telnet localhost 6000
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    IceP
    

    Printing the connection details afterwards using ic.proxyToString(base) gives me the host and port I've set. Even Wireshark confirms the connection was established and then reset as this Wireshark output shows:
    50	3.601336	127.0.0.1	127.0.0.1	TCP	47426 > 6000 [SYN] Seq=0 Win=32792 Len=0 MSS=16396 TSV=19650484 TSER=0 WS=6
    51	3.601364	127.0.0.1	127.0.0.1	TCP	6000 > 47426 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=16396 TSV=19650484 TSER=19650484 WS=6
    52	3.601382	127.0.0.1	127.0.0.1	TCP	47426 > 6000 [ACK] Seq=1 Ack=1 Win=32832 Len=0 TSV=19650484 TSER=19650484
    53	3.747270	127.0.0.1	127.0.0.1	ICEP	Validate connection
    54	3.747291	127.0.0.1	127.0.0.1	TCP	47426 > 6000 [ACK] Seq=1 Ack=15 Win=32832 Len=0 TSV=19650630 TSER=19650630
    55	3.747899	127.0.0.1	127.0.0.1	ICEP	Request(1): Meta.ice_isA()
    56	3.747942	127.0.0.1	127.0.0.1	TCP	6000 > 47426 [ACK] Seq=15 Ack=57 Win=32768 Len=0 TSV=19650630 TSER=19650630
    57	3.803796	127.0.0.1	127.0.0.1	ICEP	Reply(1): Success
    58	3.805437	127.0.0.1	127.0.0.1	ICEP	Request(2): Meta.getAllServers()
    59	3.805479	127.0.0.1	127.0.0.1	TCP	6000 > 47426 [ACK] Seq=41 Ack=104 Win=32768 Len=0 TSV=19650688 TSER=19650688
    60	3.860387	127.0.0.1	127.0.0.1	ICEP	Reply(2): Success
    [COLOR="Gray"]61	3.873074	127.0.0.1	127.0.0.1	TCP	42145 > 5000 [SYN] Seq=0 Win=32792 Len=0 MSS=16396 TSV=19650756 TSER=0 WS=6[/COLOR]
    [COLOR="DarkRed"]62	3.873101	127.0.0.1	127.0.0.1	TCP	5000 > 42145 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0[/COLOR]
    [COLOR="DimGray"]63	3.874895	127.0.0.1	127.0.0.1	TCP	42146 > 5000 [SYN] Seq=0 Win=32792 Len=0 MSS=16396 TSV=19650757 TSER=0 WS=6[/COLOR]
    [COLOR="DarkRed"]64	3.874913	127.0.0.1	127.0.0.1	TCP	5000 > 42146 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0[/COLOR]
    

    Note the last 4 colored lines. I'm no TCP protocol expert but somehow my client sends a SYN packet (packet 61 in the output above) to port 5000 (which isn't accessible on my machine) Of course this connection is being reset.
    Why does my client suddenly wants to connect to port 5000 (the port the server runs on) instead of the specified port 6000? Nowhere in my code is port 5000 specified. How does my client get this information? Does the server send it over and Ice recognizes a difference between my connection port and the port the server has sent and therefore tries to reconnect?

    Yes, if I use the same port on my machine for the tunnel as the server runs on (tunneling remote port 5000 to my local port 5000) everything works just fine. But as stated in post #1 that is not what I want to do.

    edit #2:
    The exception that is thrown after the connection failed (packet 64 in the output above)
    Ice.ConnectionRefusedException
        error = 0
    	at IceInternal.Network.doFinishConnect(Network.java:417)
    	at IceInternal.TcpTransceiver.initialize(TcpTransceiver.java:33)
    	at Ice.ConnectionI.initialize(ConnectionI.java:1536)
    	at Ice.ConnectionI.socketReady(ConnectionI.java:1116)
    	at Ice.ConnectionI$SocketReadyCallback.socketReady(ConnectionI.java:2299)
    	at IceInternal.SelectorThread.run(SelectorThread.java:203)
    	at IceInternal.SelectorThread$HelperThread.run(SelectorThread.java:273)
    Caused by: java.net.ConnectException: Connection refused
    	at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
    	at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:574)
    	at IceInternal.Network.doFinishConnect(Network.java:393)
    
  • You must make sure that your server publishes port 6000, and not port 5000, otherwise the proxy returned by checkedCast (and any other proxies returned by the server) will use port 5000. This is similar to configuring a server to work with NAT. See this FAQ for details.
  • Thank you very much. That answers all my questions.

    Support is really great even for those people with obvious questions like this one. Keep up the good work.