Skip to content

Commit 306baf6

Browse files
committed
更新 README 文档,添加 MySQL TLS 代理服务的功能特性、系统要求和快速开始指南。重构 ProxyService,简化连接池初始化逻辑,增强连接管理。修复 ConnectionContext 中 clientId 类型,添加认证状态和数据库信息管理。更新配置文件以支持后端 MySQL 连接和代理账号配置。移除不再使用的 ConnectionPool 类。
1 parent 1cce341 commit 306baf6

19 files changed

Lines changed: 2913 additions & 1637 deletions

.codebuddy/rules/common.mdc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ provider:
2121

2222
## 文件组织
2323
- 每个功能模块保持单一职责
24-
- main入口文件, 其他文件放src去
2524
- 工具代码放/app/Helpers文件夹,文件名后缀要helper
2625
- 配置文件放到/config文件夹
2726
- 测试文件放/test

.cursor/rules/common.mdc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ provider:
2121

2222
## 文件组织
2323
- 每个功能模块保持单一职责
24-
- main入口文件, 其他文件放src去
2524
- 工具代码放/app/Helpers文件夹,文件名后缀要helper
2625
- 配置文件放到/config文件夹
2726
- 测试文件放/test

README.md

Lines changed: 142 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,169 @@
1-
# Introduction
1+
# MySQL TLS 代理服务
22

3-
This is a skeleton application using the Hyperf framework. This application is meant to be used as a starting place for those looking to get their feet wet with Hyperf Framework.
3+
这是一个基于 Hyperf 框架的 MySQL 协议代理服务,支持 TLS/SSL 连接和代理层认证。客户端使用代理内配置的账号连接代理,代理使用写死的后端 MySQL 账号执行 SQL 并返回结果。
44

5-
# Requirements
5+
## 功能特性
66

7-
Hyperf has some requirements for the system environment, it can only run under Linux and Mac environment, but due to the development of Docker virtualization technology, Docker for Windows can also be used as the running environment under Windows.
7+
-**TLS/SSL 支持**: 支持客户端通过 `sslmode=require``sslmode=verify-*` 连接
8+
-**代理认证**: 客户端使用代理配置的账号进行认证,不直接使用后端 MySQL 账号
9+
-**统一后端账号**: 所有 SQL 都通过配置的固定 MySQL 账号执行
10+
-**连接池**: 自动管理后端 MySQL 连接池,提高性能
11+
-**SQL 日志**: 完整的 SQL 执行日志记录
12+
-**协议兼容**: 支持基本的 MySQL 协议,包括查询、预处理语句等
813

