Collecting command responses from mocked SSH server (Apache MINA) - java

So what I'm trying to do, is create unit test that checks if invoked command (on shell via ssh connection) has a proper response. The problem is that I can't read those responses. There are not many tutorials regarding Apache MINA, so I thought maybe some of you could help me out. Here's a code
#Before
public void setUpSSHd() {
sshd=SshServer.setUpDefaultServer();
sshd.setPort(22999);
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
public boolean authenticate(String username, String password, ServerSession session) {
// TODO Auto-generated method stub
return true;
}
});
List<NamedFactory<KeyExchange>> keyExchangeFactories;
keyExchangeFactories = sshd.getKeyExchangeFactories();
sshd.setKeyExchangeFactories(keyExchangeFactories);
try {
sshd.start();
} catch (Exception e) {
e.printStackTrace();
}
}
#After
public void teardown() throws Exception { sshd.stop(); }
#Test
public void testCommands() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = null;
try {
session = client.connect("localhost", 22999).await().getSession();
session.authPassword("none", "none").await().isSuccess();
System.out.println("Connection established");
final ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
ByteArrayOutputStream sent = new ByteArrayOutputStream();
PipedOutputStream pipedIn = new TeePipedOutputStream(sent);
channel.setIn(new PipedInputStream(pipedIn));
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open();
pipedIn.write("dir\r\n".getBytes());
pipedIn.flush();
channel.waitFor(ClientChannel.CLOSED, 0);
channel.close(false);
client.stop();
System.out.println(out.toString());
} catch (Exception e) {
e.printStackTrace();
fail("Cannot establish a connection");
} finally {
if (session != null)
session.close(true);
}
}
For now I simply try to print out collected response. However I get empty string everytime I try to do that. I assume there might be a problem with ssh server configuration (what shell is it supposed to use?). The best scenario would be if I could define my own commands and responses on server side and then, only check it on client side
EDIT: I've tried to manually connect to this mocked ssh server but I've got
Unable to negotiate with ::1 port 22999: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
error message.

I would suggest you to update Apache SSH. Based the source repository the version 0.5.0 is 7 years old.
using your posted code with the default JCE provider and Apache SSH
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>0.5.0</version>
<dependency>
the connect with a ssh client fails with
Their offer: diffie-hellman-group1-sha1
using a more recent Apache SSH release
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>1.4.0</version>
<dependency>
the connect is successful

Related

Java HTTP/HTTPS Proxy Server

