How to implement (SSL/TLS) secure communication through normal Java Sockets - java

How can I secure ordinary socket communication? I wrote a Jabber client that can only connect to dedicated SSL ports(5223) (using SSLSocket). The normal way is to connect to Jabber standard port 5222 and request starttls. How can I achieve that?

I'm not completely sure what you are asking, but you can layer a secure socket on an existing normal (non-secure) socket by using the SSLSocketFactory.createSocket() method. This is one way to "upgrade" a socket using something like starttls. But this is doing things the hard way. Almost certainly your XMPP library will provide high-level access to this kind of functionality.

Expectation Management: I haven't tried this with Jabber. But it works with GMail's SMTP server, so maybe...
Here's how to upgrade a socket to an SSL socket, where socket is the original (non-TLS) connection:
SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(
socket,
socket.getInetAddress().getHostAddress(),
socket.getPort(),
true);
InputStream inputStream = sslSocket.getInputStream();
OutputStream outputStream = sslSocket.getOutputStream();
// reads from the socket
Scanner scanner = new Scanner(inputStream);
// writes to the socket
OutputStream outputStream = new BufferedOutputStream(outputStream);

Related

Is it good approach to make connection per message while designing distributed system over socket based network?

I am designing a distributed system by creating network using sockets in java. It has different threads which are communicating simultaneously with other servers. While designing distributed system or any network application which involves simultaneous connections is it good to create connections once and then communicating using io-streams or connections should be made and closed per message?
i dont think its a good idea to make a connection each time in when client wants to send a message because you have to wait untill server accept your connection.
//Server side code.
ServerSocket listener = new ServerSocket(9090);
Socket socket = listener.accept();
//client code
Socket s = new Socket(serverAddress, 9090);
you can create a single conection and use inputStreamReader in the rest of code to listen input and output from the both sides, that approach will make your app faster than creating a connection each time.
//client code
BufferedReader input =new BufferedReader(new InputStreamReader(s.getInputStream()));
//serverCode
PrintWriter out =new PrintWriter(socket.getOutputStream(), true);

Socket networking works only on localhost

I have created two separate programs, a client and a server. I tried testing them both within eclipse and running as runnable jars on the same (Windows) machine (localhost). It worked exactly as it should.
However, when I sent clinet (and later server) to a friend of mine to test it out, it didn't work. We made sure that ports were open (even on clients side), but to no avail. It didn't work. I would just get a timeout ConnectException.
The sockets I used were 50178-50180.
I have no idea what to think of it. Any ideas what might be going wrong?
This is the socket code:
(serverside)
serverSocket = new ServerSocket(50178);
while (true)
{
clientSocket = serverSocket.accept();
streamOut = clientSocket.getOutputStream();
objectOut = new ObjectOutputStream(streamOut);
streamIn = clientSocket.getInputStream();
objectIn = new ObjectInputStream(streamIn);
(stuff)
}
(clientside)
Socket socket = new Socket(ipAddress, 50178);
OutputStream streamOut = socket.getOutputStream();
DataOutputStream dataOut = new DataOutputStream(streamOut);
DataInputStream dataIn = new DataInputStream(socket.getInputStream());
I didn't include rest of the code since it I/O stuff (which does indeed work because it works over localhost).
EDIT:
I added requested code. I also tried it over two computer that were on the same network (witch local ip 192.168.1.*). It worked.
You may already be doing this, but I believe that a call to serverSocket.accept() must be done. This will tell the server that it needs to wait for a connection.
If you are doing that, my best answer to you would be to perform network troubleshooting. The computers must be able to see each other on the local area network in order to be able to use just the ip address. Make sure that there is not a firewall or something like that that is preventing the connection.
If you could add the code of where the client tries to connect and where the server accepts the connection, that may be helpful.

java server socket in cloud server

