mozilla / ssl-config-generator

Mozilla SSL Configuration Generator
https://ssl-config.mozilla.org/
Mozilla Public License 2.0
358 stars 59 forks source link

Add support for Jetty #92

Closed ghost closed 4 years ago

ghost commented 4 years ago

Hi. Was recently using this tool to enhance security of my servers, and run into some Jetty instances, and took me a while implementing the same configurations for it as for Tomcat.

Considering Jetty is pretty popular, I think Jetty support would become really handy. The configuration is almost as simple as Tomcat or any other server.

april commented 4 years ago

Sure, if you could send me some sample configurations I'd be happy to add them.

ghost commented 4 years ago

Hi. This is the relevant part of jetty.xml. Everything is inside the root element

        <New id="zimbraSslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
                <Set name="KeyStorePath"><SystemProperty name="jetty.base" default="." />/etc/keystore</Set>
                <Set name="KeyStorePassword">*********</Set>
                <Set name="KeyManagerPassword">*********</Set>
                <Set name="EndpointIdentificationAlgorithm"></Set>
                <Set name="renegotiationAllowed">FALSE</Set>
                <!-- SSLPROTOCOLSBEGIN -->
                <Set name="IncludeProtocols">
                        <Array type="java.lang.String">
                                <Item>TLSv1.2</Item>
                        </Array>
                </Set>
                <!-- SSLPROTOCOLSEND -->
                <Set name="ExcludeCipherSuites">
                        <Array type="java.lang.String">
                                <Item>.*_RC4_.*</Item>
<Item>.*DES.*</Item>
<Item>.*DSS.*</Item>
<Item>.*MD5.*</Item>
<Item>.*NULL.*</Item>
<Item>.*RC4.*</Item>
                        </Array>
                </Set>
                <!-- INCLUDESUITESBEGIN -->
                <Set name="IncludeCipherSuites">
                        <Array type="java.lang.String">
                                <Item>TLS_DHE_RSA_WITH_AES_128_GCM_SHA256</Item>
<Item>TLS_DHE_RSA_WITH_AES_256_GCM_SHA384</Item>
<Item>TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</Item>
<Item>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384</Item>
<Item>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</Item>
<Item>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</Item>
                        </Array>
                </Set>
                <!-- INCLUDESUITESEND -->
        </New>

Of course, the "id" attribute in the <New tag should be the same later passed on the "addConnector" call:

        <Call id="httpsConnector" name="addConnector">
                <Arg>
                        <New id="ssl" class="org.eclipse.jetty.server.ServerConnector">
                                <Arg name="server">
                                        <Ref refid="Server" />
                                </Arg>
                                <Arg name="factories">
                                        <Array type="org.eclipse.jetty.server.ConnectionFactory">
                                                <Item>
                                                        <New class="org.eclipse.jetty.server.SslConnectionFactory">
                                                                <Arg name="next">http/1.1</Arg>
                                                                <Arg name="sslContextFactory">
                                                                        <Ref refid="zimbraSslContextFactory" />
                                                                </Arg>
                                                        </New>
                                                </Item>
                                                <Item>
                                                        <New class="org.eclipse.jetty.server.HttpConnectionFactory">
                                                                <Arg name="config">
                                                                        <Ref refid="sslHttpConfig" />
                                                                </Arg>
                                                        </New>
                                                </Item>
                                        </Array>
                                </Arg>
                                <Set name="host"></Set>
                                <Set name="port">443</Set>
                                <Set name="idleTimeout">60000</Set>
                        </New>
                </Arg>
        </Call>

As you may see, the configuration is not made by myself, but rather by Zimbra. But it's pretty easy to understand. Also, the configuration sequenceis tightly linked to Java code creating instances and calling methods.

Protocols can be either be included ("IncludeProtocols" Set) or excluded ("excludeProtocols" Set). Same logic applies to cipher suites. In the later, wildcards are allowed, and standard names are used.

The shown value for "ExcludeCipherSuites" is my own choice. The one for "IncludeCipherSuites" is a reduced version of the "Intermediate" configuration. The argument "renegotiationAllowed" is also my choice, but a common security advice.

Adding this: <Set name="UseCipherSuitesOrder">TRUE</Set> Will force the server to use it's own cipher order; setting it to FALSE will make the server use client order. Apparently, the default is TRUE.

OCSP Stapling can theorically be enabled with two calls:

<Set name="EnableOCSP">TRUE</Set>
<Set name="OcspResponderURL">http://ocsp.sectigo.com</Set>

Unfortunatelly, unlike other servers, which parse the certificate in order to get OCSP responder URL, Jetty does not, so it has to be configured manually. Therefore, the above mentioned is just an example.

Regarding HSTS, as Jetty is designed with strong focus on being embedded into applications, it is apparently expected that the application takes responsibility for HSTS. However, looking around, found this trick:

    <Set name="handler">
      <New id="Handlers" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
(...)
        <Call name="addRule">
            <Arg>
                <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
                    <Set name="pattern">*</Set>
                    <Set name="name">Strict-Transport-Security</Set>
                    <Set name="value">max-age=31536000;includeSubDomains</Set>
                </New>
            </Arg>
        </Call>

Does this fill the requirement?

april commented 4 years ago

I've pushed out some initial support for Jetty:

https://ssl-config.mozilla.org/#server=jetty

It would be awesome if someone from the Jetty project could comment that it looks okay, maybe @sbordet? I don't have OCSP or HSTS working, currently.