What is execProt("P") in Apache Commons net? - java

I have setup an FTPS server on my aws ec2 instance. I am using Apache Commons net to connect programmatically to my server.
try
{
ftps.enterLocalPassiveMode();
ftps.setBufferSize(1000);
ftps.execPROT("P");
if (!ftps.login(username, password))
{
ftps.logout();
error = true;
break __main;
}
}
I cannot retrieve files if I don't set execProt("P"). From their documentation, I see that "P" stands for Private Data Channel Protection Level. What does this mean? Why am I using P instead of "S" or "E"?

The PROT command in ftps can have the values P and C. P stands for private and means that the data connection is encrypted with TLS. C stands for clear and means that the data connection is not encrypted. The values of E (confidential) and S (safe) are defined too but in practice not implemented in FTP servers. For more details see the specification, i.e. RFC 4217.

Related

Update ReplicaSet using Java Kubernetes Client

I am writing a client that manages Kubernetes objects. Is it possible to update ReplicaSets using a Java client?
Yes, you can update ReplicaSet using Java Kubernetes Client. Depending on which Kubernetes client you use here are the code snippets.
Kubernetes Java Client
AppsV1Api api = new AppsV1Api();
api.patchNamespacedReplicaSet(...);
Fabric8 Kubernetes & OpenShift Java Client
KubernetesClient client = new DefaultKubernetesClient();
client.apps().replicaSets().createOrReplace(...);
I was just doing this this morning!
Yes you can do that. Checkout Fabric8 Kubernetes client for Java (https://github.com/fabric8io/kubernetes-client/blob/master/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicaSetTest.java)
An example of the change would be:
try (KubernetesClient k8sClient = new DefaultKubernetesClient()) {
ReplicaSetList list = k8sClient.apps().replicaSets().inNamespace("default").list();
for (ReplicaSet next : list.getItems()) {
next.getSpec().setReplicas(10);
k8sClient.apps().replicaSets().create(next);
}
} catch (Exception e) {
//TODO: logging
}
Just be sure to use the correct one. In this example I am changing all of them in the default namespace.

Use "RETR" FTP command with Apache Common's FTPClient

I'm working on an Android app (Java 8, target API=27) that downloads files from an FTP server (using Apache Common's FTPClient) but I'm experiencing a big problem with missing bytes with the retrieveFile and retrieveFileStream methods.
That's why I want to try the alternative of sending the actual commands:
//login
String path = remoteFolder + "/" + filename;
if(ftpClient.isConnected()) {
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE); //For images,...
ftpClient.retr(path); //sends the "RETR" command
String reply = ftpClient.getReplyString();
Log.d(TAG,reply);
}
This prints:
150 Opening BINARY mode data connection.
But what now?
ftpClient.getReplyStrings().length is 1 and it's the same text. Usually I'd send the RETR command on the command socket, then read the data socket's reply (= the contents of the e.g. txt file) but there don't seem to be different, openly accesible sockets in this library.
Question: How do I get the contents of the file "manually" - so using the FTP commands but without using the retrieveFile... methods (if possible)?
Before sending RETR, you need to send PASV, EPSV, PORT or EPRT and parse its response. Typically you would use PASV, for which there's FTP.pasv method.
The next would to be open the data connection, based on the response to the PASV (and only then you send RETR).
But implementing the data connection is lot of work. And the FTPClient implementation of the data connection is hidden in a protected _openDataConnection_ method. So you cannot reuse the standard implementation. You will have to use generic Socket class.
And only then you can call FTP.retr (which does not do much on its own).
This is all a bad idea. But if you want to do it, check the implementation of FTPClient.retrieveFile – It's all there.
The FTPClient.retrieveFile and FTPClient.retrieveFileStream methods work perfectly – They are being used by thousands – It's probably the most widely used FTP library for Java. If it does not work for you, it's either because you are using them incorrectly or because there's something wrong with your network or servers.

Creating Encrypted connection for Amazon Aurora DB with public key

