Spring Boot 3.2 SSL Bundles配置OCSP Stapling与TLS 1.3会话恢复

好的,我们开始今天的讲座:Spring Boot 3.2 SSL Bundles 配置 OCSP Stapling 与 TLS 1.3 会话恢复。

引言:SSL/TLS 安全的重要性

在现代网络应用中,SSL/TLS 安全至关重要。它不仅保护数据在传输过程中的机密性和完整性,还验证服务器的身份,防止中间人攻击。随着安全威胁的不断演变,我们需要持续关注和采用最新的安全技术。Spring Boot 3.2 引入的 SSL Bundles 提供了一种便捷的方式来配置 SSL/TLS,并支持 OCSP Stapling 和 TLS 1.3 会话恢复等高级特性。

1. SSL Bundles 简介

Spring Boot 3.2 引入的 SSL Bundles 是一种简化 SSL/TLS 配置的方式。它允许你将所有相关的 SSL/TLS 配置(例如证书、密钥、信任库等)集中管理,并通过一个逻辑名称引用它们。这大大简化了配置过程,并提高了可维护性。

2. 准备工作:生成证书与密钥

首先,我们需要生成 SSL 证书和密钥。可以使用 openssl 工具完成此操作。

  • 生成私钥:

    openssl genrsa -out key.pem 2048
  • 创建证书签名请求 (CSR):

    openssl req -new -key key.pem -out csr.pem

    在提示中,你需要提供一些信息,例如国家/地区、组织名称、通用名称 (Common Name, CN)。 Common Name 需要填写你的域名或者IP地址。

  • 自签名证书(生产环境不建议使用,应使用权威CA机构签发的证书):

    openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out cert.pem

    这会创建一个有效期为 365 天的自签名证书 cert.pem

  • 生成PKCS12格式的证书库(用于Spring Boot配置)

    openssl pkcs12 -export -inkey key.pem -in cert.pem -name "yourdomain" -out certificate.p12

    在提示中,你需要设置一个密码,这个密码将在 Spring Boot 配置中使用。

3. Spring Boot 项目配置

创建一个 Spring Boot 项目,并在 application.propertiesapplication.yml 中配置 SSL Bundles。

  • application.yml 示例:

    server:
      port: 8443
      ssl:
        bundle:
          mybundle:
            key-store-type: PKCS12
            key-store: classpath:certificate.p12
            key-store-password: your_password
            key-alias: yourdomain
            key-password: your_password
    
    management:
      server:
        port: 9443 # 为management endpoint 配置单独的端口, 避免和业务端口冲突
        ssl:
          bundle:
            managementbundle:
              key-store-type: PKCS12
              key-store: classpath:certificate.p12
              key-store-password: your_password
              key-alias: yourdomain
              key-password: your_password
    
    spring:
      ssl:
        bundle:
          pemfile:
            certificate: classpath:cert.pem
            private-key: classpath:key.pem
      application:
        name: ssl-bundle-demo

    在这个示例中,我们定义了一个名为 mybundle 的 SSL Bundle。 key-store-type 指定密钥库类型为 PKCS12,key-store 指定密钥库文件的路径,key-store-password 指定密钥库密码,key-alias 指定密钥别名, key-password指定密钥密码.

    managementbundle 为 Spring Boot Actuator 的 management endpoint 配置了独立的SSL。

    pemfile 配置则使用单独的证书和私钥文件,而不是密钥库。

  • 配置 HTTPS Connector:

    import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
    import org.springframework.boot.web.server.WebServerFactoryCustomizer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class TomcatConfiguration {
    
        @Bean
        public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() {
            return tomcatServletWebServerFactory -> {
                tomcatServletWebServerFactory.addConnectorCustomizers(connector -> {
                    connector.setScheme("https");
                    connector.setSecure(true);
                    connector.setPort(8443); // HTTPS 端口
                    connector.setAttribute("SSLEnabled", true);
                    connector.setAttribute("sslImplementationName", org.apache.tomcat.util.net.openssl.OpenSSLImplementation.class.getName());
                    connector.setAttribute("sslProtocol", "TLSv1.3"); // 显式指定TLS协议版本
                    connector.setAttribute("SSLCertificateFile", "classpath:cert.pem"); // PEM 格式证书路径
                    connector.setAttribute("SSLCertificateKeyFile", "classpath:key.pem"); // PEM 格式私钥路径
                });
            };
        }
    }

    这段代码使用 TomcatServletWebServerFactory 来定制 Tomcat Connector,并设置 HTTPS 相关的属性。这里使用了PEM格式的证书和私钥,通过 SSLCertificateFileSSLCertificateKeyFile 指定。 sslProtocol 显式指定了TLS版本为 TLSv1.3。

