Skip to content

Instantly share code, notes, and snippets.

@ilmich
Created May 9, 2017 17:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ilmich/27b0e8b1aa3b400b9df0894166786b89 to your computer and use it in GitHub Desktop.
Save ilmich/27b0e8b1aa3b400b9df0894166786b89 to your computer and use it in GitHub Desktop.
Java NIO tcp tunnel
package ctptunnel;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class NioProxy {
// mappa client remoto - server remoto
private Map<SocketChannel, SocketChannel> proxy = new HashMap<SocketChannel, SocketChannel>();
private static final int BYTE_BUFFER_SIZE = 8192;
public void serve() {
try {
Selector serverSelector = Selector.open();
Selector remoteSelector = Selector.open();
ServerSocketChannel sChannel = ServerSocketChannel.open();
sChannel.configureBlocking(false);
sChannel.socket().bind(new InetSocketAddress(9090));
sChannel.register(serverSelector, SelectionKey.OP_ACCEPT);
while (true) {
if (serverSelector.select(1) > 0) {
Iterator<SelectionKey> iter = serverSelector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
if (key.isValid() && key.isAcceptable()) {
SocketChannel sc = sChannel.accept();
sc.configureBlocking(false);
sc.finishConnect();
System.out.println("Accept remote connection from " + sc.socket().getRemoteSocketAddress().toString());
//apro connessione verso sistema esterno
try {
SocketChannel forwardTo = SocketChannel.open(new InetSocketAddress("localhost", 2080));
forwardTo.configureBlocking(false);
forwardTo.finishConnect();
forwardTo.register(remoteSelector, SelectionKey.OP_READ);
proxy.put(sc, forwardTo);
} catch (IOException e) {
System.out.println("Errore connessione remota");
sc.close();
break;
}
sc.register(serverSelector, SelectionKey.OP_READ);
key.interestOps(SelectionKey.OP_ACCEPT);
}
if (key.isValid() && key.isReadable()) {
SocketChannel remote = (SocketChannel) key.channel();
//prendo il canale remoto
SocketChannel forwardTo = proxy.get(key.channel());
ByteBuffer bb = ByteBuffer.allocateDirect(BYTE_BUFFER_SIZE);
int read = remote.read(bb);
if (read < 0) { // il client si è disconnesso
forwardTo.close();
proxy.remove(remote);
}
if (read > 0) { //client manda dati
bb.flip();
forwardTo.write(bb);
remote.register(serverSelector, SelectionKey.OP_READ);
}
}
}
}
if (remoteSelector.select(1) > 0) {
Iterator<SelectionKey> iter = remoteSelector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
if (key.isValid() && key.isReadable()) { // leggo dal server remoto
ByteBuffer bb = ByteBuffer.allocateDirect(BYTE_BUFFER_SIZE);
SocketChannel forwardTo = (SocketChannel) key.channel();
int read = forwardTo.read(bb);
SocketChannel remoteClient = null;
for (SocketChannel remoteChannel : proxy.keySet()) {
if (proxy.get(remoteChannel).equals(forwardTo)){
remoteClient = remoteChannel;
if (read > 0) {
bb.flip();
remoteClient.write(bb);
} else { //server disconnesso
proxy.remove(remoteClient);
remoteClient.close();
}
break;
}
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
new NioProxy().serve();
}
}
@fioli
Copy link

fioli commented May 10, 2017

ok. la mia curiosità era sulla casistica d'utilizzo, ossia: quand'è che un client non può parlare direttamente con un server in SSL , ma deve passare per il tunnel?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment