Solved

JAVA - Port Forwarding Program

Posted on 2007-03-28
15
623 Views
Last Modified: 2008-01-09
I have COMPUTER A, B, C

Computer A connects to B while B is listening on port 1234 let's say.  Then B connects to C on port 23 for example.

I need to write a java program that will allow A and B to talk to B and C.  A port forwarding program.  Can someone show me examples because I'm having trouble with mine where the data only moves when I press keys on the keyboard.
0
Comment
Question by:jasonslogan
  • 6
  • 6
  • 2
  • +1
15 Comments
 
LVL 30

Expert Comment

by:mayankeagle
Comment Utility
Application B in this needs to act like a middleman or a hub in between A and C. You could look at designing it this way:

http://www.experts-exchange.com/Programming/Languages/Java/Q_21757720.html#16084277

0
 
LVL 30

Expert Comment

by:mayankeagle
Comment Utility
>> Can someone show me examples because I'm having trouble with mine where the data only moves when I press keys on the keyboard.

What problems?
0
 
LVL 26

Expert Comment

by:ksivananth
Comment Utility
I don't know why you forward the data in this way but I feel this is a good candidate for the pub/sub architecture than the P2P. Think of the JMS or Tibco Rendezvous.

Where in all the system( which interested in the data from publisher ) subscribe to a publisher( the one recieve data from external source ). Whenever the pub receives the data, it notifies the subs and then the subs make call to the pub to get the data!
0
 
LVL 10

Expert Comment

by:ADSLMark
Comment Utility
Ok, ive created a very simple example to show you how it can be done. It works, but error-handling etc is very bad. It's just a small *working* sketch. It does not close connections correctly, but you can build from this.
Three files:
Forwarder.java // this class connects a input port to an output port
Pipe.java // this class connects the input and output streams
Example.java // just a small example showing that it works, receives input from standard in, writes it to socket. It does not pipe the responses (one way port forwarding)

//Forwarder.java//
package pf;

import java.io.*;
import java.net.*;

class Forwarder
    extends Thread
{
    private ServerSocket in;
    private PrintWriter out;

    private int in_port;
    private int out_port;

    public Forwarder(int in_port)
        throws IOException
    {
        this.in_port = in_port;
        this.out_port = 0;
        this.in = new ServerSocket(in_port);
        this.out = new PrintWriter(System.out);
    }

    public Forwarder(int in_port, String out_host, int out_port)
        throws IOException
    {
        this.in_port = in_port;
        this.out_port = out_port;
        this.in = new ServerSocket(in_port);
        this.out = new PrintWriter(new Socket(out_host, out_port).getOutputStream(),true);
    }

    public void run()
    {
        try
        {
            System.out.println("Accepting connections on port "+in_port+" streaming to "+out_port);

            while(true)
            {
                Socket s = this.in.accept();
                BufferedReader s_in = new BufferedReader(new InputStreamReader(s.getInputStream()));
                Pipe p = new Pipe(s_in, this.out);
                p.start();
            }
        }
        catch(IOException ioe)
        {
            System.err.println("I/O exception");
        }
    }

    public static void main(String[] args)
        throws IOException
    {
        if(args.length == 3)
        {
            Forwarder fw = new Forwarder(Integer.parseInt(args[0])
                                        ,args[1]
                                        ,Integer.parseInt(args[2]));
            fw.start();
        }
        else if(args.length == 1)
        {
            Forwarder fw = new Forwarder(Integer.parseInt(args[0]));
            fw.start();
        }
        else
        {
            System.out.println("Usage: java pf.Forwarder <in port> [<host> <out port>]");
            return;
        }


    }
}
//--------------------//
//Pipe.java//
package pf;

import java.io.*;
import java.net.*;

class Pipe
    extends Thread
{
    private BufferedReader in;
    private PrintWriter out;

    public Pipe(BufferedReader in, PrintWriter out)
    {
        this.in = in;
        this.out = out;
    }

    public void run()
    {
        try
        {
            String line;
            while((line=in.readLine())!=null)
            {
                System.out.println(line);
                this.out.println(line);
            }
        }
        catch(IOException ioe)
        {
            System.err.println("I/O exception");
        }
    }
}
//--------------------//
//Example.java//
package pf;

import java.io.*;
import java.net.*;

public class Example
    extends Thread
{
    private Socket server;
    private BufferedReader in;
    private PrintWriter out;

    public Example(String host, int port)
        throws IOException
    {
        this.server = new Socket(host, port);
        this.in = new BufferedReader(new InputStreamReader(this.server.getInputStream()));
        this.out = new PrintWriter(this.server.getOutputStream(), true);
    }

    public void run()
    {
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String line;
            while((line=br.readLine())!=null)
                this.out.println(line);
        }
        catch(IOException ioe)
        {
            System.err.println("I/O exception");
        }
    }

    public static void main(String[] args)
        throws IOException
    {
        if(args.length == 2)
        {
            Example ex = new Example(args[0], Integer.parseInt(args[1]));
            ex.start();
        }
        else
        {
            System.out.println("Usage: java pf.Example <host> <out port>");
            return;
        }
    }
}
//--------------------//