4. OCSP Stapling 配置

OCSP Stapling 是一种优化 SSL/TLS 握手过程的技术。它允许服务器定期从证书颁发机构 (CA) 获取证书的 OCSP (Online Certificate Status Protocol) 响应,并将响应“staple”到 SSL/TLS 握手过程中。这避免了客户端在每次连接时都向 CA 查询证书状态,从而提高了性能和隐私。

  • 开启 OCSP Stapling:

    application.yml 中配置 OCSP Stapling。

    server:
      port: 8443
      ssl:
        bundle:
          mybundle:
            key-store-type: PKCS12
            key-store: classpath:certificate.p12
            key-store-password: your_password
            key-alias: yourdomain
            key-password: your_password
            ocsp:
              enabled: true # 启用 OCSP Stapling
    
    management:
      server:
        port: 9443
        ssl:
          bundle:
            managementbundle:
              key-store-type: PKCS12
              key-store: classpath:certificate.p12
              key-store-password: your_password
              key-alias: yourdomain
              key-password: your_password
              ocsp:
                enabled: true
    
    spring:
      ssl:
        bundle:
          pemfile:
            certificate: classpath:cert.pem
            private-key: classpath:key.pem
            ocsp:
              enabled: true
      application:
        name: ssl-bundle-demo

    ocsp.enabled 设置为 true 即可启用 OCSP Stapling。 这需要在 mybundle, managementbundle, 和 pemfile 三个bundle中分别进行配置。

  • 确认 OCSP Stapling 是否生效:

    可以使用 openssl s_client 命令连接到服务器,并检查 OCSP Stapling 是否生效。

    openssl s_client -connect localhost:8443 -status

    如果 OCSP Stapling 生效,你应该在输出中看到 OCSP response: ... 这样的信息。

    如果没有生效,检查服务器日志,查看是否有 OCSP 相关的错误信息。通常是因为 CA 服务器不可达,或者证书配置不正确。

5. TLS 1.3 会话恢复配置

TLS 1.3 引入了更高效的会话恢复机制,可以减少 SSL/TLS 握手的开销,提高性能。会话恢复允许客户端和服务器重用之前的会话密钥,而无需完全重新协商。

  • 启用 TLS 1.3:

    在 Spring Boot 中,默认情况下会启用 TLS 1.3(如果 JDK 支持)。 但是,为了确保启用,你可以显式地配置支持的 TLS 协议版本。

    application.yml 中配置支持的 TLS 协议:

    server:
      port: 8443
      ssl:
        bundle:
          mybundle:
            key-store-type: PKCS12
            key-store: classpath:certificate.p12
            key-store-password: your_password
            key-alias: yourdomain
            key-password: your_password
            enabled-protocols: TLSv1.3
    
    management:
      server:
        port: 9443
        ssl:
          bundle:
            managementbundle:
              key-store-type: PKCS12
              key-store: classpath:certificate.p12
              key-store-password: your_password
              key-alias: yourdomain
              key-password: your_password
              enabled-protocols: TLSv1.3
    
    spring:
      ssl:
        bundle:
          pemfile:
            certificate: classpath:cert.pem
            private-key: classpath:key.pem
            enabled-protocols: TLSv1.3
      application:
        name: ssl-bundle-demo

    设置 enabled-protocolsTLSv1.3。 你也可以同时支持多个协议版本,例如 enabled-protocols: TLSv1.2,TLSv1.3

  • 配置会话缓存:

    为了有效利用会话恢复,你需要配置会话缓存的大小和超时时间。 这可以通过 Tomcat Connector 的属性进行配置。

    TomcatConfiguration 中配置:

    import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
    import org.springframework.boot.web.server.WebServerFactoryCustomizer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class TomcatConfiguration {
    
        @Bean
        public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() {
            return tomcatServletWebServerFactory -> {
                tomcatServletWebServerFactory.addConnectorCustomizers(connector -> {
                    connector.setScheme("https");
                    connector.setSecure(true);
                    connector.setPort(8443); // HTTPS 端口
                    connector.setAttribute("SSLEnabled", true);
                    connector.setAttribute("sslImplementationName", org.apache.tomcat.util.net.openssl.OpenSSLImplementation.class.getName());
                    connector.setAttribute("sslProtocol", "TLSv1.3"); // 显式指定TLS协议版本
                    connector.setAttribute("SSLCertificateFile", "classpath:cert.pem"); // PEM 格式证书路径
                    connector.setAttribute("SSLCertificateKeyFile", "classpath:key.pem"); // PEM 格式私钥路径
                    connector.setAttribute("sessionCacheSize", "1000"); // 会话缓存大小
                    connector.setAttribute("sessionTimeout", "300"); // 会话超时时间 (秒)
                });
            };
        }
    }

    sessionCacheSize 设置会话缓存的大小(例如 1000 个会话),sessionTimeout 设置会话超时时间(例如 300 秒)。

  • 验证会话恢复是否生效:

    可以使用 openssl s_client 命令连接到服务器,并在第一次连接后关闭连接,然后再次连接。 如果会话恢复生效,第二次连接的速度应该比第一次快。

    openssl s_client -connect localhost:8443 -tls1_3

    在输出中,你可以观察到会话是否被重用。 观察 New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256 这行输出。 如果是新的会话,会显示 New。 如果是恢复的会话,可能显示 Reused, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256 或者类似的指示会话重用的信息。

