Atmosphere / nettosphere

A Java WebSocket/HTTP server based on the Atmosphere and Netty Framework
http://async-io.org/
321 stars 81 forks source link

SSL WebSocket exception - Received fatal alert: certificate_unknown #153

Open supertick opened 3 years ago

supertick commented 3 years ago

Hello ! Many thanks for nettosphere and its support !

I'm trying to get a self signed certificate with ssl to nettosphere working. I checked in the unit tests of nettosphere for something appropriate and ended up with this :

        SelfSignedCertificate ssc = new SelfSignedCertificate();
        SslContext sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
        configBuilder.sslContext(sslServer);// .sslContext(sslCtx);
        configBuilder.enabledCipherSuites(sslServer.cipherSuites().toArray(new String[]{}));
        configBuilder.maxWebSocketFrameAggregatorContentLength(maxMsgSize);
        configBuilder.initParam("org.atmosphere.cpr.asyncSupport", "org.atmosphere.container.NettyCometSupport");
        configBuilder.initParam(ApplicationConfig.SCAN_CLASSPATH, "false");
        configBuilder.initParam(ApplicationConfig.PROPERTY_SESSION_SUPPORT, "true").port(port).host(address); // all
        configBuilder.maxChunkContentLength(maxMsgSize);
        configBuilder.maxWebSocketFrameSize(maxMsgSize);
        nettosphere = new Nettosphere.Builder().config(configBuilder.build()).build();        
        nettosphere.start();        

The results are mixed. This exception is constantly being thrown

ERROR o.a.n.BridgeRuntime [BridgeRuntime.java:784] Unexpected and unhandled I/O Exception
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:477) ~[netty-all-4.1.66.Final.jar:4.1.66.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-all-4.1.66.Final.jar:4.1.66.Final]

Strangely it does not appear to affect the resource handlers I have written, however it does kill the org.atmosphere.nettosphere.HttpStaticFileServerHandler

09:52:15.366 [nioEventLoopGroup-3-1] DEBUG i.n.c.AbstractChannelHandlerContext [AbstractChannelHandlerContext.java:305] An exception java.lang.NullPointerException
    at org.atmosphere.nettosphere.HttpStaticFileServerHandler.exceptionCaught(HttpStaticFileServerHandler.java:285)
    at org.atmosphere.nettosphere.BridgeRuntime.exceptionCaught(BridgeRuntime.java:785)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:302)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:281)
    at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:273)
    at io.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:1106)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:302)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:381)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)

So in the end the browser won't load the site.

Any ideas, examples, or suggestions on how to remove this exception, but still have a "valid" self signed certificate ? Thanks !

thabach commented 3 years ago

Hi there, you might want to give https://github.com/FiloSottile/mkcert a try, as an alternative to a self-signed certificate for local development.

supertick commented 3 years ago

I installed gvm which allowed me to install go1.5 which allowed me to install mkcert which I installed and ran the example.com example .. which only produces pem files, which I had to convert to pkcs12 format then convert that to a jks store :P

After all that - I don't get the trace stack anymore on the server Yay ! But it doesn't send back the static file (same end result as before) Booo ! image

It does send back a header - with a file size .. but no actual file image

supertick commented 3 years ago

Here is the debug logging I currently get :

