simple forward proxy for any protocol - java

I am wanting to develop a centralized java server that accepts multiple connections for any type of network traffic IE FTP, HTTP, HTTPS, RDP, etc. The only goal is to forward it off to the expected destination and return the response back to the requester. I have no idea where to start with this because the only information I am finding is related to forwarding java servlet requests and some info on forwarding HTTP. Is there anyway to simply forward it off, or would it require handling every protocol differently?
public void run () {
InetSocketAddress address = (InetSocketAddress)this.socket.getRemoteSocketAddress();
try {
InputStreamReader isr = new InputStreamReader(this.socket.getInputStream());
BufferedReader br = new BufferedReader(isr);
OutputStream os = this.socket.getOutputStream();
String ipAddress = address.getHostName();
Log.d("client","A client has connected from: "+ipAddress);
//TODO forward the client inputstream to the destination
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
this.socket.close();
} catch (Exception e) {}
}
}

Every protocol is different, unless you want to, and can, force them all into one straightjacket like HTTP's CONNECT verb. You will have to research what proxy protocols the intended clients are capable of using.
More probably you should be looking at using SOCKS, in an existing implementation.

Related

I'm misunderstanding something on how to set up sockets, but I'm not suer if it's client side, server side, or both

I'm setting up a simple program to test starting a server, and I'm getting a silent failure state. My client seems to think it has sent, while my server doesn't think it's recieving. The two are managing the initial connection, it's just sending things after that where it's failing.
I've cut things down to the core of where it's currently failing I think.
Here's part of the Client code
public void Client (int port, String ip)
{
try {
sock = new Socket(ip, port);
System.out.println("Found the server.");
streamInput = new DataInputStream(sock.getInputStream());
// sends output to the socket
streamOutput = new DataOutputStream(
sock.getOutputStream());
streamOutput.writeChars("Client Begining Conversation");
System.out.println(streamInput.readUTF());
}
catch (UnknownHostException u) {
System.out.println(u);
return;
}
catch (IOException i) {
System.out.println(i);
return;
}
}
public static void main(String[] args) throws IOException {
// create the frame
try {
ClientGui main = new ClientGui();
main.Client(8000,"127.0.0.1");
main.show(true);
} catch (Exception e) {e.printStackTrace();}
Here's server code.
public Server(int port) throws Exception
{
ServerSocket gameServer = new ServerSocket(port);
Socket gameSocket = gameServer.accept();
System.out.println("Client has connected");
// to send data to the client
PrintStream dataOutput
= new PrintStream(gameSocket.getOutputStream());
// to read data coming from the client
BufferedReader reader = new BufferedReader( new InputStreamReader(
gameSocket.getInputStream()
));
//play logic
Play(reader,dataOutput);
public void Play(BufferedReader reader, PrintStream dataOutput) throws Exception
{
String received, textSent;
System.out.println("Waiting for response.");
received = reader.readLine();
System.out.println("Client has responded");
//contenue until 'Exit' is sent
while (received != "Exit" || received != "exit") {
System.out.println(received);
textSent = received + "recieved";
// send to client
dataOutput.println(textSent);
}
}
My client gets to here -
Found the server.
and my server gets to here -
Trying to start server.
Client has connected
Waiting for response.
At which point, it just hangs forever, each side waiting for the other. It doesn't throw an error, it just... waits until I force it closed.
So it appears that I'm either doing something wrong when I send with "streamOutput.writeChars" in my client, or I'm doing something wrong when I receive with my server with "reader.readLine();", but I can't figure out what.
Or I could be doing something more fundamentally wrong.
The problem is that reader.readLine() doesn’t return until it sees a new line character, but streamOutput.writeChars("Client Begining Conversation") doesn’t send one.
More generally, mixing a DataOutputStream on the client with a BufferedReader on the server won’t work reliably, as the latter expects plain text, while the former produces formatted binary data. For example, the character encoding might not match. The same applies to communication in the opposite direction with PrintStream and DataInputStream. It’s best to pick either a text based or binary protocol and then be consistent about the pair of classes used on both the client and server.
In the case of a text protocol, an explicit character encoding should be defined, as the default can vary between platforms. As a learning exercise, it might not matter, but it’s a good practice to be explicit about specifying a character encoding whenever handling networked communication. UTF-8 is a good choice unless there’s a specific reason to use another one.
In addition, it is generally preferred to use PrintWriter instead of PrintStream for text output in new code. Read this answer for an explanation.

Java HTTP/1.1 GET request BufferedReader readLine never stops

Hello I'm making an HTTP client. I'm trying to fetch google.com's html code. I have a problem the the BufferedReader.readLine() function is blocking endlessly because the remote server apparently doesn't send a blank line? Or could it be that my request is wrong?
Appreciate any help!
public static void main(String[] args) {
String uri = "www.google.com";
int port = 80;
Socket socket = new Socket(uri, port);
PrintWriter toServer = new PrintWriter(socket.getOutputStream(), true);
InputStream inputStream = socket.getInputStream();
get(uri, port, language, socket, toServer, inputStream);
}
public static void get(String uri, int port, String language, Socket socket, PrintWriter toServer, InputStream inputStream) {
try {
toServer.println("GET / HTTP/1.1");
toServer.println("Host: " + uri + ":" + port);
toServer.println();
// Parse header
StringBuilder stringBuilder = new StringBuilder();
BufferedReader fromServer = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = fromServer.readLine()) != null) {
stringBuilder.append(line);
}
System.out.println("done");
} catch (IOException e) {
e.printStackTrace();
}
}
You are sending a HTTP/1.1 request which by default enables HTTP keep-alive. This means that the server might keep the TCP connection open after the response was sent in order to accept more requests from the client. Your code instead assumes that the server will close the connection after the response was finished by explicitly expecting readline to return null. But since the server will not close the connection (or only after some long timeout) the readline will just block.
To fix this either use HTTP/1.0 (which has keep-alive off by default) instead of HTTP/1.1 or explicitly tell the server that no more requests will be send by adding a Connection: close header.
Please note that in general HTTP is way more complex than you might think if you've just seen a few examples. The problem you face in your question is only a glimpse into more problems which you will face when continuing this path. If you really want to implement your own HTTP handling instead of using established libraries please study the actual standard instead of just assuming a specific behavior.

