You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Netty服务器:如何添加SAN白名单绕过主机名验证及重写验证方法?

Netty 自定义SAN白名单绕过主机名验证方案

你可以通过两种方式重写Netty的主机名验证逻辑,实现SAN条目白名单功能:

方法一:自定义HostnameVerifier并配置到SslContext

直接实现HostnameVerifier接口,在逻辑中加入SAN白名单校验,替代默认的HTTPS端点验证:

// 定义SAN白名单集合
private static final Set<String> SAN_WHITELIST = new HashSet<>(Arrays.asList(
    "allowed-host-1.com",
    "allowed-host-2.com",
    "192.168.1.100" // 支持IP类型的SAN条目
));

// 自定义主机名验证器
HostnameVerifier customVerifier = (hostname, session) -> {
    try {
        // 获取对方证书
        X509Certificate cert = (X509Certificate) session.getPeerCertificates()[0];
        Collection<List<?>> sanEntries = cert.getSubjectAlternativeNames();
        
        if (sanEntries != null) {
            for (List<?> entry : sanEntries) {
                Integer type = (Integer) entry.get(0);
                String sanValue = (String) entry.get(1);
                // 2=DNS类型SAN,7=IP类型SAN
                if ((type == 2 || type == 7) && SAN_WHITELIST.contains(sanValue.toLowerCase())) {
                    return true;
                }
            }
        }
        // 可选: fallback 验证原始请求hostname
        return SAN_WHITELIST.contains(hostname.toLowerCase());
    } catch (CertificateException e) {
        return false;
    }
};

// 构建SslContext时绑定自定义验证器
SslContext sslContext = SslContextBuilder.forServer(new File("server.crt"), new File("server.key"))
    .hostnameVerifier(customVerifier)
    .build();

配置后,Netty会用这个自定义验证器接管主机名校验,无需再手动设置setEndpointIdentificationAlgorithm。

方法二:重写SslHandler的verifyPeerCertificate方法

如果需要更细粒度的控制,可以继承SslHandler,重写证书验证逻辑:

public class WhitelistedSslHandler extends SslHandler {
    private static final Set<String> SAN_WHITELIST = new HashSet<>(Arrays.asList(
        "allowed-host-1.com",
        "192.168.1.100"
    ));

    public WhitelistedSslHandler(SSLEngine engine) {
        super(engine);
    }

    @Override
    protected void verifyPeerCertificate(X509Certificate[] peerCerts, String hostname) throws SSLException {
        boolean isWhitelisted = false;
        try {
            X509Certificate cert = peerCerts[0];
            Collection<List<?>> sanEntries = cert.getSubjectAlternativeNames();
            
            if (sanEntries != null) {
                for (List<?> entry : sanEntries) {
                    Integer type = (Integer) entry.get(0);
                    String sanValue = ((String) entry.get(1)).toLowerCase();
                    if ((type == 2 || type == 7) && SAN_WHITELIST.contains(sanValue)) {
                        isWhitelisted = true;
                        break;
                    }
                }
            }
            
            // 白名单匹配则跳过默认验证,否则执行原有逻辑
            if (!isWhitelisted) {
                super.verifyPeerCertificate(peerCerts, hostname);
            }
        } catch (CertificateException e) {
            throw new SSLException("证书SAN校验失败", e);
        }
    }
}

使用时替换原有的SslHandler:

SSLEngine sslEngine = getSSLEngine();
SslHandler sslHandler = new WhitelistedSslHandler(sslEngine);
channelPipeline.addLast(sslHandler);

注意事项

  • 生产环境避免完全禁用验证,严格控制白名单范围
  • 建议统一将SAN条目和请求hostname转成小写后再比较,避免大小写不匹配问题

内容的提问来源于stack exchange,提问作者user1845029

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 15:54:25