17:47:27.305 [nioEventLoopGroup-3-1] DEBUG i.n.u.Recycler [Recycler.java:103] -Dio.netty.recycler.maxCapacityPerThread: 4096
17:47:27.305 [nioEventLoopGroup-3-1] DEBUG i.n.u.Recycler [Recycler.java:104] -Dio.netty.recycler.maxSharedCapacityFactor: 2
17:47:27.305 [nioEventLoopGroup-3-1] DEBUG i.n.u.Recycler [Recycler.java:105] -Dio.netty.recycler.linkCapacity: 16
17:47:27.306 [nioEventLoopGroup-3-1] DEBUG i.n.u.Recycler [Recycler.java:106] -Dio.netty.recycler.ratio: 8
17:47:27.306 [nioEventLoopGroup-3-1] DEBUG i.n.u.Recycler [Recycler.java:107] -Dio.netty.recycler.delayedQueue.ratio: 8
17:47:27.322 [nioEventLoopGroup-3-1] DEBUG i.n.b.AbstractByteBuf [AbstractByteBuf.java:63] -Dio.netty.buffer.checkAccessible: true
17:47:27.322 [nioEventLoopGroup-3-1] DEBUG i.n.b.AbstractByteBuf [AbstractByteBuf.java:64] -Dio.netty.buffer.checkBounds: true
17:47:27.324 [nioEventLoopGroup-3-1] DEBUG i.n.u.ResourceLeakDetectorFactory [ResourceLeakDetectorFactory.java:196] Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@555197f7
17:47:27.544 [nioEventLoopGroup-3-2] DEBUG i.n.h.s.SslHandler [SslHandler.java:1831] [id: 0x7d77ab04, L:/127.0.0.1:8888 - R:/127.0.0.1:45118] HANDSHAKEN: protocol:TLSv1.3 cipher suite:TLS_AES_128_GCM_SHA256
17:47:27.544 [nioEventLoopGroup-3-1] DEBUG i.n.h.s.SslHandler [SslHandler.java:1831] [id: 0x9d6f107c, L:/127.0.0.1:8888 - R:/127.0.0.1:45116] HANDSHAKEN: protocol:TLSv1.3 cipher suite:TLS_AES_128_GCM_SHA256
17:48:18.812 [nioEventLoopGroup-3-3] DEBUG i.n.h.s.SslHandler [SslHandler.java:1831] [id: 0x80572d11, L:/127.0.0.1:8888 - R:/127.0.0.1:45528] HANDSHAKEN: protocol:TLSv1.3 cipher suite:TLS_AES_128_GCM_SHA256
supertick commented 3 years ago

Thanks for the suggestion ...

supertick commented 3 years ago

curl is a little more informative ...

curl -vvv https://example.com:8888/index.html
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to example.com (127.0.0.1) port 8888 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: O=mkcert development certificate; OU=greg@t14-gperry (Greg Perry)
*  start date: Aug  8 00:30:11 2021 GMT
*  expire date: Nov  8 01:30:11 2023 GMT
*  subjectAltName: host "example.com" matched cert's "example.com"
*  issuer: O=mkcert development CA; OU=greg@t14-gperry (Greg Perry); CN=mkcert greg@t14-gperry (Greg Perry)
*  SSL certificate verify ok.
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> GET /index.html HTTP/1.1
> Host: example.com:8888
> User-Agent: curl/7.58.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/1.1 200 OK
< content-length: 7512
< Content-Type: text/html
< date: Sun, 08 Aug 2021 01:06:52 GMT
< expires: Sun, 08 Aug 2021 01:07:52 GMT
< cache-control: private, max-age=60
< last-modified: Thu, 05 Aug 2021 02:29:04 GMT
< 
* TLSv1.3 (IN), TLS Unknown, Unknown (21):
* TLSv1.3 (IN), TLS alert, Client hello (1):
* transfer closed with 7512 bytes remaining to read
* stopped the pause stream!
* Closing connection 0
* TLSv1.3 (OUT), TLS Unknown, Unknown (21):
* TLSv1.3 (OUT), TLS alert, Client hello (1):
curl: (18) transfer closed with 7512 bytes remaining to read
greg@t14-gperry:~/github/mkcert$

so the 7512 bytes never come ..... The headers are exchanged so it seems that TLS over HTTP1.1 is worky No exceptions, no errors, but no data

supertick commented 3 years ago

Any thoughts for this ? TLS works headers are exchanged, but exceptions are coming from netty + no static file returned ?

thabach commented 3 years ago

I don’t quite get why this is configured as a web socket, or is it? The title has it declared as such. U try to serve a simple GET request right?

supertick commented 3 years ago

The js of the client initially is served from static pages .. I'm using the Atmosphere javascript client - https://github.com/Atmosphere/atmosphere-javascript

So, yes - a handler is set to serve the static page, the page loads in the browser, executes the js client which opens the websocket. It works without SSL, but not with SSL ...

thabach commented 3 years ago

Gotya, could you run your curl -v with --ignore-content-length and paste the output? Does a similar curl request against the working version reply with the same content-length for your index.html?

supertick commented 2 years ago

heh, sorry about the extremely long pause ... apparently some pandemic got loose ... @thabach - ya ... works fine under http