This is how you run the example:
put everything in the same directory
compile with:
    javac *.java -d .
run first the 'terminal' node
    java portforwarder.Forwarder 9999
run a 'portforwarder' node
    java portforwarder.Forwarder 8888 localhost 9999
optional run another 'portforwarder' node
    java portforwarder.Forwarder 1234 localhost 8888
etc.
run the user interface:
   java portforwarder.Example localhost 1234

Enjoy!
Mark
0
 
LVL 1

Author Comment

by:jasonslogan
Comment Utility
Thank you all and especially Mark for providing an example.

Mark, is there a way to make this pass binary data instead of simply text?  AND THANK YOU for your quick response...

Jason
0
 
LVL 10

Expert Comment

by:ADSLMark
Comment Utility
Sure, just change all the streams into their corresponding byte streams...

Mark
0
 
LVL 1

Author Comment

by:jasonslogan
Comment Utility
I haven't done this in Java before...  What do I wrap the socket with like PrintWriter that will output byte streams?
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 10

Accepted Solution

by:
ADSLMark earned 500 total points
Comment Utility
Ok, updated the example. This is a lot more flexible and better code. It uses inputstream/outputstreams. It reads one byte and flushes it to the next stream etc.
Have a look:

//Example.java//
package pf;

import java.io.*;
import java.net.*;

public class Example
    extends Thread
{
    private Socket server;
    private InputStream in;
    private OutputStream out;

    public Example(String host, int port)
        throws IOException
    {
        this.server = new Socket(host, port);
        this.in = this.server.getInputStream();
        this.out = this.server.getOutputStream();
    }

    public void run()
    {
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

            String line;
            while((line=br.readLine())!=null)
            {
                this.out.write(line.getBytes());
                this.out.flush();
            }
        }
        catch(IOException ioe)
        {
            System.err.println("I/O exception");
        }
    }

    public static void main(String[] args)
        throws IOException
    {
        if(args.length == 2)
        {
            Example ex = new Example(args[0], Integer.parseInt(args[1]));
            ex.start();
        }
        else
        {
            System.out.println("Usage: java pf.Example <host> <port>");
            return;
        }
    }
}

//Forwarder.java//
package pf;

import java.io.*;
import java.net.*;

class Forwarder
    extends Thread
{
    private ServerSocket in_socket;
    private int in_port;

    private Socket out_socket;
    private OutputStream out;
    private String out_host;
    private int out_port;

    public Forwarder(int in_port, String out_host, int out_port)
        throws IOException
    {
        this.in_socket = new ServerSocket(in_port);
        this.in_port = in_port;

        this.out_socket = new Socket(out_host, out_port);
        this.out = this.out_socket.getOutputStream();
        this.out_host = out_host;
        this.out_port = out_port;
    }

    public void run()
    {
        try
        {
            System.out.println("Accepting connections on port "+in_port+" streaming to "+out_host+":"+out_port);

            while(true)
            {
                Socket s = this.in_socket.accept();
                Pipe p = new Pipe(s.getInputStream(), this.out);
                p.start();
            }
        }
        catch(IOException ioe)
        {
            System.err.println("I/O exception");
        }
    }

    public static void main(String[] args)
        throws IOException
    {
        if(args.length == 3)
        {
            Forwarder fw = new Forwarder(Integer.parseInt(args[0]),args[1],Integer.parseInt(args[2]));
            fw.start();
        }
        else
        {
            System.out.println("Usage: java pf.Forwarder <in_port> <host> <out_port>");
            return;
        }


    }
}

//Pipe.java//
package pf;

import java.io.*;
import java.net.*;

class Pipe
    extends Thread
{
    private InputStream in;
    private OutputStream out;

    public Pipe(InputStream in, OutputStream out)
    {
        this.in = in;
        this.out = out;
    }

    public void run()
    {
        try
        {
            int b;
            while((b=in.read()) > 0)
            {
                this.out.write(b);
                this.out.flush();
            }
        }
        catch(IOException ioe)
        {
            System.err.println("I/O exception");
        }
    }
}

//Terminal.java//
package pf;

import java.io.*;
import java.net.*;

