Inline ...
Hello Joakim,
Firstly, this is the setup (Scala)
code for the SslContextFactory etc.:
/***** start code *****/
val sslContextFactory = new
SslContextFactory
val ciphers = Array(
"TLS_AES_128_GCM_SHA256",
/* TLS 1.3 */
"TLS_AES_256_GCM_SHA384",
/* TLS 1.3 */
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
/* TLS 1.0 / 1.1 - IE7/8/9 - Android
<= 4.3 */
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256")
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR)
sslContextFactory.setUseCipherSuitesOrder(true)
Not relevant, anywhere anymore.
You can get an A+ rating on ssllabs
without attempting to control cipher
suite order.
(Note: A+ rating is for all HTTP/1.x
and HTTP/2 behaviors)
sslContextFactory.setIncludeCipherSuites(ciphers:_*)
Don't include, exclude only.
You eliminate a ton of valid Cipher
Suites doing it this way.
sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA")
Use defaults, none of those Cipher
suites would be selected anyway due to
default Cipher Suite exclusions in
SslContextFactory AND the JVM disabled
cipher suites.
/** Default Excluded Cipher Suite
List */
private static final String[]
DEFAULT_EXCLUDED_CIPHER_SUITES = {
// Exclude weak / insecure
ciphers
"^.*_(MD5|SHA|SHA1)$",
// Exclude ciphers that
don't support forward secrecy
"^TLS_RSA_.*$",
// The following
exclusions are present to cleanup
known bad cipher
// suites that may be
accidentally included via include
patterns.
// The default enabled
cipher list in Java will not include
these
// (but they are available
in the supported list).
"^SSL_.*$",
"^.*_NULL_.*$",
"^.*_anon_.*$"
};
sslContextFactory.addExcludeProtocols("SSLv3")
This is the in the default excluded
protocols values, and also
excluded/disabled at the JVM level,
don't set it.
/** Default Excluded Protocols
List */
private static final String[]
DEFAULT_EXCLUDED_PROTOCOLS = {"SSL",
"SSLv2", "SSLv2Hello", "SSLv3"};
sslContextFactory.setRenegotiationAllowed(false)
sslContextFactory.setEndpointIdentificationAlgorithm("HTTPS")
This is only relevant for a client
initiating a connection to a destination
machine with TLS.
Comment out all of the above.
It screams old-school behaviors and
techniques.
Use defaults for SslContextFactory
when it comes to Cipher Suites and
Protocols, and don't attempt to support
TLS/1.0 or TLS/1.1 Those protocols are
disabled in so many places (User-Agents,
Browsers, OS level, Java VM level,
Server level, various hardware
intermediates) now its pointless to
attempt to support them. If this is
still important to you, make a different
connector for legacy behaviors.
sslContextFactory.setKeyStorePath(keyStore)
sslContextFactory.setKeyStorePassword(keyPassword)
sslContextFactory.setKeyManagerPassword(keyPassword)
sslContextFactory.setKeyStoreType(keyStoreType)
val httpsConfig = new
HttpConfiguration
httpsConfig.setSecureScheme("https")
httpsConfig.setSecurePort(port)
httpsConfig.setSendXPoweredBy(false)
httpsConfig.setSendServerVersion(false)
httpsConfig.setOutputBufferSize(32768)
httpsConfig.addCustomizer(new
SecureRequestCustomizer)
val http1 = new
HttpConnectionFactory(httpsConfig)
val connector =
{
if (httpVersion !=
"http/2")
{
val ssl = new
SslConnectionFactory(sslContextFactory,"http/1.1")
val http = new
HttpConnectionFactory(httpsConfig)
new
ServerConnector(server,ssl,http)
}
else
{
val http2 = new
HTTP2ServerConnectionFactory(httpsConfig)
val alpn = new
ALPNServerConnectionFactory
alpn.setDefaultProtocol(http1.getProtocol)
Use
alpn.setDefaultProtocol(http1.getDefaultProtocol())
val ssl = new
SslConnectionFactory(sslContextFactory,alpn.getProtocol)
new
ServerConnector(server,ssl,alpn,http2,http1)
}
}
if (address != null)
connector.setHost(address)
connector.setPort(port)
connector.setIdleTimeout(1000L
* idleTimeout)
server.addConnector(connector)
/***** end code *****/
Then for the ThreadPool part:
/***** start code *****/
val pool = new
QueuedThreadPool(maxThreads,minThreads,idleTimeout,new
ArrayBlockingQueue(queueSize))
val server = new Server(pool)
/***** end code *****/
HTTP/2 will seriously stress out your
thread pool.
Don't specify the queue, use
defaults.
Don't use less then defaults for
min/max threads with HTTP/2.
It's good that you are using the
QueuedThreadPool, it behaves much better
then a raw Executor with regards to
HTTP/2.
Threads are 10-100, idletimeouts I
have tried are from 1000 to 20000,
queueSize is now 500 but I have tried
both much smaller and larger values.
I have no idea what values would be
sensible. The number of concurrent
users is relatively low: up to a
couple of hundred, rarely more. Users
can do requests that take longish to
complete (sometimes up to 30 or even
60 seconds) but those are very rare.
The majority is relatively quick (<
50ms). Current load on the problematic
servers is very low (perhaps 10 users)
and as said: low memory and CPU close
to zero.
No problems with HTTP/1.1 with this
code/settings, problematic with
HTTP/2. Strangely enough some servers
seem fine (or users just did not
report any problems yet).
Start by using a default
QueuedThreadPool, no configuration, no
min thread, no max threads, all strictly
defaults.
Then monitor your usages and
behaviors with HTTP/2 enabled over at
least a week.
Then you can tune your maxThreads.
As to thread idle timeouts, don't
bother setting them yet.
Your connector.setIdleTimeout() is
far more useful to you.
Any help would be welcome.
Kind regards,
Silvio
Many folks have gotten HTTP/2 working
just fine in embedded-jetty.
The two most common issues:
1. Not having alpn support setup
properly
2. Too restrictive of an
SslContextFactory that is incompatible
with HTTP/2
When it comes to the ALPN suppport,
you have to worry about what JVM runtime
you are on first.
If you are using Java 8 then you have
to align your alpn-boot version to the
specific Java 8 JVM you are using.
Under Java 8, you MUST use the
-Xbootclasspath on JVM startup to have
alpn work properly.
However, if you are using Java 11
then you can use the
jetty-alpn-java-server artifact instead
(no bootclasspath requirement) to get
ALPN behaviors required for HTTP/2.
You also have a conscrypt option for
running ALPN + HTTP/2 on Jetty, which
will work the same regardless of Java 8
or Java 11.
When it comes to too restrictive of
an SslContextFactory we have the
following advice:
* If you are specifying Include
Cipher Suites you are too restrictive.
* Your certificates need to be RSA
(not DES) and at a higher bit size (like
2048+)
* If you are attempting to get old
Protocols (TLS/1.0 TLS/1.1) working,
then you are introducing incompatible
Cipher Suites too.
* If you are resetting the Exclude
Cipher Suites you are introducing
incompatible Cipher Suites.
* Avoid using Include Cipher Suites
(this exists for people stuck in the
past and not ever wanting to use HTTP/2)
* Avoid using Include Protocols (this
exists for people stuck supporting old
clients and not wanting to use HTTP/2)
* Add to the existing Exclude Cipher
Suites (if needed)
* Add to the existing Exclude
Protocols (if needed)
* Always use an Up to date
(not-expired) JVM
* Learn how to use the
SslContextFactory.dump() methods at
runtime to know what the current state
of your SslContextFactory is (including
all selected cipher suites and
protocols)
We have an example codebase that
shows how to start an HTTP/2 server
connector.
You can check the Jenkins project for
their usage of HTTP/2 on Embedded Jetty
as well. (their self executing WAR file
does just this)
You could also run h2spec against
your server and see if its behaving
properly.
- Joakim
On
20-11-18 16:06, Joakim Erdfelt
wrote:
How do you enable
HTTP/2 in your embedded
application?
Also, If you have configured
your SslContextFactory, what
does this configuration look
like?
Lastly, what does your
ThreadPool / Executor
configuration look like?
Hello
all,
We are running Jetty 9.4.14
embedded in an application that
runs on a
number of Ubuntu 18.10 servers.
Last night we switched from
HTTP1.1 only
to HTTP2. Today we are
experiencing serious problems.
Users can not
access the application or are
experiencing extremely long
latencies. At
the same time the server is
almost idle.
We have configured the Ubuntu
servers as almost default
setups.
OpenJDK11 with Jetty using pure
Java HTTPS. We have been doing
this for
years now and each time we
switched from HTTP1.1 to HTTP2
things started
falling apart. In the past we
had reports of people not being
able to
connect at all receiving
spurious messages from their
browsers (some of
which are undoubtedly outdated).
We expected things to have
improved by
now and decided to try again,
with the above result.
Are there additional things we
need to take care of when using
HTTP2
when compared to HTTP1.1? More
threads, different queue size,
more file
handles etc?
Any pointers would be very much
appreciated.
Kind regards,
Silvio
_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
To change your delivery options,
retrieve your password, or
unsubscribe from this list,
visit
https://www.eclipse.org/mailman/listinfo/jetty-users
_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users