I'm writting my own Java Proxy Server. When I try to use it, I have the correct output (I see all commands that are going through the proxy server), but any website I want to visit doesn't work at all and I have the following error in my browser: ERR_TUNNEL_CONNECTION_FAILED. I don't actually good at network questions and there are some things I don't understand. So, there is my code below and I'll be really glad if someone tell me where is the problem:
import java.io.*;
import java.net.*;
public class ProxyServer
{
private String host;
private int localPort;
private int remotePort;
private ProxyServer(String host, int localPort, int remotePort)
{
this.host=host;
this.localPort=localPort;
this.remotePort=remotePort;
}
public static void main(String[] args) throws IOException
{
new ProxyServer("localhost", 8080, 9001).start();
}
public void start() throws IOException
{
System.out.println("Starting the proxy server for "+this.host+":"+this.localPort+"...");
ServerSocket ss=new ServerSocket(this.localPort);
final byte[] request=new byte[4096];
byte[] response=new byte[4096];
while(true)
{
Socket client=null;
Socket server=null;
try
{
client=ss.accept();
final InputStream streamFromClient=client.getInputStream();
OutputStream streamToClient=client.getOutputStream();
System.out.println(new BufferedReader(new InputStreamReader(streamFromClient)).readLine());
try
{
server=new Socket(host, this.remotePort);
}
catch(IOException exc)
{
PrintWriter out=new PrintWriter(streamToClient);
out.println("Proxy server cannot connect to "+host+":"+this.remotePort+"\n"+exc);
out.flush();
client.close();
continue;
}
InputStream streamFromServer=server.getInputStream();
final OutputStream streamToServer=server.getOutputStream();
System.out.println(new BufferedReader(new InputStreamReader(streamFromServer)).readLine());
new Thread
(
()->
{
int bytesRead;
try
{
while((bytesRead=streamFromClient.read(request))!=-1)
{
streamToServer.write(request, 0, bytesRead);
streamToServer.flush();
}
}
catch(IOException exc){}
try
{
streamToServer.close();
}
catch(IOException exc){}
}
).start();
int bytesRead;
try
{
while((bytesRead=streamFromServer.read(response))!=-1)
{
streamToClient.write(response, 0, bytesRead);
streamToClient.flush();
}
}
catch(IOException exc){}
streamToClient.close();
}
catch(IOException exc)
{
System.out.println(exc.getMessage());
}
finally
{
try
{
if(server!=null) server.close();
if(client!=null) client.close();
}
catch(IOException exc){}
}
}
}
}
You made simple tcp proxy with predefined hardcoded target: host:remote_port
It is not a HTTP proxy.
So your solution should work in case:
you are running squid or some proper HTTP proxy on
localhost:9001.
And use it as HTTP proxy only (I mean that when
you configure browser you should not tell it that your app is https
proxy).
If you plan to make standalone proxy then you need to analyze HTTP request and get host, port and protocol from request to know what server should you connect (including port) and which protocol you should use (i.e. http or https).
When browser request service directly (without proxy) it sends URI only and when browser sends request through proxy then it uses full URL in a request.
so first line in a request will be something like that:
GET http://google.com[:80]/blah-blah-blah HTTP/1.1
...headers here...
Your proxy need to analyze URL and get host, port and URI out of it.
So you would need to resolve domain name and connect to the host to required port with modified first line. It would look like:
GET /blah-blah-blah HTTP/1.1
...headers here...
And if you use extra http proxy server which listens on 9001 port then please check if it is in operational state.

Send files to server via FTPS protocol

I'm creating an app which generates a CSV file and some PDFs. I want my app to send those files to a server via FTPS protocol.
I'm using Apache Commons Net FTP library and it was perfectly working when I had "Require TLS session resumption on data connection when using PORT P" unchecked, but since I enabled it I can't send my files.
An error appeared :
450 TLS session of data connection has not resumed or the session does not match the control connection.
After some researches on this site I have overriden _prepareDataSocket_ in order to overcome this problem but now it just creates empty files on the server.
There is my overriden function :
#Override
protected void _prepareDataSocket_(final Socket socket) throws IOException {
if (socket instanceof SSLSocket) {
// Control socket is SSL
final SSLSession session = ((SSLSocket) _socket_).getSession();
if (session.isValid()) {
final SSLSessionContext context = session.getSessionContext();
try {
final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method method = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
method.setAccessible(true);
method.invoke(cache, String
.format("%s:%s", socket.getInetAddress().getHostName(), String.valueOf(socket.getPort()))
.toLowerCase(Locale.ROOT), session);
method.invoke(cache, String
.format("%s:%s", socket.getInetAddress().getHostAddress(), String.valueOf(socket.getPort()))
.toLowerCase(Locale.ROOT), session);
} catch (NoSuchFieldException e) {
throw new IOException(e);
} catch (Exception e) {
throw new IOException(e);
}
} else {
throw new IOException("Invalid SSL Session");
}
}
}
and this is what FileZilla Server displays:
FileZilla Response
will this answer on another forum help?
http://forum.rebex.net/5673/450-error-connecting-to-ftp-requiring-explicit-ftp-over-tls

Connection refused error when using sockets between C# (server) and Java (Client) applications

