Prerequisites:
OS: Windows Server 2012 R2
Java: checked on both jdk1.8.0_162 jdk1.8.0_181
Tomcat: windows x64 builds checked on 9.0.12, 9.0.16, 9.0.17-dev
Valid SSL certificates
Content of file located at webapp/ROOT/1.txt: []
Tomcat's connector settings:
        <Connector port="443"
                        protocol="org.apache.coyote.http11.Http11Nio2Protocol"

sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
                        connectionTimeout="5000"
                        SSLEnabled="true"
                        scheme="https"
                        secure="true"
        >

This configuration leads to 50% of the traffic to be rejected with
Connection resets. First socket connects and receives the service, but
every second is resetted.

Exactly this combination leads to connection resets:
        protocol="org.apache.coyote.http11.Http11Nio2Protocol"
        
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"

Configurations that work well without connection resets:
        protocol="org.apache.coyote.http11.Http11Nio2Protocol"
        
sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation"
or
        protocol="org.apache.coyote.http11.Http11NioProtocol"
        
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"

Java code to reproduce the connection resets (works well with any
other secure server):
(there is no resets if a variable named FIX__gotoSleepAfterHandshake = true)

public class CheckConnectionResets{
    static String host = "your-test-host";

    public static void main( String[] args ) throws
InterruptedException, IOException{

        SSLSocketFactory factory =
(SSLSocketFactory)SSLSocketFactory.getDefault();
        int nRuns = 4;
        int success = 0;
        int denial = 0;

        boolean FIX__gotoSleepAfterHandshake = false;

        for( int i = 0; i < nRuns; i++ ){
            try ( SSLSocket socket = (SSLSocket)factory.createSocket(
host, 443 ) ){

                if( FIX__gotoSleepAfterHandshake ){
                    socket.startHandshake();
                    Thread.sleep( 500 );
                }
                try ( PrintWriter out = new PrintWriter( new
BufferedWriter( new OutputStreamWriter( socket.getOutputStream() ) )
);
                        InputStream is = socket.getInputStream(); ){

                    out.println( "GET /1.txt HTTP/1.1" );
                    out.println( "Host: " + host );
                    out.println( "Accept: */*" );
                    out.println();
                    out.flush();

                    if( out.checkError() ){
                        System.out.println( "SSLSocketClient:
java.io.PrintWriter error" );
                    }

                    Instant start = Instant.now();
                    /* read full response */
                    byte[] buff = new byte[ 1024 ];
                    int read = is.read( buff );
                    success++;
                    System.out.println( "success: " + success + ",
read " + read + " bytes for: " + start.until( Instant.now(),
ChronoUnit.MILLIS ) + "ms" );

                } catch ( IOException e ) {
                    denial++;
                    System.err.println( "denial: " + denial + ", " +
e.getMessage() );
}}}}}

Sample output:
success: 1, read 73 bytes for: 78ms
denial: 1, Connection reset
success: 2, read 73 bytes for: 78ms
denial: 2, Connection reset

The bug is stable, and always reproducible.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to