Solved

JAVA - Port Forwarding Program

Posted on 2007-03-28
15
630 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:Mayank S
ID: 18809007
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:Mayank S
ID: 18809010
>> 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
ID: 18810215
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
ID: 18810335
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
ID: 18810893
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
ID: 18811175
Sure, just change all the streams into their corresponding byte streams...

Mark
0
 
LVL 1

Author Comment

by:jasonslogan
ID: 18811351
I haven't done this in Java before...  What do I wrap the socket with like PrintWriter that will output byte streams?
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 10

Accepted Solution

by:
ADSLMark earned 500 total points
ID: 18811359
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
ID: 18811379
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
ID: 18811543
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
ID: 18811556
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
ID: 18811761
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
ID: 18815719
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
ID: 18815801
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
ID: 18817782
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
firstChar challenge 13 107
Java Filesystem manipulation of Word Docx file (find replace text) 3 65
backtracking recursion  code 19 53
expectj telnet failing 5 22
For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

911 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

20 Experts available now in Live!

Get 1:1 Help Now