I am creating a simple HTTPS connection and returning a response
URL google = new URL("https://www.google.com/");
HttpsURLConnection connection = (HttpsURLConnection)google.openConnection();
System.out.println( "Response: " + connection.getResponseCode());
This works fine and I receive a 200 response (I have all the keystores and truststores etc. defined)
I then proxy the request through a Jetty server by using https.proxyPort=8443 and https.proxyHost-localhost
The server has connectors that look like this:
Server server = new Server();
SelectChannelConnector connector0 = new SelectChannelConnector();
connector0.setPort(8080);
SslSelectChannelConnector sslConnector = new SslSelectChannelConnector();
sslConnector.setPort(8443);
SslContextFactory cf = sslConnector.getSslContextFactory();
cf.setKeyStorePath(keyStoreHome);
cf.setKeyStorePassword(keyStorePassword);
cf.setTrustStore(trustStoreHome);
cf.setTrustStorePassword(trustStorePassword);
cf.setCertAlias("jetty");
server.setConnectors(new Connector[] {connector0, sslConnector});
server.setHandler(new HelloHandler());
server.start();
server.join();
Which gives me the error below:
DEBUG: org.eclipse.jetty.io.nio - created SCEP#33589e56{l(/127.0.0.1:62348)<->r(/127.0.0.1:8443),d=false,open=true,ishut=false,oshut=false,rb=false,wb=false,w=true,i=0}-{SslConnection#7f033a6f SSL NOT_HANDSHAKING i/o/u=-1/-1/-1 ishut=false oshut=false {AsyncHttpConnection#26c623af,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-14,l=0,c=0},r=0}}
DEBUG: org.eclipse.jetty.io.nio.ssl - [Session-1, SSL_NULL_WITH_NULL_NULL] SslConnection#7f033a6f SSL NOT_HANDSHAKING i/o/u=180/0/0 ishut=false oshut=false {AsyncHttpConnection#26c623af,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-14,l=0,c=0},r=0} NOT_HANDSHAKING filled=180/180 flushed=0/0
DEBUG: org.eclipse.jetty.io.nio.ssl - SCEP#33589e56{l(/127.0.0.1:62348)<->r(/127.0.0.1:8443),d=true,open=true,ishut=false,oshut=false,rb=false,wb=false,w=true,i=0r}-{SslConnection#7f033a6f SSL NEED_WRAP i/o/u=180/0/0 ishut=false oshut=false {AsyncHttpConnection#26c623af,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-14,l=0,c=0},r=0}}
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.net.ssl.internal.ssl.EngineInputRecord.bytesInCompletePacket(EngineInputRecord.java:152)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:806)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:721)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:607)
at org.eclipse.jetty.io.nio.SslConnection.unwrap(SslConnection.java:519)
at org.eclipse.jetty.io.nio.SslConnection.process(SslConnection.java:354)
at org.eclipse.jetty.io.nio.SslConnection.access$900(SslConnection.java:43)
at org.eclipse.jetty.io.nio.SslConnection$SslEndPoint.fill(SslConnection.java:661)
at org.eclipse.jetty.http.HttpParser.fill(HttpParser.java:1030)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:275)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
at org.eclipse.jetty.io.nio.SslConnection.handle(SslConnection.java:191)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:620)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)
at java.lang.Thread.run(Thread.java:662)
DEBUG: org.eclipse.jetty.io.nio.ChannelEndPoint - close SCEP#33589e56{l(/127.0.0.1:62348)<->r(/127.0.0.1:8443),d=true,open=true,ishut=false,oshut=false,rb=false,wb=false,w=true,i=0!}-{SslConnection#7f033a6f SSL NEED_WRAP i/o/u=180/0/0 ishut=false oshut=false {AsyncHttpConnection#26c623af,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-14,l=0,c=0},r=0}}
DEBUG: org.eclipse.jetty.http.HttpParser -
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
Can anybody please tell me what might be wrong with this?
By the looks of it the exception is occurring when the proxy is connecting the HTTP - 8080 and HTTPS - 8443. Does JETTY do decryption between those ports because if not the exception is about the 8080 being plain text.
This is more or less the same problem as in this question.
When you use https.proxyPort=8443 and https.proxyHost=localhost, the connection between your client and the proxy host/port isn't done using SSL/TLS, but in plain text HTTP. The client then sends the proxy a CONNECT request with the target host name (and this is way you get this "plain text" exception).
Then, the proxy makes a request to that target server and establishes a tunnel that relays all the raw traffic back and forth. From the client's point of view (HttpsUrlConnection), the socket that is connected to the proxy is upgraded to SSL/TLS (i.e. it initiate an handshake, which is relayed to the target server via that tunnel.
There aren't many clients that also support having the connection between the client and the proxy itself using HTTPS. This isn't generally very useful, since an attacker could only see the host name and port anyway.
Related
Consider this HAProxy configuration here:
global
chroot /var/lib/haproxy
user haproxy
group haproxy
defaults
timeout connect 10s
timeout client 50s
timeout server 50s
frontend fe_https_tomcat
mode tcp
bind *:443 ssl crt /path/cert.pem alpn h2,http/1.1
default_backend be_tomcat
backend be_tomcat
mode tcp
server localhost localhost:8081 check
The issue I have is that WebSocket do not seem to get through. My guess was that in tcp mode everything would pass through. Looks like it doesn't ... :-)
The server responds with an error 403 when the WebSocket connection is getting established.
Note that with the following http-mode setup, the WebSocket just works:
frontend fe_http_8080
mode http
bind *:8080
default_backend be_tomcat_8080
backend be_tomcat_8080
mode http
server localhost localhost:8081 check
Note that I need tcp-mode to have http/2 working.
The issue was not related to HAProxy at the end, but to the WebSocket setup in Spring.
This fixed it:
-registry.addHandler(webSocketHandler, "/ws");
+registry.addHandler(webSocketHandler, "/ws").setAllowedOrigins("*");
We have a java web server which is able to serve content over h2c (HTTP/2 clear text)
We would like to reverse proxy connections established using h2 (i.e. standard HTTP/2 over SSL) to the java server in h2c.
Enabling HTTP/2 on nginx is simple enough and handling incoming h2 connections works fine.
How do we tell nginx to proxy the connection using h2c rather than http/1.1 ?
Note: a non-nginx solution may be acceptable
server {
listen 443 ssl http2 default_server;
server_name localhost;
ssl_certificate /opt/nginx/certificates/???.pem;
ssl_certificate_key /opt/nginx/certificates/???.pk8.key.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:8080/; ## <---- h2c here rather than http/1.1
}
}
CONCLUSION (June 2016)
This can be done with haproxy using a configuration file as simple as the one below.
Querying (HttpServletRequest) req.getProtocol() clearly returns HTTP/2.0
global
tune.ssl.default-dh-param 1024
defaults
timeout connect 10000ms
timeout client 60000ms
timeout server 60000ms
frontend fe_http
mode http
bind *:80
# Redirect to https
redirect scheme https code 301
frontend fe_https
mode tcp
bind *:443 ssl no-sslv3 crt mydomain.pem ciphers TLSv1.2 alpn h2,http/1.1
default_backend be_http
backend be_http
mode tcp
server domain 127.0.0.1:8080
HAProxy does support that.
HAProxy can offload TLS and forward to a backend that speaks h2c.
Details on how to setup this configuration are available in this blog post.
I have been trying to change a working FTP connection FTPClient to a FTPSClient provided by apache. The only changes made were changing the class and indicating what port the application is going to connect.
The server connects to another server within the same network. For external servers, a proxy is required.
I already tried setting up the constructor to true, it shows the following message:
Unrecognized SSL message, plaintext connection?
final FTPSClient ftp = new FTPSClient( true );
//same results
//final FTPSClient ftp = new FTPSClient("SSL", true );
//final FTPSClient ftp = new FTPSClient("TLS", true );
ftp.setDefaultPort(22);
When I set it up to false, the connection hangs up for a lot of time. It shows the following message:
Could not parse response code. Server Reply: SSH-2.0-OpenSSH_4.1
and tomcat shows the following page:
Proxy Error
The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request POST /myapppath/APage.htm.
Reason: Error reading from remote server
final FTPSClient ftp = new FTPSClient( false );
ftp.setDefaultPort(22);
I tried connecting manually with WinSCP via SFTP and the connection is successful.
FTPS (FTP over SSL/TLS) is not the same as SFTP (SSH file transfer); these are two completely different protocols. The reason you are getting the error Unrecognized SSL message, plaintext connection? is because you are not connecting to a FTPS server.
You can read more about the difference here. If you want to make an SFTP connection rather than an FTPS connection, I would recommend using the JSch library.
I'm writing a simple HTTPS proxy program with Java for educational purposes. My program listens on a port (say 7443) for incoming HTTPS requests from a browser (say Firefox), parses the request and forwards it to the desired destination (say https://www.comodo.com).
Firefox's proxy settings are set to use my port for SSL connections ( 127.0.0.1 : 7443 ).
My code is short and simple:
static // initializer
{
System.setProperty("javax.net.ssl.keyStore", "MyKeyStore");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
}
SSLServerSocketFactory ssFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
try {
SSLServerSocket listener = (SSLServerSocket) ssFactory.createServerSocket(port, 64);
listener.setUseClientMode(false);
listener.setWantClientAuth(false);
listener.setNeedClientAuth(false);
SSLSocket connection = (SSLSocket) listener.accept();
browser.startHandshake(); /* <<== Exception throws at this line */
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
But I'm catching the following exception:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
The exception says that the connection could be plain-text, but only HTTPS connections from Firefox are set to use this port. I have logged what Firefox is sending to my application which is this:
CONNECT www.comodo.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.comodo.com
Firefox is talking palin-text, and I think CONNECT is a SOCKS command (I'm not sure though), where I haven't set anything in Firefox's SOCKS settings. Below is a screenshot of Firefox's proxy settings:
What am I missing here ?! What I need to do to make this work with Firefox or any other browser ?!
------------------------------------------------------------------------------
For those who think this is a duplicate of another question and that it has been answered in the other one I have to say: Yes, both questions have roots in a similar problem but the only answer in the cited question directs at using SSL Sockets which turned out to be misleading and resulted in this new question. So although they are aimed at a similar problem, this question shows a completely different and yet mislead path to go for solving the problem and so it could provide useful guidance for future persons facing such a problem.
Get rid of all the SSL. Just process the incoming CONNECT command, make a plaintext connection to the upstream server, and then start copying bytes. The browser and the server will speak SSL but you don't need to at all.
Your setup is using HTTP tunneling, where the initial request sent to the proxy is not SSL encrypted; since the SSL-enabled socket is expecting an SSL handshake, it throws an exception.
In this mechanism, the client asks an HTTP Proxy server to forward the
TCP connection to the desired destination using the "CONNECT" HTTP
method. The server then proceeds to make the connection on behalf of
the client. Once the connection has been established by the server,
the Proxy server continues to proxy the TCP stream to and from the
client. Note that only the initial connection request is HTTP - after
that, the server simply proxies the established TCP connection.
You can read more about it at HTTP Tunneling wiki page. To see this in action, you can start off a netcat server and set the Firefox proxy to point to that port:
nc -l 8000
Now in Firefox type in https://www.google.com, and examine the nc output:
CONNECT www.google.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0)
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.google.com
And this is completely in plaintext. Below diagram demonstrates how Firefox proxy expects to communicate.
I'm working on a project to auto-configure a user's email server settings in Java. I am extracting the mail server from his email address and looking up the MX records of that mail server using the DirContext class with com.sun.jndi.dns.DnsContextFactory.
Then I'm opening a Socket to each server and testing them using a HELO command and checking the responses.
My problem is that this works only when I test it with the unsecure SMTP port 25. How can I use it with the secure port 465?
I tried using Secure Sockets by using
SSLSocketFactory sslsocketfactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket)sslsocketfactory.createSocket(mailserver, STANDARD_SMTP_PORT);
But all connections get a timeout exception as follows
alt1.gmail-smtp-in.l.google.com. java.net.ConnectException: Operation timed out
Please help.
Further Info: I am not creating a mail client. This is to simplify the mail server settings for an already existing mail client.
SMTP-SSL (Port 465) afaik is deprecated, so instead of trying to connect to a ssl socket you'd actually connect "plaintext" on port 25 (or 587 for smtp auth connections), but send EHLO instead of HELO and see if the server supports STARTTLS which replaces the deprecated SMTP-SSL. after the client sends the STARTTLS command, the connection is encrypted, so, port 25 is not per se "unsecure"
telnet alt1.gmail-smtp-in.l.google.com 25
Trying 173.194.71.26...
Connected to alt1.gmail-smtp-in.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP i7si4620651lbb.76
EHLO myserver.com
250-mx.google.com at your service, [x.x.x.x]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS <<--------- this is what you're looking for
250 ENHANCEDSTATUSCODES
STARTTLS <<--- client command to actually start encrypting the traffic
220 2.0.0 Ready to start TLS
Have you authenticated the program before establishing a connection with the server . Every remote mail server will need to authenticate the machine trying to establish a socket connection . If your using javaMail library for example , you will be given options to add the username and password . You will need to find a workaround while using simple sockets in java