How to Set Up a PHP Workerman MySQL Forward Proxy for Seamless Database Access
This guide explains how to configure and run a Workerman‑based PHP forward proxy that forwards MySQL connections, enabling smooth access to internal databases via Navicat Premium or other clients, with detailed code snippets, startup commands, and Windows usage instructions.
Overview
The forward proxy is designed to relay MySQL connections, allowing tools like Navicat Premium to connect without latency or blockage, and can also be used to reach internal databases or services.
Project repository: https://gitee.com/windthesky/forward_proxy.git
Configuration
All settings are defined in the start.php file.
<?php
/** @noinspection PhpUnused */
/** @noinspection PhpUndefinedFieldInspection */
/** @noinspection PhpObjectFieldsAreOnlyWrittenInspection */
ini_set('memory_limit', '512M');
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
// Autoload classes
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/common.php';
// Logging options
const LOG_WRITE = true;
const SHOW_LOG = true;
const TIMEOUT_CLOSE = true;
const TIME = 300; // seconds before timeout
// Buffer sizes (default 2M)
TcpConnection::$defaultMaxSendBufferSize = 2*1024*1024;
AsyncTcpConnection::$defaultMaxSendBufferSize = 2*1024*1024;
$proxy_list = [
[
'type' => 'tcp',
'host' => '127.0.0.1',
'port' => 3306,
'local_port' => 33060,
],
];
$app_list = [];
$connect_list = [];
$client_list = [];
/**
* App receives data
* @param AsyncTcpConnection $app_connection
* @param mixed $data
*/
function app_message(AsyncTcpConnection $app_connection, $data): void {
try {
write_log('app收到:开始');
$client_id = $app_connection->client_id;
global $connect_list;
write_log(['app收到:', $data]);
write_log(['app收到-client_id:', $client_id]);
$connect_list[$client_id]->send($data);
write_log('app收到-处理完:');
} catch (Throwable $e) {
write_log(['app收到:异常==》', $e->getMessage()]);
$app_connection->close();
}
}
/**
* App error handling
*/
function app_error(AsyncTcpConnection $app_connection): void {
try {
write_log('app错误:');
$client_id = $app_connection->client_id;
global $connect_list;
$connect_list[$client_id]->close();
write_log('app错误:执行完');
} catch (Throwable $e) {
write_log(['app错误:异常==》', $e->getMessage()]);
}
}
/**
* App close handling
*/
function app_close(AsyncTcpConnection $app_connection): void {
try {
write_log('app关闭:');
$client_id = $app_connection->client_id;
global $connect_list, $app_list;
$connect_list[$client_id]->close();
unset($app_list[$client_id]);
write_log('app关闭:执行完');
} catch (Throwable $e) {
write_log(['app关闭:异常==》', $e->getMessage()]);
}
}
/**
* Client connection handling
*/
function handle_connection(TcpConnection $connection): void {
try {
write_log('客户端连接:');
$connection->lastMessageTime = time();
global $app_list, $connect_list;
$client_id = 'client-' . session_create_id();
$connection->client_id = $client_id;
$connect_list[$client_id] = $connection;
$proxy_url = $connection->worker->proxy_url;
write_log(['客户端连接:开始==》', $connection->client_id]);
$app_list[$client_id] = new AsyncTcpConnection($proxy_url);
$app_list[$client_id]->client_id = $client_id;
$app_list[$client_id]->onMessage = 'app_message';
$app_list[$client_id]->onError = 'app_error';
$app_list[$client_id]->onClose = 'app_close';
$app_list[$client_id]->connect();
write_log(['客户端连接:完成==》', $connection->client_id]);
} catch (Throwable $e) {
write_log(['客户端连接:异常==》', $connection->client_id, $e->getMessage()]);
}
}
/**
* Message handling
*/
function handle_message(TcpConnection $connection, $data): void {
try {
write_log(['收到消息:', $data]);
global $app_list;
if (TIMEOUT_CLOSE && time() - $connection->lastMessageTime > TIME) {
write_log(['收到消息:超时关闭']);
$connection->close();
return;
}
$app_list[$connection->client_id]->send($data);
$connection->lastMessageTime = time();
write_log(['收到消息:完']);
} catch (Throwable $e) {
write_log(['收到消息:异常==》', $connection->client_id, $e->getMessage()]);
}
}
/**
* Error handling for client connections
*/
function handle_error(TcpConnection $connection): void {
try {
write_log(['处理错误:开始==》', $connection->client_id]);
$client_id = $connection->client_id;
global $app_list;
if (empty($app_list[$client_id])) return;
$app_list[$client_id]->close();
write_log(['处理错误:完成==》', $client_id]);
} catch (Throwable $e) {
write_log(['处理错误:异常==》', $e->getMessage()]);
}
}
/**
* Close handling for client connections
*/
function handle_close(TcpConnection $connection): void {
try {
write_log(['处理关闭:开始==》', $connection->client_id]);
$client_id = $connection->client_id;
global $app_list, $connect_list;
if (empty($app_list[$client_id])) return;
$app_list[$client_id]->close();
unset($connect_list[$client_id]);
write_log(['处理关闭:完成==》', $client_id]);
} catch (Throwable $e) {
write_log(['处理关闭:异常==》', $e->getMessage()]);
}
}
$worker = new Worker();
$worker->onWorkerStart = function () {
global $client_list, $proxy_list;
foreach ($proxy_list as $k => $v) {
$url = $v['type'] . '://0.0.0.0:' . $v['local_port'];
$proxy_url = $v['type'] . '://' . $v['host'] . ':' . $v['port'];
echo '监听地址:' . $url . PHP_EOL;
echo '代理地址:' . $proxy_url . PHP_EOL;
$client_list[$k] = new Worker($url);
$client_list[$k]->proxy_key = $k;
$client_list[$k]->proxy_info = $v;
$client_list[$k]->proxy_url = $proxy_url;
$client_list[$k]->onConnect = 'handle_connection';
$client_list[$k]->onMessage = 'handle_message';
$client_list[$k]->onError = 'handle_error';
$client_list[$k]->onClose = 'handle_close';
$client_list[$k]->listen();
}
};
Worker::runAll();Startup Commands
Run the proxy in different modes using the following commands:
Debug mode: php start.php start Daemon mode: php start.php start -d Stop: php start.php stop Restart: php start.php restart Graceful reload: php start.php reload Check status:
php start.php statusWindows Startup
On Windows, simply double‑click the batch file start_for_win.bat to launch the proxy.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