6. 其他配置选项

SSL Bundles 还支持许多其他配置选项,例如:

  • trust-storetrust-store-password 用于配置信任库,包含信任的 CA 证书。
  • client-auth 用于配置客户端身份验证,可以设置为 needwant
  • ciphers 用于配置支持的密码套件。

7. 代码示例:完整的 Spring Boot 应用

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class SslBundleDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SslBundleDemoApplication.class, args);
    }

    @RestController
    static class HelloController {
        @GetMapping("/hello")
        public String hello() {
            return "Hello, SSL!";
        }
    }

    @Configuration
    public class TomcatConfiguration {

        @Bean
        public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() {
            return tomcatServletWebServerFactory -> {
                tomcatServletWebServerFactory.addConnectorCustomizers(connector -> {
                    connector.setScheme("https");
                    connector.setSecure(true);
                    connector.setPort(8443); // HTTPS 端口
                    connector.setAttribute("SSLEnabled", true);
                    connector.setAttribute("sslImplementationName", org.apache.tomcat.util.net.openssl.OpenSSLImplementation.class.getName());
                    connector.setAttribute("sslProtocol", "TLSv1.3"); // 显式指定TLS协议版本
                    connector.setAttribute("SSLCertificateFile", "classpath:cert.pem"); // PEM 格式证书路径
                    connector.setAttribute("SSLCertificateKeyFile", "classpath:key.pem"); // PEM 格式私钥路径
                    connector.setAttribute("sessionCacheSize", "1000"); // 会话缓存大小
                    connector.setAttribute("sessionTimeout", "300"); // 会话超时时间 (秒)
                });
            };
        }
    }
}

这个示例包含了一个简单的 Spring Boot 应用,它提供了一个 /hello 端点,并配置了 HTTPS、OCSP Stapling 和 TLS 1.3 会话恢复。 请确保 cert.pemkey.pem 文件位于 src/main/resources 目录下,并且 application.yml 文件也配置正确。

8. 故障排除

  • 证书问题: 确保证书有效,并且与密钥匹配。检查证书的有效期和域名是否正确。
  • 密钥库密码错误: 确保在 application.yml 中配置的密钥库密码正确。
  • OCSP Stapling 失败: 检查 CA 服务器是否可达,以及证书是否支持 OCSP。查看服务器日志,查找 OCSP 相关的错误信息。
  • TLS 版本问题: 确保 JDK 支持配置的 TLS 版本。 可以使用 java -version 命令查看 JDK 版本。
  • 防火墙问题: 确保防火墙没有阻止 HTTPS 流量。

9. 表格:SSL Bundle 配置选项

配置项 说明
key-store-type 密钥库类型,例如 PKCS12, JKS。
key-store 密钥库文件路径。
key-store-password 密钥库密码。
key-alias 密钥别名。
key-password 密钥密码。
trust-store 信任库文件路径。
trust-store-password 信任库密码。
client-auth 客户端身份验证,可选值为 needwant
ciphers 支持的密码套件列表。
enabled-protocols 支持的 TLS 协议版本列表,例如 TLSv1.2,TLSv1.3
ocsp.enabled 是否启用 OCSP Stapling。
certificate PEM 格式的证书文件路径 (用于pemfile bundle)。
private-key PEM 格式的私钥文件路径 (用于pemfile bundle)。

文章总结:配置安全的应用

Spring Boot 3.2 的 SSL Bundles 提供了一种便捷的方式来配置 SSL/TLS,并支持 OCSP Stapling 和 TLS 1.3 会话恢复等高级特性。 通过正确配置这些特性,可以提高应用的安全性、性能和用户体验。请务必在生产环境中使用权威 CA 机构签发的证书。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注