Monitor All outgoing/Incoming packet from a specific port

I'm trying to monitor a port to get the outgoing/incoming packets (or sockets) from my PC using Java, more like what Wireshark does.
I'm using this code:
int portNumber = 5816;
try {
System.out.println("New ServerSocket...");
ServerSocket serverSocket = new ServerSocket(portNumber);
serverSocket.setSoTimeout(5000);
System.out.println("Accepting...");
serverSocket.accept();
System.out.println("Done Accepting.");
} catch (IOException e) {
System.out.println(e.getMessage());
}
Now I can see the packets using Wireshark, and I can see the connection is established using Process Hacker 2, but I always get this output:
New ServerSocket... Accepting... Accept timed out
EDIT:
The question,
I got an application installed, that exchange packets with an external server (nor the client or the server are mine), i just want to intercept these packets and log them.
and they are using 5816 port.
Wireshark is using pcap library to intercept network communication. You can use pcap wrapper for java to achieve similar functionality.
Note:
You are not closing sockets. However, this code is still incorrect approach to achieve your goal.
int portNumber = 5816;
System.out.println("New ServerSocket...");
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
serverSocket.setSoTimeout(5000);
System.out.println("Accepting...");
try(Socket socket = serverSocket.accept()) {
System.out.println("Done Accepting.");
}
} catch (IOException e) {
System.out.println(e.getMessage());
}

How to exit/disconnect from telnet properly?