curl -k -vvv --ignore-content-length http://example.com:8888/index.html
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to example.com (127.0.0.1) port 8888 (#0)
> GET /index.html HTTP/1.1
> Host: example.com:8888
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< content-length: 7560
< Content-Type: text/html
< date: Thu, 28 Apr 2022 06:13:47 GMT
< expires: Thu, 28 Apr 2022 06:14:47 GMT
< cache-control: private, max-age=60
< last-modified: Sat, 05 Mar 2022 17:24:32 GMT
* no chunk, no close, no size. Assume close to signal end
< 
<!doctype html>
<html lang="en" ng-app="mrlapp">
    <head>
        <meta charset="utf-8">
    ( full html page )

All bytes are returned specifically 7560 of them ... but switching to use ssl - I get this ..

curl -k -vvv --ignore-content-length https://example.com:8888/index.html
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to example.com (127.0.0.1) port 8888 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=localhost
*  start date: Apr 28 06:17:43 2021 GMT
*  expire date: Dec 31 23:59:59 9999 GMT
*  issuer: CN=localhost
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> GET /index.html HTTP/1.1
> Host: example.com:8888
> User-Agent: curl/7.58.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/1.1 200 OK
< content-length: 7560
< Content-Type: text/html
< date: Thu, 28 Apr 2022 06:18:02 GMT
< expires: Thu, 28 Apr 2022 06:19:02 GMT
< cache-control: private, max-age=60
< last-modified: Sat, 05 Mar 2022 17:24:32 GMT
* no chunk, no close, no size. Assume close to signal end
< 
* TLSv1.3 (IN), TLS Unknown, Unknown (21):
* TLSv1.3 (IN), TLS alert, Client hello (1):
* Closing connection 0
* TLSv1.3 (OUT), TLS Unknown, Unknown (21):
* TLSv1.3 (OUT), TLS alert, Client hello (1):

It returns the correct byte count ... but no data

supertick commented 2 years ago

can we re-open this ?

supertick commented 2 years ago

interestingly, my custom resource works fine in https configBuilder.resource("/api", this);

curl -k -vvv --ignore-content-length https://example.com:8888/api/service/runtime/getUptime
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to example.com (127.0.0.1) port 8888 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=localhost
*  start date: Apr 28 06:17:43 2021 GMT
*  expire date: Dec 31 23:59:59 9999 GMT
*  issuer: CN=localhost
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> GET /api/service/runtime/getUptime HTTP/1.1
> Host: example.com:8888
> User-Agent: curl/7.58.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/1.1 200 OK
< Content-Type:application/json
< Transfer-Encoding:chunked
< Server:Nettosphere/3.2.5
< Cache-Control:no-store, no-cache, must-revalidate
< X-Atmosphere-first-request:true
< Connection:Keep-Alive
< Expires:-1
< Pragma:no-cache
< X-Atmosphere-tracking-id:68ae2672-b974-47df-b7fc-773b81bd2b69
< 
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* Connection #0 to host example.com left intact
"0 days 0 hours 10 minutes 5 seconds"

but any static file with the default file path resource - does not work e.g. index.html inside this path configBuilder.resource("./src/main/resources/resource/WebGui/app");

jfarcand commented 2 years ago

@supertick If you can share a github's repo with a test case I will take a look

supertick commented 2 years ago

Easy :)

https://github.com/MyRobotLab/nettosphere-ssl I tried to provide the simplest example...

      boolean ssl = true;
      if (ssl) {
        SelfSignedCertificate ssc = new SelfSignedCertificate("localhost");
        SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null).build();
        configBuilder.sslContext(sslCtx);
      }

      configBuilder.resource("./");
      Nettosphere nettosphere = new Nettosphere.Builder().config(configBuilder.build()).build();
      nettosphere.start();

ssl = false returns the index.html correctly ssl = true does not

thabach commented 2 years ago

@jfarcand I digged a bit too, not sure why the HttpStaticFileServerHandler in the presence of SSL chooses to send the file chunk-encoded, maybe a hint:

image

Cheers.

thabach commented 2 years ago

btw, for the test-case of @supertick to work, I needed to add the below to his pom.xml for the self-signed certificate creation:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.49</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.49</version>
</dependency>
supertick commented 2 years ago

@jfarcand any ideas ?

jfarcand commented 2 years ago

@supertick On it today

jfarcand commented 2 years ago

@thabach Have you been able to pass this exception? I think you are right with the code...I forgot how to setup Nettosphere properly hahahaha

06:45:02.163 [nioEventLoopGroup-3-2] ERROR org.atmosphere.nettosphere.BridgeRuntime - Unexpected and unhandled I/O Exception
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:477)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:313)
    at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:186)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
    at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681)
    at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433)
    at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:637)
    at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:296)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1342)
    at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1235)
    at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1284)
    at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:507)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:446)
    ... 17 common frames omitted
supertick commented 2 years ago

@thabach - I updated the pom in the example with the bouncy castle dep. Also, I updated the poms spec references to java 11 (from java 8) ... I'm using Java 11 locally anyway, and see one of the badges on Nettosphere's page as green. I tried to make the sample as simple as possible. In another project I can tell that the non-static file resource handlers appear to be working, only the static resource handler explodes.

