java - 使用 Java 8 在嵌入式 Tomcat 8.5 上启用 TLS 握手的可观察性(日志记录/指标)

标签 java spring-boot tomcat ssl embedded-tomcat-8

我们正在运行 Spring Boot API,我们在 API 本身中终止 TLS。有好几次,我们观察到由于某人创建许多连接(合法或错误地因为拒绝客户端证书)或未使用 TLS 恢复而导致大量搜索后 CPU 使用率过高。

为了防止将来进行这些耗时长且代价高昂的搜索,我们希望记录握手失败或成功的时间,以及为什么以及是否使用 session 恢复。

我们并没有特别依赖于我们当前的堆栈,升级到不同的服务器,如 Undertow 或 WebFlux,和/或新版本的 Java 也可以。同样,我们可以使用 APR、NIO 或 native 绑定(bind)来实现这些目标。

以下其他问题表明目前没有开箱即用的解决方案。他们建议延长 JSSEImplementationcreate customized SSL Socket Factory , 或者将 NIO 适配器的级别设置为 Debug。这些解决方案感觉很脆弱,我想知道是否有基于事件或回调的更具扩展性的机制。或者,我们可以从 Java 启用握手日志,但这些日志很冗长,而且这样做会严重影响性能。

更新 1: 我尝试使用自定义的 SSLServerSocketFactory。 sun.security.ssl.SSLServerSocketFactoryImpl 在绑定(bind)时返回一个 sun.security.ssl.SSLServerSocketImpl,在接受时返回一个不错的 SSLSocket。我可以始终包装该 accept 方法以添加完成处理程序。唯一的缺点是:SSLServerSocketFactoryImpl 是最终的,所以我不能只包装它。这意味着我需要复制大量代码,而且它仍然只会给我成功握手的指标。复制代码会造成维护负担,因为这是 JRE 特定的代码。

最佳答案

我的回答可能不是你所期望的,但这是我自己会做的。

首先,我从不在自定义软件上启用 SSL。既不是 Java,也不是 C#,也不是 Python,也不是 Javascript。在我所有的解决方案中,它们都通过纯 HTTP 运行。

我委托(delegate)给 NGINX 的所有 TLS 内容。这是可靠的。它很快。它有很多选择。它具有多功能和详细的日志。它有一些基本的访问控制和 DDoS 保护。它封装了部署的细节,并为多个提供的服务提供了一个外观。

开销很小,即使在适度的硬件上也能很好地运行。

您需要两个功能:反向代理和详细日志记录。

最简单的配置文件如下所示:

server {
        listen 443 ssl;

        server_name example.com;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;

        location / {
                # Transfer all request to the actual server using HTTP
                proxy_pass http://<server-in-intranet>:12345;
                proxy_set_header Host $host;
        }
        # TLS handshake errors are reported at the info level
        error_log /var/log/nginx/example.com/error.log info;
        # Extra ideas about SSL logging: 
        #   https://docs.nginx.com/nginx/admin-guide/monitoring/logging/#tls_sample

        # The certificates from Let's Encrypt are installed by Certbot
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
}

使用此配置服务器 https://example.com/通过 HTTPS 为您的实际服务器提供内容,该服务器在 Intranet 内某处运行,而实际服务器是纯 HTTP。

使用此设置,我运行用 Go、Javascript 和 Python 编写的服务器,这些服务器运行在不同的机器上,但在单个访问点下收集,例如https://global.name/service1/ , https://global.name/service2/ , https://global.name/service3/

关于java - 使用 Java 8 在嵌入式 Tomcat 8.5 上启用 TLS 握手的可观察性(日志记录/指标),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52289501/

相关文章:

java - Struts 标签覆盖实际的上下文路径

java - 阻止 spring boot 执行故障安全插件

java - 如何在 swagger-ui 中获取 POST 数据?

rest - Spring boot Embedded tomcat 中 jersey Servlet 注册的编程等效

java - 修改IntelliJ中Java代码编辑器生成 `toString`方法使用的模板

java - 如何在 AppCompatButton 旋转时更改其背景?

java - java中的内存不足错误

java - @KafkaListener 不使用消息 - 反序列化问题

java - 用于应用程序部署的负载平衡 Tomcat 7

java - 在 Java 中以用户身份登录