1

I am trying to listen on a socket locally for use as an HTTP proxy and forward everything (TCP) to another HTTP proxy which is protected by mututal TLS.

I've looked around but found no libraries yet that could help me achieve this goal, so I opted for raw java.net.Socket. However, Socket & connection management is a pain, leading to 'socket closed' errors and most of the time no responses being received at all or connection resets. Is this the correct way to pass everything between two Sockets?

public class ThreadServer
implements Runnable
{
    private final ServerSocket inSocket;
    private final SSLSocketFactory socketFactory;
    private final String proxyHost;
    private final int proxyPort;

    public ThreadServer(final SSLSocketFactory socketFactory,
                        final String proxyHost, final int proxyPort,
                        final ServerSocket inSocket)
    {
        this.proxyHost = proxyHost;
        this.proxyPort = proxyPort;
        this.socketFactory = socketFactory;
        this.inSocket = inSocket;
    }

    private void process(Socket acceptSocket, Socket sendSocket)
    throws IOException
    {
        try (final InputStream inFromClient = acceptSocket.getInputStream();
             final OutputStream outToClient = acceptSocket.getOutputStream();
             final InputStream inFromServer = sendSocket.getInputStream();
             final OutputStream outToServer = sendSocket.getOutputStream())
        {
            new Thread(() -> {
                try {
                    // can blocking indefinetely so run in a separate Thread
                    inFromClient.transferTo(outToServer);
                } catch (IOException ignored) {}
            }).start();

            // now copy everything from response back to the client, blocking as wel
            inFromServer.transferTo(outToClient);
        } finally {
            acceptSocket.close();
            sendSocket.close();
        }
    }

    @Override
    public void run()
    {
        while (true) {
            try {
                Socket socket = this.inSocket.accept();
                Socket tlsSocket = socketFactory.createSocket(
                SocketFactory.getDefault().createSocket(proxyHost, proxyPort), proxyHost, proxyPort, true);
                process(socket, tlsSocket);
            } catch (IOException ignored) {}
        }
    }
}

1 Answers1

0

No, this is not the right way, because the server-side socket-handling is a mess.

Use a (rest / soap service) library, like jersey. Other libraries will do the same job, too. ;-)

Edit: Now, I'm understand. You need a TCP-Proxy / TCP-Tunnel. Yes, jersey is the wrong tool for you. But there are some TCP-Proxy written in java f.e. oksuz/tcp-proxy . Other people here at so asking for the same, I think Java tunnel and tcp proxy

Perhaps this could help you.

Mirko
  • 1,512
  • 1
  • 12
  • 19
  • completely agree, but examples I see from Jetty or Jersey all speak regular HTTP, while I would need a HTTP web Proxy protocol. (CONNECT and the like) – Niels Hofmans Sep 24 '20 at 05:48