So I have two java classes for socket server and client as follows:
For the server:
System.out.println("Server started:");
ServerSocket server = new ServerSocket(1935, 0, InetAddress.getByName("localhost"));
Socket connection = new Socket();
while(active){
connection = server.accept();
printTimeStamp();
InputStream in = connection.getInputStream();
while(in.available() == 0){
//waiting till message is complete
}
MessageDecode(in);
}
MessageDecode is just an internal method that reads the input streams and stores it somewhere
for the client
Socket connectionSocket = new Socket();
InetAddress address = InetAddress.getByName("THE_CLOUD_SERVER_IP");
SocketAddress sAddress = new InetSocketAddress(address, 1935);
connectionSocket.setKeepAlive(true);
connectionSocket.setTcpNoDelay(true);
connectionSocket.connect(sAddress, 2000);
OutputStream os = connectionSocket.getOutputStream();
os.write("HELLO SERVER".getBytes());
os.close();
System.out.println("sent");
when I run both on a localhost it works like a charm, but when I run the class into the cloud server, I get timout exception java.net.SocketTimeoutException: connect timed out
even when the por is listening, I know its listening because when I run the app, and do a netstat -anp I get:
tcp 0 0 127.0.0.1:1935 0.0.0.0:* LISTEN PID/java
can someone give me a clue on how to solve this?
your help is must appreciated.
Thanks (._.')
As far as I know, cloud providers do not allow to open low level sockets (even WebSocket are rarely allowed). They usually use a proxy in front of the Java application server. Cloud providers are often used for HTTP application.
If you really want to use sockets, leave your current cloud provider and open an account on Amazon EC2.

SSL Socket connect timeout

How can I configure connect timeout for SSL Sockets in Java?
For plain sockets, I can simply create new socket instance without any target endpoint using new Socket(), and then call connect(SocketAddress endpoint, int timeout) method. With SSL sockets, I cannot create new SSLSocket() and SSLSocketFactory.getDefault().createSocket() method with no endpoint throws UnsupportedOperationException with Unconnected sockets not implemented message.
Is there a way to use connect timeouts for SSL Sockets in Java, using standard java libs only?
I believe you could use your current approach of creating the Socket and then connecting it. To establish SSL over the connection you could use SSLSocketFactory.createSocket
Returns a socket layered over an
existing socket connected to the named
host, at the given port.
This way you get full control over the connection and then you negociate setting up SSL on top of it. Please let me know if I misread your question.
With java 1.7 the following does not throw the exception stated in the question:
String host = "example.com";
int port = 12345;
int connectTimeout = 5000;
SSLSocket socket = (SSLSocket)SSLSocketFactory.getDefault().createSocket();
socket.connect(new InetSocketAddress(host, port), connectTimeout);
socket.startHandshake();
so it's business as usual.
Elaborating on #predi's answer, I found that I needed to use "setSoTimeout" too. Otherwise sometimes it gets stuck in the handshake (on very unstable connections):
final int connectTimeout = 30 * 1000;
SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
socket.setSoTimeout(connectTimeout);
socket.connect(new InetSocketAddress(hostAddress, port), connectTimeout);
socket.startHandshake();
socket.setSoTimeout(0);`

Why it cannot find getInputStream?

I have this code:
ServerSocket serverSideSocket = new ServerSocket(1234);
serverSideSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(serverSideSocket.getInputStream()));
And compiler writes me that it cannot find "getInputStream". I do not understand why. In the beginning of my code I do import java.net.*.
Calling of accept returns instance of Socket which has required method getInputStream.
The code might look like this:
ServerSocket serverSideSocket = new ServerSocket(1234);
Socket socket = serverSideSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Great tutorial how to work with sockets in java: http://java.sun.com/docs/books/tutorial/networking/sockets/index.html
This because conceptually a ServerSocket doesn't provide a direct connection object that can be used to send and receive data. A ServerSocket is a tool that you can use with the .accept() method to let it listen on the choosen port and generate a new real connection when a client tries to connect.
That's why you can't get an InputStream from a ServerSocket. Since many clients can connect to the same server, every client will make the server socket generate a new Socket (that is an opened TCP connection) that is returned from .accept() through which you can send and receive using its InputStream and OutputStream.

Categories