class Terminal
    extends Thread
{
    private ServerSocket socket;
    private int port;

    private OutputStream out;

    public Terminal(int port)
        throws IOException
    {
        this.socket = new ServerSocket(port);
        this.port = port;

        this.out = System.out;
    }

    public void run()
    {
        try
        {
            System.out.println("Accepting connections on port "+port+".");

            while(true)
            {
                Socket s = this.socket.accept();
                Pipe p = new Pipe(s.getInputStream(), this.out);
                p.start();
            }
        }
        catch(IOException ioe)
        {
            System.err.println("I/O exception");
        }
    }

    public static void main(String[] args)
        throws IOException
    {
        if(args.length == 1)
        {
            Terminal tm = new Terminal(Integer.parseInt(args[0]));
            tm.start();
        }
        else
        {
            System.out.println("Usage: java pf.Terminal <port>");
            return;
        }
    }
}

It is a little bit different to start now. First you need a terminal, then forwarder(s) and then the cliet:
    java pf.Terminal 9999
    java pf.Forwarder 8888 localhost 9999
    java pf.Forwarder 7777 localhost 8888
    ...
    java pf.Forwarder 1111 localhost 2222
    java pf.Example localhost 1111

Good luck.
Mark
0
 
LVL 10

Expert Comment

by:ADSLMark
Comment Utility
Note that i convert the string into a byte array. You could also imagine the user giving a command like:

file <filename>

and that you then read this file and stream this to the socket. So although the example is basically the same, internally you can do more (ie. send byte arrays).

I hope this puts you in the right direction.
Mark
0
 
LVL 1

Author Comment

by:jasonslogan
Comment Utility
I was able to run it but it won't work for non text input.  My goal is to open a port on a server in a DMZ (1234 for example) then forward that to another computer behind the firewall say srv-trm:23

This way I can telnet to my server from the internet on port 1234 and it will give me the termserv server on it's port 23.

Your solution definitely works so I can make another question for this and give you additional points if you think that would be more fair.

Let me know what you would like.  I don't mind learning new things but I've never messed with streams over the internet much.  And the ones I did I used printwriter which converts everything to strings and I need pure byte data because there are a lot of characters that are sent in this emulation of my termserv server.
0
 
LVL 1

Author Comment

by:jasonslogan
Comment Utility
In your example I had to press enter for it to send.  I need something that will send anything to and from not depending on anything.  If something shows up in the read buffer send it along and so forth.
0
 
LVL 10

Expert Comment

by:ADSLMark
Comment Utility
ah :-) that's another problem.
Read this:
http://forum.java.sun.com/thread.jspa?threadID=677391&messageID=3953865

You can change the way input is send to the socket you connect to, but in my understanding its not possible to easily flush the input buffer with a console. If you had a gui around, then you can catch keyevents and whenever a key is pressed, just flush the buffer.
Anyway, the solution to send data through the pipeline is to call flush(). It completely depends on how and when you want to send data through this pipeline (does it really need to be after every byte? do you want to send commands? send binary files?).

If you really think you need a console application and want to process every keypress by flushing it through the pipeline, then you have to look at JNI to get it done. I think there are libraries out there which will do the job, but I truly doubt you really need them (if you did, you would probably know ;-) .. )

Mark
0
 
LVL 1

Author Comment

by:jasonslogan
Comment Utility
This is going to be used to forward all kinds of stuff.  Telnet apps, remote desktop on port 3389 and so forth.  My server would be listening on port 4000 then connects to a computer on the lan side on port 3389 to get remote desktop of a computer behind the firewall.  This is a way to get to your computer at work without installing any additional software on the workstations.

So as you see, I need something that will transmit data when there IS data to transmit in both directions.  Can that be done with Java?
0
 
LVL 1

Author Comment

by:jasonslogan
Comment Utility
Not sure if this will help but...

Have two things happening at the same time.  Have computer A transmitting data to C and C to A.  The data send by computer A could be anything I choose.  It could be listening on port 5000 and be talking to a computer internally on port 80 for a webserver.  I then browse with my browser http://whatever.com:5000 and it will connect to the internal server's web server and act as if all was normal.

I have a C program that does this but it is terrible.  It has not gui and it stops working and I have to start it over again and again.

Sorry I wasn't clear enough initially about my usage of this program.  I assumed if something could pass data period it could pass it the way I needed it.  Not just textual data like a chat program.
0
 
LVL 10

Expert Comment

by:ADSLMark
Comment Utility
Ok, so what I don't understand is why this solution doesn't work for you..
I agree, it only forwards and doesn't 'backwards' stuff, but I can fix that..
So, basically what I've written for you is this:
A class "Forwarder" and "Pipe" which setup a program which listens on some port X and outputs everything directly to some output port Y.
The example class is just an example, to show that it works. You can also run the Forwarder with some real applications and it will just forward those things.

For example, it should work if you setup your system like:
pc A runs a browser which connects to some server on port 5000.
pc B runs a Forwarder listening on port 5000 and forwards all data to port 80 on some pc C.
pc C receives the input from pc B.

Now, I will try to make the Forwarder bi-directional, sending data forward/backwards data. This solves your problem, no? You can replace the example class to anything you like......

Mark
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Suggested Solutions

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now