2012-06-29 4 views
2

Я пытаюсь создать туннель для использования службы за брандмауэром, который поддерживает SSH. Я хотел получить полное решение в java, но я не могу заставить его работать. Я нашел этот github snip и основано на том, что я создал следующий код, чтобы фоновый поток дает мне туннель:SSH-порт с SSHj

// property on surrounding class 
// static final SSHClient sshclient = new SSHClient(); 

Thread thread = new Thread(new Runnable() { 

    @Override 
    public void run() { 
     try { 
      String host = "10.0.3.96"; 
      sshclient.useCompression(); 
      sshclient.addHostKeyVerifier("30:68:2a:20:21:9f:c8:e8:ac:b4:a7:fc:2d:a7:d0:26"); 
      sshclient.connect(host); 
      sshclient.authPassword("messy", "messy"); 
      if (!sshclient.isAuthenticated()) { 
       throw new RuntimeException(String.format("Unable to authenticate against '%s'", host)); 
      } 
      Forward forward = new Forward(8111); 
      InetSocketAddress addr = new InetSocketAddress("google.com", 80); 
      SocketForwardingConnectListener listener = new SocketForwardingConnectListener(addr); 

      sshclient.getRemotePortForwarder().bind(forward, listener); 
      sshclient.getTransport().setHeartbeatInterval(30); 

      HttpURLConnection con = (HttpURLConnection) new URL("http://localhost:8111").openConnection(); 
      con.setRequestMethod("GET"); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); 
      String line = null; 
      while((line = reader.readLine()) != null) { 
       System.out.println(line); 
      } 

      sshclient.getTransport().join(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     try { 
      if (sshclient != null && sshclient.isConnected()) { 
       sshclient.disconnect(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
}); 
thread.setDaemon(true); 
thread.start(); 

Проблема заключается в том, что если я подключиться к удаленному серверу SSH, как '10 .0.3.96' это делает не работа. Если я использую локальный SSH-сервер на моем локальном хосте, он будет работать. Я пробовал разные конфигурации с любой удачей и пытался отлаживать, но я не могу понять, что происходит внутри пакета SSHj.

Теперь это не должно быть решением SSHj, но это было бы предпочтительнее, так как другие части кода полностью реализованы и с использованием SSHj, и я не хочу смешивать два пакета SSH в одном проекте.

Спасибо за любую помощь.

+0

Определить, что «не работает». Что происходит вместо этого? – EJP

+0

Когда он не работает, HttpConnection, с которым я тестирую, выдает исключение, в котором говорится, что Connection отказано. Когда он работает, я печатаю, что google.com обслуживает содержимое. – CodeReaper

ответ

1

Попробуйте что-нибудь подобное. Он принимает список серверов для подключения. Он будет туннелировать каждое промежуточное соединение с последним сервером. Я не тестировал более двух серверов, но он должен работать. Этот ответ был адаптирован из более сложного проекта и написан в паре. Им нужно только импорт, чтобы заставить его работать в groovyconsole.

@Grab(group='net.schmizz', module='sshj', version='0.8.1') 
@Grab(group='org.bouncycastle', module='bcprov-jdk16', version='1.46') 

//the sequence of hosts that the connections will be made through 
def hosts = ["server1", "server2"] 
//the starting port for local port forwarding 
def startPort = 2222 
//username for connecting to all servers 
def username = 'user' 
def pw = 'pass' 

//--------------------------------------------------------------------------// 

final TunnelPortManager PORT_MANAGER = new TunnelPortManager() 

//list of all active port forwarders 
List<PortForwarder> portForwarders = [] 

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 

/** 
* Established the actual port forwarder 
*/ 
class PortForwarder extends Thread implements Closeable { 
    private final SSHClient sshClient; 
    private final InetSocketAddress remoteAddress; 
    private final ServerSocket localSocket; 
    private CountDownLatch latch = new CountDownLatch(1); 

    public PortForwarder(SSHClient sshClient, InetSocketAddress remoteAddress, ServerSocket localSocket) { 
     this.sshClient = sshClient; 
     this.remoteAddress = remoteAddress; 
     this.localSocket = localSocket; 
    } 

    private static String buildName(InetSocketAddress remoteAddress, Integer localPort) { 
     return "SSH local port forward thread [${localPort}:${remoteAddress.toString()}]" 
    } 

    @Override 
    public void run() { 
     LocalPortForwarder.Parameters params = new LocalPortForwarder.Parameters("127.0.0.1", localSocket.getLocalPort(), 
       remoteAddress.getHostName(), remoteAddress.getPort()); 
     LocalPortForwarder forwarder = sshClient.newLocalPortForwarder(params, localSocket); 
     try { 
      latch.countDown(); 
      forwarder.listen(); 
     } catch (IOException ignore) {/* OK. */} 
    } 

    @Override 
    public void close() throws IOException { 
     localSocket.close(); 
     try { 
      this.join(); 
     } catch (InterruptedException e) {/* OK.*/} 
    } 
} 

/** 
* Will hand out local ports available for port forwarding 
*/ 
class TunnelPortManager { 
    final int MAX_PORT = 65536 

    Set<Integer> portsHandedOut = new HashSet() 

    ServerSocket leaseNewPort(Integer startFrom) { 
     for (int port = startFrom; port < MAX_PORT; port++) { 
      if (isLeased(port)) { 
       continue; 
      } 

      ServerSocket socket = tryBind(port); 
      if (socket != null) { 
       portsHandedOut.add(port); 
       println "handing out port ${port} for local binding" 
       return socket; 
      } 
     } 
     throw new IllegalStateException("Could not find a single free port in the range [${startFrom}-${MAX_PORT}]..."); 
    } 

    synchronized void returnPort(ServerSocket socket) { 
     portsHandedOut.remove(socket.getLocalPort()); 
    } 

    private boolean isLeased(int port) { 
     return portsHandedOut.contains(port); 
    } 

    protected ServerSocket tryBind(int localPort) { 
     try { 
      ServerSocket ss = new ServerSocket(); 
      ss.setReuseAddress(true); 
      ss.bind(new InetSocketAddress("localhost", localPort)); 
      return ss; 
     } catch (IOException e) { 
      return null; 
     } 
    } 
} 


PortForwarder startForwarder(PortForwarder forwarderThread) { 
    forwarderThread.start(); 
    try { 
     forwarderThread.latch.await(); 
    } catch (InterruptedException e) { 
     Thread.currentThread().interrupt(); 
    } 
    return forwarderThread; 
} 


SSHClient getSSHClient(username, pw, String hostname, int port=22){ 
    SSHClient client = new SSHClient() 
    client.addHostKeyVerifier(new PromiscuousVerifier()) 
    client.connect(hostname, port) 
    client.authPassword(username, pw) 
    return client 
} 

int hostCount = hosts.size() 
String hostname = hosts[0] 

SSHClient client = getSSHClient(username, pw, hostname) 
println "making initial connection to ${hostname}" 

Session session 

//create port forwards up until the final 
for (int i=1; i<hostCount; i++){ 
    hostname = hosts[i] 
    println "creating connection to ${hostname}" 
    ServerSocket ss = PORT_MANAGER.leaseNewPort(startPort) 
    InetSocketAddress remoteAddress = new InetSocketAddress(hostname, 22) 

    PortForwarder forwarderThread = new PortForwarder(client, remoteAddress, ss) 
    forwarderThread = startForwarder(forwarderThread) 
    session = client.startSession() 

    println "adding port forward from local port ${ss.getLocalPort()} to ${remoteAddress.toString()}" 
    portForwarders.add(forwarderThread) 

    client = getSSHClient(username, pw, "127.0.0.1", ss.getLocalPort()) 
} 

session = client.startSession() 

//shut down the running jboss using the script 
Command cmd = session.exec("hostname") 
String response = IOUtils.readFully(cmd.getInputStream()).toString() 
cmd.join(5, TimeUnit.SECONDS) 
println "response -> ${response}" 

portForwarders.each { pf -> 
    pf.close() 
} 

session.close() 
client.disconnect() 
+0

Я просмотрел код и, кажется, звук. Однако я изменил работу и больше не имею доступа к проекту, где это было необходимо. Также я не слишком большой на groovy, поэтому мне может понадобиться кто-то, кто проверит это, прежде чем я смогу принять этот ответ. – CodeReaper

+0

groovy в значительной степени java +. Вы можете запустить java прямо в строке. Загрузите groovy, добавьте в путь, введите groovyconsole, вставьте код, добавьте импорт, запустите. – Scott

Смежные вопросы