Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote port forwarding not working #239

Closed
anderserik opened this issue Mar 24, 2016 · 1 comment
Closed

Remote port forwarding not working #239

anderserik opened this issue Mar 24, 2016 · 1 comment

Comments

@anderserik
Copy link

Tested on commit c3f75cd
For the tests below, only remotehostPortForwarding() pass.


package com.hierynomus.sshj.connection.channel.forwarded;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URL;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import com.hierynomus.sshj.test.HttpServer;
import com.hierynomus.sshj.test.SshFixture;
import com.hierynomus.sshj.test.util.FileUtil;

import net.schmizz.sshj.DefaultConfig;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.connection.ConnectionException;
import net.schmizz.sshj.connection.channel.forwarded.RemotePortForwarder;
import net.schmizz.sshj.connection.channel.forwarded.RemotePortForwarder.Forward;
import net.schmizz.sshj.connection.channel.forwarded.SocketForwardingConnectListener;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;

public class RemotePortForwarderTest {

    // Credentials for an remote SSH Server to test against.
    private static final String REMOTE_HOST = "x.x.x.x";
    private static final String USER = "xxxx";
    private static final String PASSWORD = "yyyy";

    private static final int UPPER_RPF_PORT = 9999;
    private static final int LOWER_RPF_PORT = 9000;
    private static final AtomicInteger RPF_PORT = new AtomicInteger(LOWER_RPF_PORT);
    private static final InetSocketAddress HTTP_SERVER_SOCKET_ADDR = new InetSocketAddress("127.0.0.1", 8080);

    @Rule
    public SshFixture fixture = new SshFixture();

    @Rule
    public HttpServer httpServer = new HttpServer();

    @Before
    public void setup() throws IOException {
        fixture.getServer().setTcpipForwardingFilter(new AcceptAllForwardingFilter());
        File file = httpServer.getDocRoot().newFile("index.html");
        FileUtil.writeToFile(file, "<html><head/><body><h1>Hi!</h1></body></html>");
    }

    @Test
    public void localhostDynamicPortForwarding() throws IOException {
        SSHClient sshClient = getFixtureClient();
        int remotePort = shouldDynamicallyForwardPort(sshClient);
        httpGet("127.0.0.1", remotePort);
    }

    @Test
    public void remotehostDynamicPortForwarding() throws IOException {
        SSHClient sshClient = getClient();
        int remotePort = shouldDynamicallyForwardPort(sshClient);
        httpGet(REMOTE_HOST, remotePort);
        sshClient.disconnect();
    }

    @Test
    public void localhostPortForwarding() throws IOException {
        SSHClient sshClient = getFixtureClient();
        int remotePort = shouldForwardPort(sshClient);
        httpGet("127.0.0.1", remotePort);
    }

    @Test
    public void remotehostPortForwarding() throws IOException {
        SSHClient sshClient = getClient();
        int remotePort = shouldForwardPort(sshClient);
        httpGet(REMOTE_HOST, remotePort);
        sshClient.disconnect();
    }

    @Test
    public void httpTest() throws IOException {
        // Just to check that we have a working http server...
        httpGet("127.0.0.1", 8080);
    }

    private int shouldDynamicallyForwardPort(SSHClient sshClient) throws IOException {
        Forward forward = sshClient.getRemotePortForwarder().bind(
                // where the server should listen
                new RemotePortForwarder.Forward(0),
                // what we do with incoming connections that are forwarded to us
                new SocketForwardingConnectListener(HTTP_SERVER_SOCKET_ADDR));

        return forward.getPort();
    }

    private int shouldForwardPort(SSHClient sshClient) throws IOException {
        boolean portTaken = true;
        Forward forward = null;
        while (portTaken) {
            try {
                forward = sshClient.getRemotePortForwarder().bind(
                        // where the server should listen
                        new RemotePortForwarder.Forward(RPF_PORT.getAndIncrement()),
                        // what we do with incoming connections that are forwarded to us
                        new SocketForwardingConnectListener(HTTP_SERVER_SOCKET_ADDR));
                portTaken = false;
            } catch (ConnectionException e) {
                if (RPF_PORT.get() >= UPPER_RPF_PORT) {
                    System.out.println("Reached upper limit for remote port forwarder ports: " + UPPER_RPF_PORT);
                    throw e;
                }
                System.out.println(
                        "Failed to bind an remote port forwarder to port " + RPF_PORT.get() + "trying a new port");
            }
        }

        return forward.getPort();
    }

    private void httpGet(String server, int port) throws IOException {
        String urlString = "http://" + server + ":" + port;
        System.out.println("Trying: GET " + urlString);
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(1_000);
        connection.setRequestMethod("GET");
        assertEquals("Didn't get 200 OK", 200, connection.getResponseCode());
    }

    private SSHClient getClient() throws IOException {
        SSHClient sshClient = new SSHClient(new DefaultConfig());
        sshClient.addHostKeyVerifier(new PromiscuousVerifier());
        sshClient.loadKnownHosts();
        sshClient.connect(REMOTE_HOST, 22);
        sshClient.authPassword(USER, PASSWORD);

        return sshClient;
    }

    private SSHClient getFixtureClient() throws IOException {
        SSHClient sshClient = fixture.setupConnectedDefaultClient();
        sshClient.authPassword("jeroen", "jeroen");

        return sshClient;
    }
}

@hierynomus
Copy link
Owner

Thanks for checking the initial work. As you can see there was a bug in the lookup. Should be fully fixed now ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants