Red5 / red5-server

Red5 Server core
Apache License 2.0
3.34k stars 982 forks source link

RTMPS Not Working with Red5 1.0.7 #187

Closed DannyL9143 closed 8 years ago

DannyL9143 commented 8 years ago

Issue

Related to Issue #92 with RTMPS handshake errors, but I have more information. I tried using Red5 1.0.7 to see if RTMPS was working since Red5 1.0.4. I got additional detail I was not able to get before.

Short description

The issue is running Red5 1.0.5 and above on CentOS platforms with RTMPS does not work with Adobe Air devices. The Air devices just say SSLHandshakeError, no other details, and minimal logging from Red5 or Java on the server side other than the connection was forced closed. Originally it started out with Android, now it also affects other devices as well. For Red5 1.0.7 I found that I had to run with Java 8 even though the documentation said it supported Java 7 because of the use of a threadsafe Collection that was built with Java 8 without a javac flag to allow it to be backward compatible with Java 7. Upon upgrading to Java 8, I now get an exception where I did not before.

The error has to do with a library called BouncyCastle. I uploaded the BC provider JAR file into the Java 8 ext directory, added it to the java.security file, and regenerated my JKS file to include the BC (which may be an issue for me, the command “works” but I don’t see the BC certificate in the JKS).

The reason I am messing with BouncyCastle is because I now get an exception with this configuration which has this stack trace (below). What happens is the stacktrace exception is thrown when I try to join the Adobe app with RTMPS and Red5 hangs until either the timeout or the handshake timeout breaks the hang (I tried really long timeouts, no change). The corresponding line of code appears to actually be on line 143 of RTMPHandshake, not 188 (at least on this site https://github.com/rfkrocktk/red5-server/blob/master/src/org/red5/server/net/rtmp/RTMPHandshake.java (https://github.com/rfkrocktk/red5-server/blob/master/src/org/red5/server/net/rtmp/RTMPHandshake.java) ), it is when the BouncyCastleProvider is loaded. It seems like BC is still not getting loaded correctly, but when I run keytool to make the certificate, I know it loads it because the same keytool command with a Java version without the BC provider barfs. So it is something to do with my Tomcat runtime configuration or perhaps a BouncyCastle library needs to be included with the Red5 build?

Since this code is in static context (below stack trace), is there a way to catch the exception and print it in a future version of Red5?

Thanks for your help in advance!

Environment

[] Operating system and version: CentOS 6 [] Java version: 1.8.0_92 [] Red5 version: 1.0.7

Expected behavior

RTMPS works

Actual behavior

Hangs until a timeout is reached (handshake timeout or general timeout set in the red5.properties file).

This is the stacktrace:

ProviderList: Loading all providers                                                                                                         
java.lang.Exception: Call trace                                                                                                             
        at sun.security.jca.ProviderList.loadAll(ProviderList.java:278)                                                                     
        at sun.security.jca.ProviderList.removeInvalid(ProviderList.java:299)                                                               
        at sun.security.jca.Providers.getFullProviderList(Providers.java:173)                                                               
        at java.security.Security.insertProviderAt(Security.java:360)                                                                             
        at java.security.Security.addProvider(Security.java:403)                                                                            
        at org.red5.server.net.rtmp.RTMPHandshake.<clinit>(RTMPHandshake.java:188)                                                          
        at org.red5.server.net.rtmps.RTMPSMinaIoHandler.sessionCreated(RTMPSMinaIoHandler.java:210)                                         
        at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.sessionCreated(DefaultIoFilterChain.java:772)                   
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionCreated(DefaultIoFilterChain.java:459)                      
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$700(DefaultIoFilterChain.java:48)                                   
        at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.sessionCreated(DefaultIoFilterChain.java:913)                  
        at org.apache.mina.core.filterchain.IoFilterAdapter.sessionCreated(IoFilterAdapter.java:74)                                         
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionCreated(DefaultIoFilterChain.java:459)                      
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireSessionCreated(DefaultIoFilterChain.java:452)                          
        at org.apache.mina.core.service.IoServiceListenerSupport.fireSessionCreated(IoServiceListenerSupport.java:212)                      
        at org.apache.mina.core.polling.AbstractPollingIoProcessor.addNow(AbstractPollingIoProcessor.java:510)                              
        at org.apache.mina.core.polling.AbstractPollingIoProcessor.handleNewSessions(AbstractPollingIoProcessor.java:479)                   
        at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$400(AbstractPollingIoProcessor.java:68)                           
        at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:1088)                      
        at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)                                                  
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)                                                  
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)                                                  
        at java.lang.Thread.run(Thread.java:745)                                                                                         

I think it is this code:

                static {
                                //get security provider
                                Security.addProvider(new BouncyCastleProvider());                       
                }

Steps to reproduce

  1. Try to run RTMPS on CentOS 6 with Red5 1.0.7 with a signed certificate.
  2. If you find it necessary, as I did, load/install BouncyCastle and regenerate your certificate. Those steps may need to be added to the Red5 manual, for example at https://github.com/Red5/red5-server/wiki/RTMPS. I was clued into this by running OpenSSL to test the connection handshake; tried various jee-container.xml changes (which didn't matter) and the BC files to get where I got (which I think did help).
  3. Try to connect with Adobe Air using RTMPS.

    Logs

My log is too big for pastebin.com, I can e-mail it if interested, it is 1 MB zipped. I think the interesting part is the stack trace I pasted above; I did turn on full SSL debug logging though.

References

http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/ https://docs.oracle.com/cd/E19830-01/819-4712/ablsc/index.html http://stackoverflow.com/questions/5914108/bouncycastle-installation-problems http://stackoverflow.com/questions/10379799/bouncycastle-cannot-load-when-i-redeploy-application https://gokceng.wordpress.com/2012/08/06/creating-ssl-keystore-for-apache-tomcat-using-keytool-and-bouncycastle/

mondain commented 8 years ago

May possibly be related to this BC bug report https://github.com/bcgit/bc-java/issues/144

mondain commented 8 years ago

The RTMPS encryption layer seems to be configured and working fine; the SSL/TLS part. FlashPlayer seems to dislike something in the packets following the successful setup and fails. I suggest using RTMPS over HTTP until this can be debugged further.

mondain commented 8 years ago

Is your cert a wild-card type or signed with an intermediate? http://serverfault.com/questions/263312/wildcard-ssl-certificate-not-working-with-chromes-built-in-flash-player

DannyL9143 commented 8 years ago

Thanks for looking into this Paul. I am working on our development servers which are using a wildcard certificate. Our production server has a regular certificate but I have not tried it there. I provide the certificate chain for both, but I don't think there is an intermediate certificate unless that is the same thing (this is not my area of expertise, I hope I am answering correctly).

Also, Red5 1.0.4 with Java 1.7 works fine. Red5 1.0.7 with Java 1.8 produces this issue. I tried running 1.0.7 with Java 1.7, but I get a fatal threading issue when starting because Red5 1.0.7 was not compiled with a flag to allow it to run with Java 1.7.

I am not sure if the problem referenced in this ticket is related to Java and the Bouncy Castle component in Java 1.8, so I was hoping I could try Red5 1.0.7 with Java 1.7.

mondain commented 8 years ago

This is a flash player issue with Native RTMPS, red5 works fine with native and tunneled RTMPS with other clients such as red5-client and rtmpdump. RTMPS tunneled does work in these configurations:

Chrome 52.0.2743.82 (64 bit) with Flash Player 22.0.0.209
Firefox 47 with Flash Player 11.2.202.632