Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions docs/cn/Configuration_TLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,45 @@ public class ExampleProducer {

// Send messages as usual.
producer.shutdown();
}
}
}
```
```

## 5 Proxy TLS 配置

RocketMQ Proxy 使用 `rmq-proxy.json`(而非 `tls.properties`)进行 TLS 配置。Proxy 的 gRPC 和 Remoting 协议端口均支持 TLS。

### 5.1 配置 rmq-proxy.json

在 `distribution/conf/rmq-proxy.json` 中添加 TLS 相关字段:

```json
{
"rocketMQClusterName": "DefaultCluster",
"tlsTestModeEnable": false,
"tlsKeyPath": "/opt/certFiles/server.key",
"tlsKeyPassword": "123456",
"tlsCertPath": "/opt/certFiles/server.pem"
}
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `tlsTestModeEnable` | boolean | `true` | 是否使用自签名测试证书,生产环境需设为 `false` |
| `tlsKeyPath` | string | `${PROXY_HOME}/conf/tls/rocketmq.key` | 服务端私钥文件路径(PKCS#8 PEM 格式) |
| `tlsKeyPassword` | string | `""` | 加密私钥的密码,私钥未加密时留空 |
| `tlsCertPath` | string | `${PROXY_HOME}/conf/tls/rocketmq.crt` | 服务端证书链文件路径(X.509 PEM 格式) |
| `tlsCertWatchIntervalMs` | int | `3600000` | 证书文件变更检测间隔(毫秒) |

### 5.2 配置 Proxy 启动参数

编辑 `runproxy.sh`(或启动 Proxy 的脚本),启用 TLS enforcing 模式:

```shell
JAVA_OPT="${JAVA_OPT} -Dtls.server.mode=enforcing"
```

三种 TLS 模式说明:
- `disabled` - 不支持 TLS,拒绝所有 TLS 握手请求
- `permissive` - TLS 可选,同时接受 TLS 和非 TLS 连接
- `enforcing` - 强制 TLS,拒绝非 TLS 连接
41 changes: 40 additions & 1 deletion docs/en/Configuration_TLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,45 @@ public class ExampleProducer {

// Send messages as usual.
producer.shutdown();
}
}
}
```

## 5 Proxy TLS Configuration

RocketMQ Proxy uses `rmq-proxy.json` (not `tls.properties`) for TLS configuration. The proxy supports TLS for both its gRPC and Remoting protocol endpoints.

### 5.1 Configure rmq-proxy.json

Add TLS-related fields to `distribution/conf/rmq-proxy.json`:

```json
{
"rocketMQClusterName": "DefaultCluster",
"tlsTestModeEnable": false,
"tlsKeyPath": "/opt/certFiles/server.key",
"tlsKeyPassword": "123456",
"tlsCertPath": "/opt/certFiles/server.pem"
}
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `tlsTestModeEnable` | boolean | `true` | Use self-signed certificates for testing. Set to `false` for production. |
| `tlsKeyPath` | string | `${PROXY_HOME}/conf/tls/rocketmq.key` | Path to the server private key file (PKCS#8 PEM format). |
| `tlsKeyPassword` | string | `""` | Password for the encrypted private key. Leave empty if the key is not encrypted. |
| `tlsCertPath` | string | `${PROXY_HOME}/conf/tls/rocketmq.crt` | Path to the server certificate chain file (X.509 PEM format). |
| `tlsCertWatchIntervalMs` | int | `3600000` | Interval in milliseconds to check for certificate file changes. |

### 5.2 Update Proxy JVM parameters

Edit `runproxy.sh` (or the script that launches the proxy) to enable TLS enforcing mode:

```shell
JAVA_OPT="${JAVA_OPT} -Dtls.server.mode=enforcing"
```

The three available TLS modes are:
- `disabled` - TLS is not supported; incoming TLS handshakes are rejected.
- `permissive` - TLS is optional; the proxy accepts both TLS and non-TLS connections.
- `enforcing` - TLS is required; non-TLS connections are rejected.
2 changes: 1 addition & 1 deletion proxy/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ java_library(
"src/test/resources/rmq-proxy-home/conf/broker.conf",
"src/test/resources/rmq-proxy-home/conf/logback_proxy.xml",
"src/test/resources/rmq-proxy-home/conf/rmq-proxy.json",
],
] + glob(["src/test/resources/certs/*.pem"]) + glob(["src/test/resources/certs/*.key"]),
visibility = ["//visibility:public"],
deps = [
"//auth",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public class ProxyConfig implements ConfigFile {
*/
private boolean tlsTestModeEnable = true;
private String tlsKeyPath = ConfigurationManager.getProxyHome() + "/conf/tls/rocketmq.key";
private String tlsKeyPassword = "";
private String tlsCertPath = ConfigurationManager.getProxyHome() + "/conf/tls/rocketmq.crt";
private int tlsCertWatchIntervalMs = 60 * 60 * 1000; // 1 hour
/**
Expand Down Expand Up @@ -501,6 +502,14 @@ public void setTlsKeyPath(String tlsKeyPath) {
this.tlsKeyPath = tlsKeyPath;
}

public String getTlsKeyPassword() {
return tlsKeyPassword;
}

public void setTlsKeyPassword(String tlsKeyPassword) {
this.tlsKeyPassword = tlsKeyPassword;
}

public String getTlsCertPath() {
return tlsCertPath;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,14 @@ public static void loadSslContext() throws CertificateException, IOException {
} else {
String tlsCertPath = ConfigurationManager.getProxyConfig().getTlsCertPath();
String tlsKeyPath = ConfigurationManager.getProxyConfig().getTlsKeyPath();
String tlsKeyPassword = ConfigurationManager.getProxyConfig().getTlsKeyPassword();
try (InputStream serverKeyInputStream = Files.newInputStream(
Paths.get(tlsKeyPath));
InputStream serverCertificateStream = Files.newInputStream(
Paths.get(tlsCertPath))) {
sslContext = GrpcSslContexts.forServer(serverCertificateStream,
serverKeyInputStream)
serverKeyInputStream,
StringUtils.isNotBlank(tlsKeyPassword) ? tlsKeyPassword : null)
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.clientAuth(ClientAuth.NONE)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ public RemotingProtocolServer(MessagingProcessor messagingProcessor, TlsCertific
System.setProperty(TlsSystemConfig.TLS_SERVER_CERTPATH, config.getTlsCertPath());
TlsSystemConfig.tlsServerKeyPath = config.getTlsKeyPath();
System.setProperty(TlsSystemConfig.TLS_SERVER_KEYPATH, config.getTlsKeyPath());
TlsSystemConfig.tlsServerKeyPassword = config.getTlsKeyPassword();
System.setProperty(TlsSystemConfig.TLS_SERVER_KEYPASSWORD, config.getTlsKeyPassword());
this.tlsCertificateManager = tlsCertificateManager;
this.tlsReloadHandler = new RemotingTlsReloadHandler();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,15 @@
import io.grpc.netty.shaded.io.netty.buffer.ByteBuf;
import io.grpc.netty.shaded.io.netty.buffer.Unpooled;
import io.grpc.netty.shaded.io.netty.handler.codec.haproxy.HAProxyTLV;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import org.apache.rocketmq.proxy.config.ConfigurationManager;
import org.apache.rocketmq.proxy.config.ProxyConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -39,11 +46,57 @@ public void setUp() throws Exception {
negotiator = new ProxyAndTlsProtocolNegotiator();
}

@After
public void tearDown() {
ProxyConfig proxyConfig = ConfigurationManager.getProxyConfig();
proxyConfig.setTlsTestModeEnable(true);
proxyConfig.setTlsKeyPath("");
proxyConfig.setTlsCertPath("");
proxyConfig.setTlsKeyPassword("");
}

@Test
public void handleHAProxyTLV() {
ByteBuf content = Unpooled.buffer();
content.writeBytes("xxxx".getBytes(StandardCharsets.UTF_8));
HAProxyTLV haProxyTLV = new HAProxyTLV((byte) 0xE1, content);
negotiator.handleHAProxyTLV(haProxyTLV, Attributes.newBuilder());
}
}

@Test
public void testLoadSslContextWithUnencryptedKey() throws Exception {
configureTls("server.key", "server.pem", "");
ProxyAndTlsProtocolNegotiator.loadSslContext();
}

@Test
public void testLoadSslContextWithEncryptedKey() throws Exception {
// "1234" is the password of certs/client.key, inherited from remoting module test resources
configureTls("client.key", "client.pem", "1234");
ProxyAndTlsProtocolNegotiator.loadSslContext();
}

@Test(expected = IllegalArgumentException.class)
public void testLoadSslContextWithWrongPassword() throws Exception {
configureTls("client.key", "client.pem", "wrong_password");
ProxyAndTlsProtocolNegotiator.loadSslContext();
}

private void configureTls(String keyFile, String certFile, String password) throws IOException {
ProxyConfig proxyConfig = ConfigurationManager.getProxyConfig();
proxyConfig.setTlsTestModeEnable(false);
proxyConfig.setTlsKeyPath(getCertsPath(keyFile));
proxyConfig.setTlsCertPath(getCertsPath(certFile));
proxyConfig.setTlsKeyPassword(password);
}

private static String getCertsPath(String fileName) throws IOException {
File tempFile = File.createTempFile(fileName, null);
tempFile.deleteOnExit();
try (InputStream is = ProxyAndTlsProtocolNegotiatorTest.class
.getClassLoader().getResourceAsStream("certs/" + fileName)) {
Files.copy(is, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
return tempFile.getAbsolutePath();
}
}
17 changes: 17 additions & 0 deletions proxy/src/test/resources/certs/client.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICoTAbBgkqhkiG9w0BBQMwDgQI1vtPpDhOYRcCAggABIICgMHwgw0p9fx95R/+
cWnNdEq8I3ZOOy2wDjammFvPrYXcCJzS3Xg/0GDJ8pdJRKrI7253e4u3mxf5oMuY
RrvpB3KfdelU1k/5QKqOxL/N0gQafQLViN53f6JelyBEAmO1UxQtKZtkTrdZg8ZP
0u1cPPWxmgNdn1Xx3taMw+Wo05ysHjnHJhOEDQ2WT3VXigiRmFSX3H567yjYMRD+
zmvBq+qqR9JPbH9Cn7X1oRXX6c8VsZHWF/Ds0I4i+5zJxsSIuNZxjZw9XXNgXtFv
7FEFC0HDgDQQUY/FNPUbmjQUp1y0YxoOBjlyIqBIx5FWxu95p2xITS0OimQPFT0o
IngaSb+EKRDhqpLxxIVEbDdkQrdRqcmmLGJioAysExTBDsDwkaEJGOp44bLDM4QW
SIA9SB01omuCXgn7RjUyVXb5g0Lz+Nvsfp1YXUkPDO9hILfz3eMHDSW7/FzbB81M
r8URaTagQxBZnvIoCoWszLDXn3JwEjpZEA6y55Naptps3mMRf7+XMt42lX0e4y9a
ogNu5Zw/RZD9YcaTjC2z5XeKiMCs1Ymhy9iuzbo+eRGESqzvUE4VirtsiEwxJRci
JHAvuAl3X4XnpTty4ahOU+DihM9lALxdU68CN9++7mx581pYuvjzrV+Z5+PuptZX
AjCZmkZLDh8TCHSzWRqvP/Hcvo9BjW8l1Lq6tOa222PefSNCc6gs6Hq+jUghbabZ
/ux4WuFc0Zd6bfQWAZohSvd78/ixsdJPNGm2OP+LUIrEDKIkLuH1PM0uq4wzJZNu
Bo7oJ5iFWF67u3MC8oq+BqOVKDNWaCMi7iiSrN2XW8FBo/rpx4Lf/VYREL+Y0mP6
vzJrZqw=
-----END ENCRYPTED PRIVATE KEY-----
19 changes: 19 additions & 0 deletions proxy/src/test/resources/certs/client.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDATCCAekCAQIwDQYJKoZIhvcNAQEFBQAwfDELMAkGA1UEBhMCemgxCzAJBgNV
BAgMAnpqMQswCQYDVQQHDAJoejEPMA0GA1UECgwGYXBhY2hlMREwDwYDVQQLDAhy
b2NrZXRtcTEOMAwGA1UEAwwFeXVrb24xHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFw
YWNoZS5vcmcwIBcNMTgwMTE2MDYxNjQ0WhgPMjExNzEyMjMwNjE2NDRaMIGSMQsw
CQYDVQQGEwJDTjERMA8GA1UECAwIWmhlamlhbmcxETAPBgNVBAcMCEhhbmd6aG91
MQ8wDQYDVQQKDAZhcGFjaGUxETAPBgNVBAsMCHJvY2tldG1xMRgwFgYDVQQDDA9h
cGFjaGUgcm9ja2V0bXExHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFwYWNoZS5vcmcw
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOjPlSjZk37XLBJBc5G/qQNsNdVD
vZnEGntrqW0UuHjF2T/LPtsGOavLP5wCHvn2zwMR2eCXZwKdKIzSvk0L3XOjH/XY
OLgRa3cg90lV7Wzn9UMGq3nOjFtjIODPjtz3lwYAuAt1MH+K0E+ChuCFBgFqdY9U
E0suW3DX0Mt/WB3pAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFGPaZKyCZzQihKj
n/7I1J0wKl1HrU7N4sOie8E+ntcpKeX9zKYAou/4Iy0qwgxgRsnucB1rDous560a
+8DFDU8+FnikK9cQtKfQqu4F266IkkXolviZMSfkmB+NIsByIl95eMJlQHVlAvnX
vnpGdhD/Jhs+acE1VHhO6K+8omKLA6Og8MmYGRwmnBLcxIvqoSNDlEShfQyjaECg
I4bEi4ZhH3lSHE46FybJdoxDbj9IjHWqpOnjM23EOyfd1zcwOZJA7a54kfOpiTjz
wrtes5yoQznun5WtGcLM8ZmyaQ+Jr3j6NyZhOwULzK1+A8YUsW6Ww39xTxQoIHEQ
7eirb54=
-----END CERTIFICATE-----
16 changes: 16 additions & 0 deletions proxy/src/test/resources/certs/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOsmp4YtrIRsBdBQ
LyPImafCRynTJls3NNF4g6nZr9e0efBY830gw9kBebcm603sdZNl95fzRr2+srXi
5FJbG7Fmq1+F0xLNK/kKWirGtNMT2DubmhVdKyXYJSvInoGRkrQzbOG0MdAyzE6Q
O6OjjNN+xGkmadWyCyNF6S8YqMJTAgMBAAECgYEAj0OlnOIG0Ube4+N2VN7KfqKm
qJy0Ka6gx14dGUY/E7Qo9n27GujzaSq09RkJExiVKZBeIH1fBAtC5f2uDV7kpy0l
uNpTpQkbw0g2EQLxDsVwaUEYbu+t9qVeXoDd1vFeoXHBuRwvI9UW1BrxVtvKODia
5StU8Lw4yjcm2lQalwECQQD/sKj56thIsIY7D9qBHk7fnFLd8aYzhnP2GsbZX4V/
T1KHRxr/8MqdNQX53DE5qcyM/Mqu95FIpTAniUtvcBujAkEA62+fAMYFTAEWj4Z4
vCmcoPqfVPWhBKFR/wo3L8uUARiIzlbYNU3LIqC2s16QO50+bLUd41oVHNw9Y+uM
fxQpkQJACg/WpncSadHghmR6UchyjCQnsqo2wyJQX+fv2VAD/d2OPtqSem3sW0Fh
6dI7cax36zhrdXUyl2xAt92URV9hBwJALX93sdWSxnpbWsc449wCydVFH00MnfFz
AB+ARLtJ0eBk58M+qyZqgDmgtQ8sPmkH3EgwC3SoKdiiAIJPt2s1EQJBAKnISZZr
qB2F2PfAW2JJbQlrPyVzkxhv9XYdiVNOErmuxLFae3AI7nECgGuFBtvmeqzm2yRj
7RBMCmzyWG7MF3o=
-----END PRIVATE KEY-----
19 changes: 19 additions & 0 deletions proxy/src/test/resources/certs/server.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDATCCAekCAQIwDQYJKoZIhvcNAQEFBQAwfDELMAkGA1UEBhMCemgxCzAJBgNV
BAgMAnpqMQswCQYDVQQHDAJoejEPMA0GA1UECgwGYXBhY2hlMREwDwYDVQQLDAhy
b2NrZXRtcTEOMAwGA1UEAwwFeXVrb24xHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFw
YWNoZS5vcmcwIBcNMTgwMTE2MDYxMzQ5WhgPMjExNzEyMjMwNjEzNDlaMIGSMQsw
CQYDVQQGEwJDTjERMA8GA1UECAwIWmhlamlhbmcxETAPBgNVBAcMCEhhbmd6aG91
MQ8wDQYDVQQKDAZhcGFjaGUxETAPBgNVBAsMCHJvY2tldG1xMRgwFgYDVQQDDA9h
cGFjaGUgcm9ja2V0bXExHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFwYWNoZS5vcmcw
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOsmp4YtrIRsBdBQLyPImafCRynT
Jls3NNF4g6nZr9e0efBY830gw9kBebcm603sdZNl95fzRr2+srXi5FJbG7Fmq1+F
0xLNK/kKWirGtNMT2DubmhVdKyXYJSvInoGRkrQzbOG0MdAyzE6QO6OjjNN+xGkm
adWyCyNF6S8YqMJTAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAAzbwXyAULmXitiU
+8/2vbUZQlzB/nXY52OIq7qu3F55hE5qlHkcVxG2JZjO3p5UETwOyNUpU4dpu3uT
7WSdygH4Iagl87ILpGsob9pAf0joAbaXAY4sGDhg+WjR5JInAxbmT+QWZ+4NTuLQ
fSudUSJrv+HmUlmcVOvLiNStgt9rbtcgJAvpVwY+iCv0HQziFuQxmOkDv09ZLzu/
lxCMqnbgkEFYkwdntN6MVk38K3MovszedGO/n19hNOFss7nn5XDEeEnc6BqKGdck
YDoy6amohY0Ds0o0gJ2rq0Y8Gjl9spQ3oeXpoNUoz84OF4KIBRTzSMv8CrmqPdFY
Zd2MGjw=
-----END CERTIFICATE-----
Loading