9-
The various versions of Dockerfile have been prepared for you in the [hyperf/hyperf-docker](https://github.com/hyperf/hyperf-docker) project, or directly based on the already built [hyperf/hyperf](https://hub.docker.com/r/hyperf/hyperf) Image to run.
14+
## 系统要求
1015

11-
When you don't want to use Docker as the basis for your running environment, you need to make sure that your operating environment meets the following requirements:
16+
- **PHP**: >= 8.1
17+
- **Swoole**: >= 5.0,支持 SSL (编译时需开启 `--enable-openssl`)
18+
- **扩展**: pdo_mysql, pcntl, json, openssl
19+
- **环境**: Linux/Mac/Windows (Docker)
1220

13-
- PHP >= 8.1
14-
- Any of the following network engines
15-
- Swoole PHP extension >= 5.0,with `swoole.use_shortname` set to `Off` in your `php.ini`
16-
- Swow PHP extension >= 1.3
17-
- JSON PHP extension
18-
- Pcntl PHP extension
19-
- OpenSSL PHP extension (If you need to use the HTTPS)
20-
- PDO PHP extension (If you need to use the MySQL Client)
21-
- Redis PHP extension (If you need to use the Redis Client)
22-
- Protobuf PHP extension (If you need to use the gRPC Server or Client)
21+
## 快速开始
2322

24-
# Installation using Composer
23+
### 1. 环境检查
2524

26-
The easiest way to create a new Hyperf project is to use [Composer](https://getcomposer.org/). If you don't have it already installed, then please install as per [the documentation](https://getcomposer.org/download/).
25+
```bash
26+
# 检查 Swoole SSL 支持和其他环境要求
27+
php test/check_swoole_ssl.php
28+
```
2729

28-
To create your new Hyperf project:
30+
### 2. 配置 SSL 证书
2931

3032
```bash
31-
composer create-project hyperf/hyperf-skeleton path/to/install
33+
# 创建证书目录
34+
mkdir -p runtime/certs
35+
36+
# 生成自签名证书(生产环境请使用正式证书)
37+
openssl req -x509 -newkey rsa:4096 -keyout runtime/certs/server.key -out runtime/certs/server.crt -days 365 -nodes -subj '/CN=localhost'
38+
```
39+
40+
### 3. 配置代理账号和后端 MySQL
41+
42+
编辑 `config/autoload/proxy.php`
43+
44+
```php
45+
'proxy_accounts' => [
46+
[
47+
'username' => 'proxy_user',
48+
'password' => 'proxy_pass',
49+
'database' => '', // 空表示不限制数据库
50+
],
51+
],
52+
53+
'backend_mysql' => [
54+
'host' => 'mysql57',
55+
'port' => 3306,
56+
'username' => 'root',
57+
'password' => 'root',
58+
'database' => '',
59+
],
3260
```
3361

34-
If your development environment is based on Docker you can use the official Composer image to create a new Hyperf project:
62+
63+
### 5. 测试连接
3564

3665
```bash
37-
docker run --rm -it -v $(pwd):/app composer create-project --ignore-platform-reqs hyperf/hyperf-skeleton path/to/install
66+
# 测试 SSL 连接和代理认证
67+
php test/ssl_test.php
68+
69+
# 或使用 mysql 客户端
70+
mysql --ssl-mode=REQUIRED -h 127.0.0.1 -P 3317 -u proxy_user -p proxy_pass
3871
```
3972

40-
# Getting started
73+
## 配置说明
74+
75+
### 代理账号配置
76+
77+
`config/autoload/proxy.php` 中配置允许连接代理的账号:
78+
79+
```php
80+
'proxy_accounts' => [
81+
[
82+
'username' => 'app_user',
83+
'password' => 'secure_password',
84+
'database' => 'app_db', // 可选,限制可访问的数据库
85+
],
86+
[
87+
'username' => 'admin',
88+
'password' => 'admin_pass',
89+
'database' => '', // 空字符串表示可访问任何数据库
90+
],
91+
],
92+
```
4193

42-
Once installed, you can run the server immediately using the command below.
94+
### 后端 MySQL 配置
4395

44-
```bash
45-
cd path/to/install
46-
php bin/hyperf.php start
96+
配置代理用于连接真实 MySQL 的账号:
97+
98+
```php
99+
'backend_mysql' => [
100+
'host' => 'mysql-server',
101+
'port' => 3306,
102+
'username' => 'service_account',
103+
'password' => 'service_password',
104+
'database' => '', // 默认数据库,可为空
105+
'charset' => 'utf8mb4',
106+
'tls' => false, // 是否对后端使用 TLS
107+
],
47108
```
48109

49-
Or if in a Docker based environment you can use the `docker-compose.yml` provided by the template:
110+
### SSL/TLS 配置
50111

51-
```bash
52-
cd path/to/install
53-
docker-compose up
112+
```php
113+
'tls' => [
114+
'server_cert' => BASE_PATH . '/runtime/certs/server.crt',
115+
'server_key' => BASE_PATH . '/runtime/certs/server.key',
116+
'ca_cert' => null, // 用于客户端证书验证
117+
'require_client_cert' => false,
118+
],
119+
```
120+
121+
## 架构说明
122+
123+
```
124+
客户端 (mysql --ssl-mode=REQUIRED)
125+
↓ TLS 连接
126+
MySQL 代理 (端口 3317)
127+
├── 代理认证 (验证 proxy_accounts)
128+
├── SQL 执行 (使用 backend_mysql 账号)
129+
└── 结果返回 (MySQL 协议)
130+
131+
真实 MySQL 服务器
54132
```
55133

56-
This will start the cli-server on port `9501`, and bind it to all network interfaces. You can then visit the site at `http://localhost:9501/` which will bring up Hyperf default home page.
134+
## 故障排除
135+
136+
### 连接失败
137+
138+
1. **检查服务状态**:
139+
```bash
140+
php bin/hyperf.php status
141+
```
142+
143+
2. **查看日志**:
144+
```bash
145+
tail -f runtime/logs/hyperf.log
146+
tail -f runtime/logs/connection.log
147+
```
148+
149+
3. **测试证书**:
150+
```bash
151+
openssl s_client -connect 127.0.0.1:3317 -servername localhost
152+
```
153+
154+
### 常见问题
57155

58-
## Hints
156+
- **SSL 连接失败**: 检查证书文件是否存在且可读
157+
- **认证失败**: 确认代理账号配置正确
158+
- **后端连接失败**: 检查后端 MySQL 服务器可访问性
159+
- **连接池耗尽**: 调整 `pool.size` 配置
59160

60-
- A nice tip is to rename `hyperf-skeleton` of files like `composer.json` and `docker-compose.yml` to your actual project name.
61-
- Take a look at `config/routes.php` and `app/Controller/IndexController.php` to see an example of a HTTP entrypoint.
161+
## 开发说明
62162

63-
**Remember:** you can always replace the contents of this README.md file to something that fits your project description.
163+
项目结构:
164+
- `App/Proxy/Protocol/` - MySQL 协议处理
165+
- `App/Proxy/Auth/` - 代理认证逻辑
166+
- `App/Proxy/Executor/` - 后端执行器
167+
- `App/Proxy/Pool/` - 连接池管理
168+
- `config/autoload/proxy.php` - 代理配置
169+
- `test/` - 测试脚本

app/Listener/ApplicationLifecycleListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function process(object $event): void
6464
// 初始化连接池
6565
try {
6666
$proxyService = $this->container->get(ProxyService::class);
67-
$proxyService->initializeConnectionPool();
67+
$proxyService->initialize();
6868

6969
$this->logger->info('连接池初始化完成', [
7070
'event' => 'BeforeWorkerStart',

app/Protocol/ConnectionContext.php

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class ConnectionContext
1111
{
12-
private string $clientId;
12+
private int $clientId;
1313
private string $clientIp;
1414
private int $clientPort;
1515
private ?Socket $mysqlSocket = null;
@@ -21,15 +21,25 @@ class ConnectionContext
2121
private bool $tlsEnabled = false;
2222
private ?string $clientTlsPeerCN = null;
2323
private ?Lock $socketLock = null;
24+
private bool $authenticated = false;
25+
private ?string $username = null;
26+
private ?string $database = null;
27+
private bool $sslRequested = false;
28+
private string $authPluginData = '';
2429

25-
public function __construct(string $clientId, string $clientIp, int $clientPort)
30+
public function __construct(int $clientId, string $clientIp, int $clientPort)
2631
{
2732
$this->clientId = $clientId;
2833
$this->clientIp = $clientIp;
2934
$this->clientPort = $clientPort;
3035
}
3136

3237
public function getClientId(): string
38+
{
39+
return (string) $this->clientId;
40+
}
41+
42+
public function getThreadId(): int
3343
{
3444
return $this->clientId;
3545
}
@@ -139,6 +149,56 @@ public function setClientTlsPeerCN(?string $clientTlsPeerCN): void
139149
$this->clientTlsPeerCN = $clientTlsPeerCN;
140150
}
141151

152+
public function isAuthenticated(): bool
153+
{
154+
return $this->authenticated;
155+
}
156+
157+
public function setAuthenticated(bool $authenticated): void
158+
{
159+
$this->authenticated = $authenticated;
160+
}
161+
162+
public function getUsername(): ?string
163+
{
164+
return $this->username;
165+
}
166+
167+
public function setUsername(?string $username): void
168+
{
169+
$this->username = $username;
170+
}
171+
172+
public function getDatabase(): ?string
173+
{
174+
return $this->database;
175+
}
176+
177+
public function setDatabase(?string $database): void
178+
{
179+
$this->database = $database;
180+
}
181+
182+
public function isSslRequested(): bool
183+
{
184+
return $this->sslRequested;
185+
}
186+
187+
public function setSslRequested(bool $sslRequested): void
188+
{
189+
$this->sslRequested = $sslRequested;
190+
}
191+
192+
public function getAuthPluginData(): string
193+
{
194+
return $this->authPluginData;
195+
}
196+
197+
public function setAuthPluginData(string $authPluginData): void
198+
{
199+
$this->authPluginData = $authPluginData;
200+
}
201+
142202
public function __toString(): string
143203
{
144204
return sprintf('%s:%d', $this->clientIp, $this->clientPort);

0 commit comments

Comments
 (0)