Problem Statement
Currently RocketMQ Proxy supports only a single certificate model:
ProxyConfig has only tlsCertPath / tlsKeyPath for a single cert/key pair
- gRPC and Remoting servers each build a single
SslContext
TlsCertificateManager only watches one cert/key pair for hot-reload
- No SNI (Server Name Indication) support at all
This makes it impossible to serve multiple top-level domains (e.g. *.mq.com and *.rocketmq.com) with different certificates on the same Proxy port.
Proposed Solution
Introduce SNI (Server Name Indication) support using Netty's SniHandler. The Proxy will inspect the TLS ClientHello's SNI hostname and dynamically select the corresponding certificate.
Key Changes
- New
TlsDomainConfig POJO — per-domain cert/key path configuration
- Extended
ProxyConfig — new tlsDomainConfigs map (domain pattern → config)
- New
TlsSniManager — manages multiple SslContext instances with wildcard matching
- Extended
TlsCertificateManager — watches multiple cert/key pairs independently
- gRPC
ProxyAndTlsProtocolNegotiator — uses SniHandler for SNI-aware TLS
- Remoting
NettyRemotingServer — TlsModeHandler uses SniHandler via TlsContextProvider
Configuration Example
tlsCertPath: /path/to/default.crt
tlsKeyPath: /path/to/default.key
tlsDomainConfigs:
"*.alibaba-inc.com":
certPath: /path/to/alibaba.crt
keyPath: /path/to/alibaba.key
"*.rocketmq.com":
certPath: /path/to/rocketmq.crt
keyPath: /path/to/rocketmq.key
Wildcard Matching
- Exact match first
- Wildcard:
foo.rocketmq.com matches *.rocketmq.com
- Bare domain:
rocketmq.com matches *.rocketmq.com
- Multi-level (
a.b.rocketmq.com) does NOT match *.rocketmq.com
- No match → fallback to default certificate
Verification
Manual verification with openssl s_client:
# .com domain → should return *.rocketmq.com cert
openssl s_client -connect 127.0.0.1:<proxyPort> -servername test.rocketmq.com </dev/null 2>/dev/null | openssl x509 -noout -subject
# .alibaba domain → should return *.alibaba-inc.com cert
openssl s_client -connect 127.0.0.1:<proxyPort> -servername test.alibaba-inc.com </dev/null 2>/dev/null | openssl x509 -noout -subject
# No SNI → should return default (localhost) cert
openssl s_client -connect 127.0.0.1:<proxyPort> </dev/null 2>/dev/null | openssl x509 -noout -subject
Backward Compatibility
When tlsDomainConfigs is not configured, the behavior is identical to the current single-certificate model.
Risks
- Netty SniHandler async nature — needs verification that gRPC's
ProxyAndTlsProtocolNegotiator pipeline is compatible
- Pipeline order —
TlsModeHandler (PERMISSIVE mode detection) must run before SniHandler
- Old clients without SNI — will fallback to default certificate
- TlsSystemConfig compatibility — Remoting's static config system needs backward compatibility
Related PR
#10295
Problem Statement
Currently RocketMQ Proxy supports only a single certificate model:
ProxyConfighas onlytlsCertPath/tlsKeyPathfor a single cert/key pairSslContextTlsCertificateManageronly watches one cert/key pair for hot-reloadThis makes it impossible to serve multiple top-level domains (e.g.
*.mq.comand*.rocketmq.com) with different certificates on the same Proxy port.Proposed Solution
Introduce SNI (Server Name Indication) support using Netty's
SniHandler. The Proxy will inspect the TLS ClientHello's SNI hostname and dynamically select the corresponding certificate.Key Changes
TlsDomainConfigPOJO — per-domain cert/key path configurationProxyConfig— newtlsDomainConfigsmap (domain pattern → config)TlsSniManager— manages multipleSslContextinstances with wildcard matchingTlsCertificateManager— watches multiple cert/key pairs independentlyProxyAndTlsProtocolNegotiator— usesSniHandlerfor SNI-aware TLSNettyRemotingServer—TlsModeHandlerusesSniHandlerviaTlsContextProviderConfiguration Example
Wildcard Matching
foo.rocketmq.commatches*.rocketmq.comrocketmq.commatches*.rocketmq.coma.b.rocketmq.com) does NOT match*.rocketmq.comVerification
Manual verification with
openssl s_client:Backward Compatibility
When
tlsDomainConfigsis not configured, the behavior is identical to the current single-certificate model.Risks
ProxyAndTlsProtocolNegotiatorpipeline is compatibleTlsModeHandler(PERMISSIVE mode detection) must run beforeSniHandlerRelated PR
#10295