apache / apache/rocketmq

[Feature] SNI multi-domain certificate support for Proxy TLS

Open
#10,302 8 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
22.6k
Forks
12k
Avg merge
2d 20h
Merged PRs (30d)
26

Description

### Is Your Feature Request Related to a Problem?

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 with different certificates on the same Proxy port.

### Describe the Solution You'd Like

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:

1. **New `TlsDomainConfig` POJO** — per-domain cert/key path configuration
2. **Extended `ProxyConfig`** — new `tlsDomainConfigs` map (domain pattern → config)
3. **New `TlsSniManager`** — manages multiple `SslContext` instances with wildcard matching
4. **Extended `TlsCertificateManager`** — watches multiple cert/key pairs independently
5. **gRPC `ProxyAndTlsProtocolNegotiator`** — uses `SniHandler` for SNI-aware TLS
6. **Remoting `NettyRemotingServer`** — `TlsModeHandler` uses `SniHandler` via `TlsContextProvider`

### Describe Alternatives You've Considered

The alternative is to run multiple Proxy instances, each with a different certificate, behind a reverse proxy (e.g. nginx) that handles SNI. However, this adds operational complexity and an extra network hop.

### Additional Context

**Configuration example:**

```yaml
# Existing config retained as default fallback
tlsCertPath: /path/to/default.crt
tlsKeyPath: /path/to/default.key
tlsCertWatchIntervalMs: 3600000

# New: domain-to-certificate mapping
tlsDomainConfigs:
"*.example.com":
certPath: /path/to/example.crt
keyPath: /path/to/example.key
"*.sample.org":
certPath: /path/to/sample.crt
keyPath: /path/to/sample.key
```

**Wildcard matching rules:**

- Exact match first
- Wildcard: `foo.example.com` matches `*.example.com`
- Bare domain: `example.com` matches `*.example.com`
- Multi-level (`a.b.example.com`) does NOT match `*.example.com`
- No match → fallback to default certificate

**Backward compatibility:** When `tlsDomainConfigs` is not configured, the behavior is identical to the current single-certificate model.

Contributor guide

Open the contributing guide

Research direction

Start by tracing the existing single-certificate flow through ProxyConfig, TlsCertificateManager, ProxyAndTlsProtocolNegotiator, and NettyRemotingServer. Define the multi-domain configuration, certificate watching, SNI selection, wildcard rules, fallback behavior, and backward compatibility described in the issue; done means both gRPC and Remoting select the correct certificate and retain the current default behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend, networking, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.