I am trying to create a socket connection between a .Net server application and Java Client Application.
I am getting an error from the java client application:
Connection refused: connect
Notes:
Communicating with a .Net Client Application, works fine.
I have disables the windows firewall
Undoubtedly, I am running the server application in the background and then I am running the client application
Following are my server code (C#):
public class Server
{
public Server()
{
CreateListener();
}
public void CreateListener()
{
// Create an instance of the TcpListener class.
TcpListener tcpListener = null;
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
string output;
try
{
// Set the listener on the local IP address
// and specify the port.
tcpListener = new TcpListener(ipAddress, 13);
tcpListener.Start();
output = "Waiting for a connection...";
}
catch (Exception e)
{
output = "Error: " + e.ToString();
MessageBox.Show(output);
}
}
}
and client application code (Java):
public class smtpClient {
public void Send() {
Socket smtpSocket = null;
DataOutputStream os = null;
DataInputStream is = null;
try {
smtpSocket = new Socket("localhost", 13); // FAILURE
os = new DataOutputStream(smtpSocket.getOutputStream());
is = new DataInputStream(smtpSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host: hostname");
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
It fails at the following line in the Java Client Application:
smtpSocket = new Socket("localhost", 13);
I can't tell what is the issue you are facing, but you need to start with a solid foundation to discover these issues.
As a rule of thumb, you should always write one piece (typically the server) first and verify connectivity (say using telnet) and then write the other piece (typically client) and verify its connectivity.
I always keep a Standard Client and Server handy to test whether its my code or its the environment/configuration.
Below is a sample code that works fine to test connectivity.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class ClientServer {
static void Main() {
new Thread(() => { StartServer("localhost", 5013); }).Start();
Thread.Sleep(100);
Console.WriteLine("\nPress enter to start the client...");
Console.ReadLine();
StartClient("localhost", 5013);
}
public static void StartServer(string serverInterface, int port) {
try {
IPHostEntry hostInfo = Dns.GetHostEntry(serverInterface);
string hostName = hostInfo.HostName;
IPAddress ipAddress = hostInfo.AddressList[0];
var server = new TcpListener(ipAddress, port);
server.Start();
Console.WriteLine($"Waiting for a connection at {server.LocalEndpoint}");
Console.WriteLine("Press ctrl+c to exit server...");
while (true) {
TcpClient client = server.AcceptTcpClient();
Console.WriteLine($"Server says - Client connected: {client.Client.RemoteEndPoint}");
ThreadPool.QueueUserWorkItem((state) => {
using (var _client = (TcpClient)state)
using (NetworkStream stream = _client.GetStream()) {
string msg = stream.ReadAsciiData();
if (msg == "Hello!") {
stream.WriteAsciiData($"Time:{DateTime.Now: yyyy/MM/dd HH:mm zzz}. Server name is {hostName}");
}
}
}, client);
}
} catch (Exception e) {
Console.WriteLine(e);
}
}
public static void StartClient(string serverInterface, int port) {
Console.WriteLine("Client started...");
try {
using (var client = new TcpClient(serverInterface, port))
using (NetworkStream stream = client.GetStream()) {
Console.WriteLine("Client says - Hello!");
stream.Write(Encoding.ASCII.GetBytes("Hello!"));
string msg = stream.ReadAsciiData();
Console.WriteLine($"Client says - Message from server: Server#{client.Client.RemoteEndPoint}: {msg}");
}
} catch (Exception e) {
Console.WriteLine(e);
}
Console.WriteLine("Client exited");
}
}
static class Utils {
public static void WriteAsciiData(this NetworkStream stream, string data) {
stream.Write(Encoding.ASCII.GetBytes(data));
}
public static string ReadAsciiData(this NetworkStream stream) {
var buffer = new byte[1024];
int read = stream.Read(buffer, 0, buffer.Length);
return Encoding.ASCII.GetString(buffer, 0, read);
}
public static void Write(this NetworkStream stream, byte[] data) {
stream.Write(data, 0, data.Length);
}
}
Now to your specific problem,
The choice of port 13, is not ideal for testing. Usually all ports below 1024 are considered privileged. i.e. a firewall or antivirus might block your attempt to listen on that port
Remember that IPV6 addresses plays a role. Your machine might have that enabled or disabled based on your configuration. You want to make sure that if your server is listening on a IPv6 interface, then your client also connects on the same
Which brings us to another related point: Irrespective of you are using IPv6 interface or not, the client needs to connect to the same interface the server is listening on. This might seem obvious, but is often missed. A typical machine
has at-least 2 interfaces: One for localhost (127...* called loopback interface) and another non local (typically 10...* or 192...*, but not restricted to it). It can so happen (especially when you pick the first available interface to bind your server without knowing which one it is) that server might be listening on non loopback interface like say 192.168.1.10 interface and the client might be connecting to 127.0.0.1, and you can see why the client will get "connection refused" errors
The sample code above works and you can test your code with it. You can us telnet for a client or just my sample code. You can play around changing the serverInterface values to some surprising discoveries which are accentuated by
ipAddress = hostInfo.AddressList[0] line
Hope this helps you with your debugging

MongoDB: check connection to DB

I'm looking for best way to check connection to Mongo DB.
Situation: client makes request (api) to server. And server returns status of all databases.
What the best way to do it?
I use this:
Builder o = MongoClientOptions.builder().connectTimeout(3000);
MongoClient mongo = new MongoClient(new ServerAddress("192.168.0.1", 3001), o.build());
try {
mongo.getAddress();
} catch (Exception e) {
System.out.println("Mongo is down");
mongo.close();
return;
}
In Java MongoDriver 3.3.0 use ServerMonitorListener to determine whether server is up and connected or not.
Here is the example code,
public class ServerConnection implements ServerMonitorListener {
private MongoClient client;
public ServerConnection(){
try {
MongoClientOptions clientOptions = new MongoClientOptions.Builder()
.addServerMonitorListener(this)
.build();
client = new MongoClient(new ServerAddress("localhost", 27017), clientOptions);
} catch (Exception ex) {
}
}
#Override
public void serverHearbeatStarted(ServerHeartbeatStartedEvent serverHeartbeatStartedEvent) {
// Ping Started
}
#Override
public void serverHeartbeatSucceeded(ServerHeartbeatSucceededEvent serverHeartbeatSucceededEvent) {
// Ping Succeed, Connected to server
}
#Override
public void serverHeartbeatFailed(ServerHeartbeatFailedEvent serverHeartbeatFailedEvent) {
// Ping failed, server down or connection lost
}
}
The ping command is a no-op used to test whether a server is responding to commands. This command will return immediately even if the server is write-locked:
try{
DBObject ping = new BasicDBObject("ping", "1");
mongoTemplate.getDb().getMongo().getDB("DATABASE NAME"").command(ping);
} catch (Exception exp){
// MongoDb is down..
}
Use MongoClient for Java, all the info you need is here...
http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-java-driver/
If I understand your question correctly you want to get state returned via a web service call. You can write a function that invokes db.serverStatus() and have it return the data. Check out the documentation here:
Monitoring for MongoDB

Java - File Transfer FTP to Remote Server(Apache MINA)

I am implementing a Java program,
which has to connect to remote server
connected remote server should download a file from ftp
i am using Apache MINA lib's for this code
here is code, which connects to the remote server
public class filetrans
{
public static void main(String[] args) throws IOException, InterruptedException
{
SshClient client = null;
String login="user";
String password="password";
try
{
client = SshClient.setUpDefaultClient();
client.start();
ConnectFuture future = client.connect("myhost",myport);
future.await();
ClientSession session = (ClientSession) future.getSession();
boolean auth = session.authPassword(login, password).await().isSuccess();
if (auth)
{
System.out.println("Authenticated....");
ClientChannel channel = session.createChannel("shell");
channel.setIn(new NoCloseInputStream(System.in));
channel.setOut(new NoCloseOutputStream(System.out));
channel.setErr(new NoCloseOutputStream(System.err));
channel.open();
channel.waitFor(ClientChannel.CLOSED, 5000);
channel.close(true);
}
else
{
System.out.println("Authentication failed....");
}
}
catch (Throwable t)
{
System.out.println(t);
}
finally
{
client.stop();
}
}
}
I am successfully connecting to the Remote server. now i have to connect to the FTP server and download a file and to save in the Remote Server. I am Stuck here, any ideas how to implement further or any codes or any suggestion will be great. thanks

Categories