I am using Maria JDBC driver for creating a connection to Amazon Aurora DB
I wanted to create a secured connection so I read here
To connect to a DB cluster with SSL using the MySQL utility
Download the public key for the Amazon RDS signing certificate from
https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem.
Note that this will download a file named rds-combined-ca-bundle.pem.
First Question: How exactly is it secured - anyone can download this pem file from Amazon AWS?
I did some research How should i connect into Aurora DB with public key
and i found these 2 links First, Second
So my Code is quite Simple:
Class.forName("org.mariadb.jdbc.Driver");
Properties prop = new Properties();
prop.setProperty("javax.net.ssl.trustStore","C:\\temp\\rds-combined-ca-bundle.pem");
prop.setProperty("user",jdbcDetails.username);
prop.setProperty("password",jdbcDetails.getSensitiveData());
java.sql.Connection conne = DriverManager.getConnection(jdbcDetails.connectionString, prop);
try (Statement stmt1 = conne.createStatement()) {
// Execute all but the rest
ResultSet rs = stmt1.executeQuery("Select 98765 from dual limit 2");
while(rs.next()) {
rs.getLong(1);
}
}
conne.close();
Second Question: How is having the public key file relate to Encryption?
The above information doesn't get along with Oracle Java information that says:
If the client wants to authenticate the server, then the client's trust store must contain the server's certificate
Third Question: From what I understand if the client trust the server it doesn't require him to use this file
Forth Question: I was checking the connection creation with Wireshark
both cases with and without this public key file i was able to create a connection and both cases in Wireshark appeared Encrypted
Something that looks like that:
Encrypted Application Data:
eb:62:45:fb:10:50:f7:8c............:b9:0a:52:e7:97:1d:34
Base on this answer I understand about public key usage:
First,
It appears that Amazon AWS Azure documentation is misleading a bit - it is only relevant for connection with specific tool called MySQL utility
An answer for First & Second & third Question:
"Java can definitely establish an SSL connection without a client
validating the certificate chain of the server."
the key exchange is made to ensure that the server that it's connected to is indeed the one it was expecting (i.e non-suspicious server)
This means that it's still the same SSL connection made, but with verifyServerCertificate=false it does not verify that it is the intended server
Answer Forth Question:
Currect, The code is in Java - and passing the SSL parameter make it encrypted.
So using these parameter gives what requires
?trustServerCertificate=true&useSSL=true&requireSSL=true&verifyServerCertificate=false

How to bind variables into websocket route paths using Spark Web Framework?

I'm, trying to implement a websocket server using Spark (a java web framework). I'm using the version 2.3 that has added support for it.
There's some way to bind variables into route paths just like http routes?
e.g. /chat/:city
I want to create conversation channels among users. If it's possible, how can I make it work and how can I retrieve the variable?
Simply add ?userId=somekey to the end of path on your client side. Example would be to initialize your websocket path to Spark.websocket("/chat") (server-side obvi.) . Then have your client hit the URL with /chat?userId=blah. From the server side you'll receive a connection for the socket. From there simply grab the incoming URI from the socket connection and use the String userKey = session.getRemote().getQuery() method to pull of the field. May have to do a user.split("=")[1] to get the value
(stackoverflow's answer didn't worked for me, but pointed me in the right direction):
I managed to get the parameters this way:
#OnWebSocketConnect
void onConnect(Session sockSession) throws Exception {
Map<String, List<String>> params = sockSession.upgradeRequest.parameterMap;
if(params != null && params.containsKey("city")) {
// As the parameter's value is a List, we use 'get(0)'
String city = params.get("city").get(0);
...
}
...
}

Port forwarding with nginx from java