Im telneting into a server and it will block the port if I do not disconnect properly. Im already using socket.close(); so I am not sure what I am doing wrong to disconnect completely from the server
//java socket client example
import java.io.*;
import java.net.*;
public class socket_client {
public static void main(String[] args) throws IOException {
Socket s = new Socket();
String host = "1.1.1.1";
PrintWriter s_out = null;
BufferedReader s_in = null;
try {
s.connect(new InetSocketAddress(host, 12656));
System.out.println("Connected");
// writer for socket
s_out = new PrintWriter(s.getOutputStream(), true);
// reader for socket
s_in = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
// Host not found
catch (UnknownHostException e) {
System.err.println("Don't know about host : " + host);
System.exit(1);
}
// Send message to server
String message = "this is the msg";
s_out.println(message);
System.out.println("Message send");
// Get response from server
String response;
while ((response = s_in.readLine()) != null) {
System.out.println(response);
}
// close the socket
s.close();
// close the i/o streams
s_out.close();
s_in.close();
}
}
There is no disconnect sub-protocol in Telnet. All you have to do is close the socket.
I've never seen or heard of a Telnet server 'block a port if I do not disconnect properly'. I have a production Telnet client which does only that, and which has been working correctly for five or six years. And any server at all that doesn't handle unexpected disconnections properly has something very seriously wrong with it.
The problem is elsewhere, possibly in the (unspecified) server itself. To behave as you describe, it would have to completely ignore end of stream conditions, and ignore IOExceptions as well (or else treat them as completely fatal to the entire process). It would also have to be single-threaded. I'm finding it rather difficult to believe in the existence of such a server, or indeed this problem.
NB you only need to close 's_out', the outermost stream/writer you've wrapped around the socket output stream. If you must close the input stream and the socket, do so after closing the output stream/writer.
The socket is blocked since the server side is not handling unexpected socket closing. You have two alternatives - or rather, two steps, if you want to be thorough - to fixing this.
Handle the other end of the connection closing unexpectedly in an
exception handler, and closing the socket when needed.
Having the client send a message to the server when it wants to
close the connection, allowing the server to close the socket, and
then handling that closed socket as a successful operation.
This is an example of server socket code from O'Reilly that gracefully handles unexpected termination:
try {
ServerSocket server = new ServerSocket(5776);
while (true) {
Socket connection = server.accept( );
try {
OutputStreamWriter out
= new OutputStreamWriter(connection.getOutputStream( ));
out.write("You've connected to this server. Bye-bye now.\r\n");
connection.close( );
}
catch (IOException e) {
// This tends to be a transitory error for this one connection;
// e.g. the client broke the connection early. Consequently,
// we don't want to break the loop or print an error message.
// However, you might choose to log this exception in an error log.
}
finally {
// Most servers will want to guarantee that sockets are closed
// when complete.
try {
if (connection != null) connection.close( );
}
catch (IOException e) {}
}
}
catch (IOException e) {
System.err.println(e);
}

Checking for a client disconnect on a Java TCP server - output only

I have a Java TCP server which, when a client connects to it, outputs a message to the client every 30 seconds. It is a strict requirement that the client does not send any messages to the server, and that the server does not send any data other than the 30-second interval messages to the client.
When I disconnect the client, the server will not realise this until the next time it tries to write to the client. So it can take up to 30 seconds for the server to recognise the disconnect.
What I want to do is check for the disconnect every few seconds without having to wait, but I am not sure how to do this given that a) the server does not receive from the client and b) the server cannot send any other data. Would anyone please be able to shed some light on this? Thanks.
Even though your server doesn't "receive" from the client, a non-blocking read on the client socket will tell you that either there's nothing to be read (as you expect), or that the client has disconnected.
If you're using NIO you can simply use a non-blocking Selector loop (with non-blocking sockets) and only write on your 30 second marks. If a SelectionKey is readable and the read on the SocketChannel returns -1 you know the client has disconnected.
EDIT: Another approach with blocking is simply to select with a 30 second timeout. Any client disconnects will cause the select to return and you'll know which ones those are via the read set. The additional thing you'd need to do there is track how long you were blocked in the select to figure out when to do your writes on the 30 second mark (Setting the timeout for the next select to the delta).
Big Edit: After talking to Myn below, offering complete example:
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
// Set a 1 second timeout on the socket
clientSocket.setSoTimeout(1000);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
long myNextOutputTime = System.currentTimeMillis() + 30000;
String inputLine = null;
boolean connected = true;
while (connected)
{
try {
inputLine = in.readLine();
if (inputLine == null)
{
System.out.println("Client Disconnected!");
connected = false;
}
}
catch(java.net.SocketTimeoutException e)
{
System.out.println("Timed out trying to read from socket");
}
if (connected && (System.currentTimeMillis() - myNextOutputTime > 0))
{
out.println("My Message to the client");
myNextOutputTime += 30000;
}
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
Worth noting here is that the PrintWriter really moves you far away from the actual socket, and you're not going to catch the socket disconnect on the write (It will never throw an exception, you have to manually check it with checkError()) You could change to using a BufferedWriter instead (requires using flush() to push the output) and handling it like the BufferedReader to catch a disco on the write.
If you are managing multiple clients then I guess you would be using Non-Blocking sockets (If not then consider using Non-Blocking). You can use Selector to monitor all the connected sockets to check if they are readable or writeable or there is some Error on that socket. When some client disconnects, your Selector will mark that socket and will return.
For more help google "Socket Select function"

Categories

Resources