thabach commented 2 years ago

@jfarcand, with @supertick's pom changes, I can start his test and then I do a:

curl -k -v https://localhost:8080/index.html

to reproduce the issue with the infamous transfer closed with 47 bytes remaining to read. I don't get the unknown Certificate Authority exception, but as of it being a self-signed certificate, the following:

* Closing connection 0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

which is probably the very same issue you see in your client. Therefore I employ the -k switch in curl for it to go on.

@supertick, gotya, yes I think the culprit is indeed the HttpStaticFileServerHandler with an emphasis on static.

thabach commented 2 years ago

@jfarcand, it does not work on exercising the standard/non-ssl if-branch from the above code for the https-call. I just tried. We need you 😃 ...

jfarcand commented 2 years ago

@thabach THANKS!!!! I always like to work with you! Looking at it today! Thanks @supertick

jfarcand commented 2 years ago

@supertick Fixed in 3.2.6-SNAPSHOT and let me know the result I will cut the official release

supertick commented 2 years ago

My super quick way to test - adding the source test to a clean nettosphere git checkout 4a5d587d00d22899671790832df945adf526f80c

image noWorky :( image

curl -k https://localhost:8080/index.html curl: (52) Empty reply from server

jfarcand commented 2 years ago

@supertick I do get

❯ curl -k https://localhost:8080/index.html
<html>
<head/>
<body>
    hello !
</body>
</html>

But I do experience issue when I use Chrome

jfarcand commented 2 years ago
❯ curl -vvv https://127.0.0.1:8080/index.html
*   Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: self signed certificate
* Closing connection 0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.html

I think in my case I just need to sign the cert

supertick commented 2 years ago

Hmmm ... :thinking: is your setup like this ?

      if (ssl) {
        SelfSignedCertificate ssc = new SelfSignedCertificate("localhost");
        SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null).build();
        configBuilder.sslContext(sslCtx);
      }

      configBuilder.resource("./");
      Nettosphere nettosphere = new Nettosphere.Builder().config(configBuilder.build()).build();
      nettosphere.start();

I've tried curl & wget ... neither get responses ...

--2022-05-10 15:28:51--  (try: 3)  https://localhost:8080/index.html
Connecting to localhost (localhost)|127.0.0.1|:8080... connected.
WARNING: cannot verify localhost's certificate, issued by ‘CN=localhost’:
  Self-signed certificate encountered.
HTTP request sent, awaiting response... No data received.
Retrying.

--2022-05-10 15:28:54--  (try: 4)  https://localhost:8080/index.html
Connecting to localhost (localhost)|127.0.0.1|:8080... connected.
WARNING: cannot verify localhost's certificate, issued by ‘CN=localhost’:
  Self-signed certificate encountered.
HTTP request sent, awaiting response... No data received.
Retrying.
jfarcand commented 2 years ago

@supertick I use the latest Nettosphere snapshot and just added to your pom.xml

         <dependency>
             <groupId>com.sun.activation</groupId>
             <artifactId>javax.activation</artifactId>
             <version>1.2.0</version>
         </dependency>
supertick commented 2 years ago

added activation dep .... WORKY !

curl  -k https://localhost:8080/index.html
<html>
<head/>
<body>
        hello !
</body>
</html>

Thanks @jfarcand :+1:

jfarcand commented 2 years ago

@supertick I've released 3.2.6!

supertick commented 2 years ago

Uh oh ... Did you have non-valid reflective access in the update ? Running without ssl .. I now get the following errors.

java.lang.UnsupportedOperationException: Reflective setAccessible(true) disabled
    at io.netty.util.internal.ReflectionUtil.trySetAccessible(ReflectionUtil.java:31)
    at io.netty.util.internal.PlatformDependent0$4.run(PlatformDependent0.java:233)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:227)
    at io.netty.util.internal.PlatformDependent.isAndroid(PlatformDependent.java:289)
    at io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:92)
    at io.netty.channel.group.DefaultChannelGroup.<init>(DefaultChannelGroup.java:48)
    at io.netty.channel.group.DefaultChannelGroup.<init>(DefaultChannelGroup.java:74)
    at org.atmosphere.nettosphere.Nettosphere.<clinit>(Nettosphere.java:67)
    at org.atmosphere.nettosphere.Nettosphere$Builder.build(Nettosphere.java:201)
    at org.myrobotlab.service.WebGui.start(WebGui.java:1100)
    at org.myrobotlab.service.WebGui.startService(WebGui.java:1151)
    at org.myrobotlab.service.WebGui.main(WebGui.java:1291)