I'm trying to make a java application which uses redis as a backend. Since Redis is a really fast key-value store which I'd like to use, but redis is made to be used with 1 client so it doesn't have an option for user:pass authentication. I'd like to find a way to implement some kind of authentication, so I tried nginx with the redis2 extension. I did this because I could use client-side certficates and HTTPS. But it's making my application really slow.
I'm thinking about using some kind of tunnel which connects to redis via nginx proxy. For this redis would be listen on localhost and there would be an address which I'd like to use to reach redis, but with https authentication. So basically my current method
JAVA - Jedis - LAN - REDIS ,would be
JAVA - Jedis(with localhost as the tunnel entrance?)-
-SSL LAN - Nginx(tunnel exit) - Redis
Any tip for achieving this? I've been googled the web for the last days but i couldn't come up anything that adds only a little overhead to the native connection.
Redis is designed to work on a secure network, behind a backend application. Client applications are not supposed to connect directly to Redis. It makes Redis a poor choice for a 2-tier application.
Now if you still want to use Redis for this, you have several options. You can encapsulate the Redis server in a HTTP interface. This is what the nginx redis2 module provide. You might also want to have a look at webdis, which is similar (and does not depend on nginx). Webdis offers some access control mechanisms. See the documentation.
Another solution is to establish a tunnel, as you proposed. I would not use nginx for this, but just plain old SSH. Let's suppose Redis server runs on machine B (port 6379) and client runs on machine A.
On machine A, I can run:
ssh user#host_B -L 7008:host_B:6379 -N
It will open a tunnel from A to B from local port 7008 (arbitrary choice), and waits. The user should be declared on host B, and its password known. In another session, still on host A, we can now run:
redis-cli -p 7008 ping
Please note a standard Redis client is used. The tunnel handles authentication, encryption and optionally compression in a transparent way for the client.
Now, your client is a Java application, and you probably do not want to run SSH commands to setup the tunnel. Hopefully, you can use the Jsch package to open the tunnel directly from Java. Here is an example with Jedis:
import redis.clients.jedis.*;
import java.util.*;
import com.jcraft.jsch.*;
public class TestTunnel {
Jedis jedis;
Session session;
JSch jsch = new JSch();
int port;
// None of the following should be hardcoded
static String USER = "user"; // SSH user on the redis server host
static String PASSWD = "XXXXXXXX"; // SSH user password
static String HOST = "192.168.1.62"; // Redis server host
static int PORT = 6379; // Redis server port
public TestTunnel() {
try {
// Open the SSH session
session = jsch.getSession( USER, HOST, 22 );
session.setPassword( PASSWD );
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
config.put("Compression", "yes");
config.put("ConnectionAttempts","3");
session.setConfig(config);
session.connect();
// Setup port forwarding from localhost to the Redis server
// Local port is ephemeral (given by the OS)
// Jedis connects to localhost using the local port
port = session.setPortForwardingL( 0, HOST, PORT );
jedis = new Jedis( "127.0.0.1", port );
} catch ( JSchException e ) {
// Proper error handling omitted
System.out.println(e);
}
}
public void disconnect() {
jedis.disconnect();
try {
session.delPortForwardingL( port );
session.disconnect();
} catch ( JSchException e ) {
// Proper error handling omitted
System.out.println(e);
}
}
public void mytest( int n ) {
for ( int k = 0; k < n; k++) {
jedis.set("k" + k, "value"+k);
}
System.out.println("Read: "+jedis.get("k0") );
}
public static void main(String[] args) {
TestTunnel obj = new TestTunnel();
obj.mytest(10);
obj.disconnect();
}
}
It works fine, but please note there is an overhead due to the tunnel. The overhead is very low when the network is slow (the Internet for instance). On a fast LAN (1 GbE), it is much more noticeable: the latency can be multiplied by up to 3 when the tunnel is used. The maximum throughput the Redis server can sustain is also impacted. On server-side, the sshd daemon takes some CPU (more than Redis itself).
That said, I don't think raw performance matters much for a 2-tier application.
Note: There's an SSL version of redis called SSL-REDIS which can be found on github:
https://github.com/bbroerman30/ssl-redis 2.6ish
https://github.com/tritondigital/ssl-redis 2.4ish
With this and modifying the Jedis Java client, SSL authentication could be achieved.

Categories