The exception is thrown when initializing the default channel group..
public final class Nettosphere {

    public final static String FLASH_SUPPORT = Nettosphere.class.getName() + ".enableFlash";
    private static final Logger logger = LoggerFactory.getLogger(Nettosphere.class);
    private static final ChannelGroup ALL_CHANNELS = new DefaultChannelGroup("atmosphere",
            ImmediateEventExecutor.INSTANCE);

My configuration is pretty straightforward - this used to work

    configBuilder.resource("./resource");
    configBuilder.resource("/api", this);
    configBuilder.maxWebSocketFrameAggregatorContentLength(maxMsgSize);
    configBuilder.initParam("org.atmosphere.cpr.asyncSupport", "org.atmosphere.container.NettyCometSupport");
    configBuilder.initParam(ApplicationConfig.SCAN_CLASSPATH, "false");
    configBuilder.initParam(ApplicationConfig.PROPERTY_SESSION_SUPPORT, "true").port(port).host(address); // all
    configBuilder.maxChunkContentLength(maxMsgSize);
    configBuilder.maxWebSocketFrameSize(maxMsgSize);

I'll keep testing (Using Java 11 btw - I know reflection access becomes more problematic in future jdks)

It seems as now, the websocket after getting connected, is immediately disconnected (not running ssl) Reverting back to nettosphere 3.2.1 where websockets were worky.

jfarcand commented 2 years ago

euh...what is that :-) Can you try 3.2.5?

supertick commented 2 years ago

The reflective warning is apparently not an error - https://github.com/netty/netty/issues/7817 I went back and validated it is giving the same "warning" in 3.2.1 (and probably not relevant - its logged at DEBUG level) However,

The issue is: 3.2.5 & 3.2.1 - do not immediately disconnect websockets 3.2.6 - does :cry:

this is new behavior with 3.2.6

supertick commented 2 years ago

3.2.1 & 3.2.5 ws connection as expected

git checkout 925feaa65d0c144d61acd83fea34397ecad6f1ea
prepare release nettosphere-project-3.2.5
$ wscat -c http://localhost:8080/api
Connected (press CTRL+C to quit)
< X

3.2.6 immediate disconnect

$ wscat -c http://localhost:8080/api
error: socket hang up
supertick commented 2 years ago

In order to show what is happening easily, I forked your repo and just added a quick test file It's on master - https://github.com/supertick/nettosphere/blob/master/server/src/main/java/NettoSsl.java You can switch between the 3.2.5 and 3.2.6 releases:

on 3.2.5 - gets a static resource, and will suspend a websocket connection

switch to 3.2.6 - gets a static resource, but immediately disconnects on a websocket connection

Hope this helps.

jfarcand commented 2 years ago

@supertick Yep that helps. So you are ok with 3.2.5 then. I will rollback the latest changes and release 3.2.7 asap

supertick commented 2 years ago

I think the current state is: 3.2.5 - websockets work, but static resource to ssl returns nothing 3.2.6 - static resource works with ssl, but websockets do not work

jfarcand commented 2 years ago

@supertick Can you try 3.2.7-SNAPSHOT? Couples of tests failing but both ws and ssl seems to work fine

supertick commented 2 years ago

yessir

supertick commented 2 years ago

3.2.7-SNAPSHOT

This might be the same results as 3.2.5 Let me know if you want me to test some other functionality

jfarcand commented 2 years ago

@supertick OK I think I have it fixed. Let me know and SUPER thanks for the help!

supertick commented 2 years ago

I tested 3.2.7 from maven central ... still no worky :cry:

supertick commented 2 years ago

3.2.7 maven central release no worky for non ssl static content :x:

haven't regression tested the rest yet ...

jfarcand commented 2 years ago

Let me know what you tested. For me everything works as expected

supertick commented 2 years ago

super simple test - single file, testing with java 11 https://github.com/MyRobotLab/netto-test

4 files

I'm using eclipse - start project - start server with 3.2.1 goto http://localhost:8080/index.html get "hello world !" in browser

switch to 3.2.7 image

I could document curl requests - but I suspect they are the same as before

supertick commented 2 years ago

I think there might be 4 use cases to test

supertick commented 2 years ago

Ahoy ! can you replicate the issue ?

supertick commented 2 years ago

I wonder if this is a dependency conflict issue :thinking: