修正了无法远程连接SSHv1.99的交换机的问题。

pull/111/head
Apex Liu 2018-09-22 00:51:56 +08:00
parent 0437cb16d3
commit e326b3ac48
13 changed files with 156 additions and 124 deletions

View File

@ -1,3 +1,3 @@
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
VER_TP_SERVER = "3.0.3.12" VER_TP_SERVER = "3.0.4.16"
VER_TP_ASSIST = "3.0.1.6" VER_TP_ASSIST = "3.0.1.6"

View File

@ -51,6 +51,7 @@
#define TP_SESS_STAT_ERR_RESET 7 // 会话结束因为teleport核心服务重置了 #define TP_SESS_STAT_ERR_RESET 7 // 会话结束因为teleport核心服务重置了
#define TP_SESS_STAT_ERR_IO 8 // 会话结束,因为网络中断 #define TP_SESS_STAT_ERR_IO 8 // 会话结束,因为网络中断
#define TP_SESS_STAT_ERR_SESSION 9 // 会话结束因为无效的会话ID #define TP_SESS_STAT_ERR_SESSION 9 // 会话结束因为无效的会话ID
#define TP_SESS_STAT_ERR_AUTH_TYPE 10 // 会话结束,因为不被允许的认证方式
#define TP_SESS_STAT_STARTED 100 // 已经连接成功了,开始记录录像了 #define TP_SESS_STAT_STARTED 100 // 已经连接成功了,开始记录录像了
#define TP_SESS_STAT_ERR_START_INTERNAL 104 // 会话结束,因为内部错误 #define TP_SESS_STAT_ERR_START_INTERNAL 104 // 会话结束,因为内部错误
#define TP_SESS_STAT_ERR_START_BAD_PKG 106 // 会话结束,因为收到错误的报文 #define TP_SESS_STAT_ERR_START_BAD_PKG 106 // 会话结束,因为收到错误的报文

Binary file not shown.

View File

@ -1,6 +1,6 @@
#ifndef __TS_SERVER_VER_H__ #ifndef __TS_SERVER_VER_H__
#define __TS_SERVER_VER_H__ #define __TS_SERVER_VER_H__
#define TP_SERVER_VER L"3.0.3.12" #define TP_SERVER_VER L"3.0.4.16"
#endif // __TS_SERVER_VER_H__ #endif // __TS_SERVER_VER_H__

View File

@ -422,7 +422,7 @@ void SshSession::check_noop_timeout(ex_u32 t_now, ex_u32 timeout) {
} }
int SshSession::_on_auth_password_request(ssh_session session, const char *user, const char *password, void *userdata) { int SshSession::_on_auth_password_request(ssh_session session, const char *user, const char *password, void *userdata) {
// 这里拿到的user就是我们要的session-id。 // here, `user` is the session-id we need.
SshSession *_this = (SshSession *)userdata; SshSession *_this = (SshSession *)userdata;
_this->m_sid = user; _this->m_sid = user;
EXLOGV("[ssh] authenticating, session-id: %s\n", _this->m_sid.c_str()); EXLOGV("[ssh] authenticating, session-id: %s\n", _this->m_sid.c_str());
@ -441,6 +441,7 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
_this->m_auth_type = _this->m_conn_info->auth_type; _this->m_auth_type = _this->m_conn_info->auth_type;
_this->m_acc_name = _this->m_conn_info->acc_username; _this->m_acc_name = _this->m_conn_info->acc_username;
_this->m_acc_secret = _this->m_conn_info->acc_secret; _this->m_acc_secret = _this->m_conn_info->acc_secret;
_this->m_flags = _this->m_conn_info->protocol_flag;
if (_this->m_conn_info->protocol_type != TP_PROTOCOL_TYPE_SSH) { if (_this->m_conn_info->protocol_type != TP_PROTOCOL_TYPE_SSH) {
EXLOGE("[ssh] session '%s' is not for SSH.\n", _this->m_sid.c_str()); EXLOGE("[ssh] session '%s' is not for SSH.\n", _this->m_sid.c_str());
_this->m_have_error = true; _this->m_have_error = true;
@ -449,21 +450,18 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
} }
} }
// 现在尝试根据session-id获取得到的信息连接并登录真正的SSH服务器 // config and try to connect to real SSH host.
EXLOGV("[ssh] try to connect to real SSH server %s:%d\n", _this->m_conn_ip.c_str(), _this->m_conn_port); EXLOGV("[ssh] try to connect to real SSH server %s:%d\n", _this->m_conn_ip.c_str(), _this->m_conn_port);
_this->m_srv_session = ssh_new(); _this->m_srv_session = ssh_new();
// int verbosity = 4;
// ssh_options_set(_this->m_srv_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
//ssh_set_blocking(_this->m_srv_session, 1);
ssh_options_set(_this->m_srv_session, SSH_OPTIONS_HOST, _this->m_conn_ip.c_str()); ssh_options_set(_this->m_srv_session, SSH_OPTIONS_HOST, _this->m_conn_ip.c_str());
int port = (int)_this->m_conn_port; int port = (int)_this->m_conn_port;
ssh_options_set(_this->m_srv_session, SSH_OPTIONS_PORT, &port); ssh_options_set(_this->m_srv_session, SSH_OPTIONS_PORT, &port);
#ifdef EX_DEBUG #ifdef EX_DEBUG
// int flag = SSH_LOG_FUNCTIONS; // int flag = SSH_LOG_FUNCTIONS;
// ssh_options_set(_this->m_srv_session, SSH_OPTIONS_LOG_VERBOSITY, &flag); // ssh_options_set(_this->m_srv_session, SSH_OPTIONS_LOG_VERBOSITY, &flag);
#endif #endif
// int val = 0; int val = 0;
// ssh_options_set(_this->m_srv_session, SSH_OPTIONS_STRICTHOSTKEYCHECK, &val); ssh_options_set(_this->m_srv_session, SSH_OPTIONS_STRICTHOSTKEYCHECK, &val);
if (_this->m_auth_type != TP_AUTH_TYPE_NONE) if (_this->m_auth_type != TP_AUTH_TYPE_NONE)
@ -490,49 +488,49 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
_this->m_ssh_ver = ssh_get_version(_this->m_srv_session); _this->m_ssh_ver = ssh_get_version(_this->m_srv_session);
EXLOGW("[ssh] real host is SSHv%d\n", _this->m_ssh_ver); EXLOGW("[ssh] real host is SSHv%d\n", _this->m_ssh_ver);
#if 0
// check supported auth type by host // check supported auth type by host
//ssh_userauth_none(_this->m_srv_session, _this->m_acc_name.c_str()); ssh_userauth_none(_this->m_srv_session, _this->m_acc_name.c_str());
// rc = ssh_userauth_none(_this->m_srv_session, NULL); rc = ssh_userauth_none(_this->m_srv_session, NULL);
// if (rc == SSH_AUTH_ERROR) { if (rc == SSH_AUTH_ERROR) {
// EXLOGE("[ssh] can not got auth type supported by real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port); EXLOGE("[ssh] can not got auth type supported by real SSH server %s:%d.\n", _this->m_conn_ip.c_str(), _this->m_conn_port);
// _this->m_have_error = true; _this->m_have_error = true;
// _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED; _this->_session_error(TP_SESS_STAT_ERR_SESSION);
// return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
// } }
// // int auth_methods = ssh_userauth_list(_this->m_srv_session, NULL);
// const char* banner = ssh_get_issue_banner(_this->m_srv_session);
// if (NULL != banner) {
// EXLOGE("[ssh] issue banner: %s\n", banner);
// }
int auth_methods = ssh_userauth_list(_this->m_srv_session, _this->m_acc_name.c_str());
const char* banner = ssh_get_issue_banner(_this->m_srv_session);
if (NULL != banner) {
EXLOGE("[ssh] issue banner: %s\n", banner);
}
#endif
int auth_methods = SSH_AUTH_METHOD_INTERACTIVE | SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY;
if (SSH_AUTH_ERROR != ssh_userauth_none(_this->m_srv_session, NULL))
{
auth_methods = ssh_userauth_list(_this->m_srv_session, NULL);
EXLOGV("[ssh] allowed auth method: 0x%08x\n", auth_methods);
}
else
{
EXLOGW("[ssh] can not get allowed auth method, try each method we can.\n");
}
if (_this->m_auth_type == TP_AUTH_TYPE_PASSWORD) { if (_this->m_auth_type == TP_AUTH_TYPE_PASSWORD) {
if (!(((auth_methods & SSH_AUTH_METHOD_INTERACTIVE) == SSH_AUTH_METHOD_INTERACTIVE) || ((auth_methods & SSH_AUTH_METHOD_PASSWORD) == SSH_AUTH_METHOD_PASSWORD)))
{
_this->_session_error(TP_SESS_STAT_ERR_AUTH_TYPE);
return SSH_AUTH_ERROR;
}
int retry_count = 0; int retry_count = 0;
if (_this->m_ssh_ver == 1) { // first try interactive login mode if server allow.
// first try password for SSHv1 if ((auth_methods & SSH_AUTH_METHOD_INTERACTIVE) == SSH_AUTH_METHOD_INTERACTIVE)
rc = ssh_userauth_password(_this->m_srv_session, _this->m_acc_name.c_str(), _this->m_acc_secret.c_str()); {
for (;;) {
if (rc == SSH_AUTH_AGAIN) {
retry_count += 1;
if (retry_count >= 3)
break;
ex_sleep_ms(100);
rc = ssh_userauth_password(_this->m_srv_session, _this->m_acc_name.c_str(), _this->m_acc_secret.c_str());
continue;
}
if (rc == SSH_AUTH_SUCCESS) {
EXLOGW("[ssh] logon with password mode.\n");
_this->m_is_logon = true;
return SSH_AUTH_SUCCESS;
}
else {
EXLOGW("[ssh] failed to login with password mode, got %d.\n", rc);
}
}
}
// first try interactive login mode for SSHv2.
retry_count = 0; retry_count = 0;
rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL); rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL);
for (;;) { for (;;) {
@ -570,26 +568,31 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL); rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL);
} }
if (rc == SSH_AUTH_SUCCESS) {
EXLOGW("[ssh] logon with keyboard interactive mode.\n");
_this->m_is_logon = true;
return SSH_AUTH_SUCCESS;
}
else {
EXLOGW("[ssh] failed to login with keyboard interactive mode, got %d, try password mode.\n", rc);
} }
if (_this->m_ssh_ver != 1) { // and then try password login mode if server allow.
// then try password mode if interactive mode does not supported by host with SSHv2. if ((auth_methods & SSH_AUTH_METHOD_PASSWORD) == SSH_AUTH_METHOD_PASSWORD)
rc = ssh_userauth_password(_this->m_srv_session, _this->m_acc_name.c_str(), _this->m_acc_secret.c_str()); {
retry_count = 0;
rc = ssh_userauth_password(_this->m_srv_session, NULL, _this->m_acc_secret.c_str());
for (;;) {
if (rc == SSH_AUTH_AGAIN) {
retry_count += 1;
if (retry_count >= 3)
break;
ex_sleep_ms(100);
rc = ssh_userauth_password(_this->m_srv_session, NULL, _this->m_acc_secret.c_str());
continue;
}
if (rc == SSH_AUTH_SUCCESS) { if (rc == SSH_AUTH_SUCCESS) {
EXLOGW("[ssh] logon with password mode.\n"); EXLOGW("[ssh] logon with password mode.\n");
_this->m_is_logon = true; _this->m_is_logon = true;
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
} }
else { else {
EXLOGW("[ssh] failed to login with password mode, got %d.\n", rc); EXLOGE("[ssh] failed to login with password mode, got %d.\n", rc);
break;
}
} }
} }
@ -599,6 +602,12 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
else if (_this->m_auth_type == TP_AUTH_TYPE_PRIVATE_KEY) { else if (_this->m_auth_type == TP_AUTH_TYPE_PRIVATE_KEY) {
if ((auth_methods & SSH_AUTH_METHOD_PUBLICKEY) != SSH_AUTH_METHOD_PUBLICKEY) {
_this->m_have_error = true;
_this->_session_error(TP_SESS_STAT_ERR_AUTH_TYPE);
return SSH_AUTH_ERROR;
}
ssh_key key = NULL; ssh_key key = NULL;
if (SSH_OK != ssh_pki_import_privkey_base64(_this->m_acc_secret.c_str(), NULL, NULL, NULL, &key)) { if (SSH_OK != ssh_pki_import_privkey_base64(_this->m_acc_secret.c_str(), NULL, NULL, NULL, &key)) {
EXLOGE("[ssh] can not import private-key for auth.\n"); EXLOGE("[ssh] can not import private-key for auth.\n");
@ -615,13 +624,12 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
_this->m_is_logon = true; _this->m_is_logon = true;
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
} }
else {
EXLOGE("[ssh] failed to use private-key to login to real SSH server %s:%d.\n", _this->m_conn_ip.c_str(), _this->m_conn_port); EXLOGE("[ssh] failed to use private-key to login to real SSH server %s:%d.\n", _this->m_conn_ip.c_str(), _this->m_conn_port);
_this->m_have_error = true; _this->m_have_error = true;
_this->_session_error(TP_SESS_STAT_ERR_AUTH_DENIED); _this->_session_error(TP_SESS_STAT_ERR_AUTH_DENIED);
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
}
else if (_this->m_auth_type == TP_AUTH_TYPE_NONE) { else if (_this->m_auth_type == TP_AUTH_TYPE_NONE) {
_this->_session_error(TP_SESS_STAT_ERR_AUTH_DENIED); _this->_session_error(TP_SESS_STAT_ERR_AUTH_DENIED);
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
@ -736,6 +744,11 @@ int SshSession::_on_client_shell_request(ssh_session session, ssh_channel channe
SshSession *_this = (SshSession *)userdata; SshSession *_this = (SshSession *)userdata;
EXLOGD("[ssh] client request shell\n"); EXLOGD("[ssh] client request shell\n");
if ((_this->m_flags & TP_FLAG_SSH_SHELL) != TP_FLAG_SSH_SHELL)
{
EXLOGE("[ssh] ssh-shell disabled by ops-policy.\n");
return SSH_ERROR;
}
TP_SSH_CHANNEL_PAIR* cp = _this->_get_channel_pair(TP_SSH_CLIENT_SIDE, channel); TP_SSH_CHANNEL_PAIR* cp = _this->_get_channel_pair(TP_SSH_CLIENT_SIDE, channel);
if (NULL == cp) { if (NULL == cp) {
@ -761,7 +774,7 @@ int SshSession::_on_client_shell_request(ssh_session session, ssh_channel channe
} }
void SshSession::_on_client_channel_close(ssh_session session, ssh_channel channel, void *userdata) { void SshSession::_on_client_channel_close(ssh_session session, ssh_channel channel, void *userdata) {
EXLOGV("---client channel closed.\n"); EXLOGV("[ssh] ---client channel closed.\n");
SshSession *_this = (SshSession *)userdata; SshSession *_this = (SshSession *)userdata;
TP_SSH_CHANNEL_PAIR* cp = _this->_get_channel_pair(TP_SSH_CLIENT_SIDE, channel); TP_SSH_CHANNEL_PAIR* cp = _this->_get_channel_pair(TP_SSH_CLIENT_SIDE, channel);
@ -896,6 +909,13 @@ int SshSession::_on_client_channel_subsystem_request(ssh_session session, ssh_ch
return SSH_ERROR; return SSH_ERROR;
} }
if ((_this->m_flags & TP_FLAG_SSH_SFTP) != TP_FLAG_SSH_SFTP)
{
EXLOGE("[ssh] ssh-sftp disabled by ops-policy.\n");
return SSH_ERROR;
}
cp->type = TS_SSH_CHANNEL_TYPE_SFTP; cp->type = TS_SSH_CHANNEL_TYPE_SFTP;
g_ssh_env.session_update(cp->db_id, TP_PROTOCOL_TYPE_SSH_SFTP, TP_SESS_STAT_STARTED); g_ssh_env.session_update(cp->db_id, TP_PROTOCOL_TYPE_SSH_SFTP, TP_SESS_STAT_STARTED);
@ -1099,7 +1119,7 @@ int SshSession::_on_server_channel_data(ssh_session session, ssh_channel channel
} }
void SshSession::_on_server_channel_close(ssh_session session, ssh_channel channel, void *userdata) { void SshSession::_on_server_channel_close(ssh_session session, ssh_channel channel, void *userdata) {
EXLOGV("---server channel closed.\n"); EXLOGV("[ssh] ---server channel closed.\n");
SshSession *_this = (SshSession *)userdata; SshSession *_this = (SshSession *)userdata;
TP_SSH_CHANNEL_PAIR* cp = _this->_get_channel_pair(TP_SSH_SERVER_SIDE, channel); TP_SSH_CHANNEL_PAIR* cp = _this->_get_channel_pair(TP_SSH_SERVER_SIDE, channel);
if (NULL == cp) { if (NULL == cp) {

View File

@ -132,6 +132,7 @@ private:
ex_u16 m_conn_port; ex_u16 m_conn_port;
ex_astr m_acc_name; ex_astr m_acc_name;
ex_astr m_acc_secret; ex_astr m_acc_secret;
ex_u32 m_flags;
int m_auth_type; int m_auth_type;
bool m_is_logon; bool m_is_logon;

View File

@ -109,6 +109,7 @@
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_types.h" /> <ClInclude Include="..\..\..\..\common\libex\include\ex\ex_types.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_util.h" /> <ClInclude Include="..\..\..\..\common\libex\include\ex\ex_util.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_winsrv.h" /> <ClInclude Include="..\..\..\..\common\libex\include\ex\ex_winsrv.h" />
<ClInclude Include="..\..\..\..\common\teleport\teleport_const.h" />
<ClInclude Include="..\..\..\..\external\jsoncpp\include\json\json.h" /> <ClInclude Include="..\..\..\..\external\jsoncpp\include\json\json.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\callbacks.h" /> <ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\callbacks.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\libssh.h" /> <ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\libssh.h" />

View File

@ -113,6 +113,9 @@
<ClInclude Include="..\..\..\..\external\jsoncpp\include\json\json.h"> <ClInclude Include="..\..\..\..\external\jsoncpp\include\json\json.h">
<Filter>jsoncpp</Filter> <Filter>jsoncpp</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\..\common\teleport\teleport_const.h">
<Filter>common</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="tpssh.cpp"> <ClCompile Include="tpssh.cpp">

View File

@ -859,7 +859,6 @@ $app.create_dlg_edit_host = function () {
cid: dlg.field_cid, cid: dlg.field_cid,
desc: dlg.field_desc desc: dlg.field_desc
}; };
console.log(args);
// 如果id为-1表示创建否则表示更新 // 如果id为-1表示创建否则表示更新
$tp.ajax_post_json('/asset/update-host', args, $tp.ajax_post_json('/asset/update-host', args,
@ -1148,7 +1147,6 @@ $app.create_dlg_accounts = function () {
$tp.ajax_post_json('/asset/get-accounts', {host_id: dlg.host.id}, $tp.ajax_post_json('/asset/get-accounts', {host_id: dlg.host.id},
function (ret) { function (ret) {
if (ret.code === TPE_OK) { if (ret.code === TPE_OK) {
console.log('account:', ret.data);
$app.table_acc.set_data(cb_stack, {}, {total: ret.data.length, page_index: 1, data: ret.data}); $app.table_acc.set_data(cb_stack, {}, {total: ret.data.length, page_index: 1, data: ret.data});
} else { } else {
$app.table_acc.set_data(cb_stack, {}, {total: 0, page_index: 1, data: {}}); $app.table_acc.set_data(cb_stack, {}, {total: 0, page_index: 1, data: {}});
@ -1519,6 +1517,10 @@ $app.create_dlg_edit_account = function () {
} }
dlg.dom.auth_type.empty().append($(html.join(''))); dlg.dom.auth_type.empty().append($(html.join('')));
if(!_.isNull(dlg.account))
dlg.dom.auth_type.val(dlg.account.auth_type);
dlg.on_auth_change(); dlg.on_auth_change();
}; };

View File

@ -328,6 +328,9 @@ $app.on_table_host_render_created = function (render) {
case TP_SESS_STAT_ERR_SESSION: case TP_SESS_STAT_ERR_SESSION:
msg = '无效会话'; msg = '无效会话';
break; break;
case TP_SESS_STAT_ERR_AUTH_TYPE:
msg = '无效认证方式';
break;
default: default:
msg = '未知状态 [' + fields.state + ']'; msg = '未知状态 [' + fields.state + ']';
} }

View File

@ -49,6 +49,7 @@ var TP_SESS_STAT_ERR_BAD_PKG = 6; // 会话结束,因为收到错误的报文
var TP_SESS_STAT_ERR_RESET = 7; // 会话结束因为teleport核心服务重置了 var TP_SESS_STAT_ERR_RESET = 7; // 会话结束因为teleport核心服务重置了
var TP_SESS_STAT_ERR_IO = 8; // 会话结束,因为网络中断 var TP_SESS_STAT_ERR_IO = 8; // 会话结束,因为网络中断
var TP_SESS_STAT_ERR_SESSION = 9; // 会话结束因为无效的会话ID var TP_SESS_STAT_ERR_SESSION = 9; // 会话结束因为无效的会话ID
var TP_SESS_STAT_ERR_AUTH_TYPE = 10; // // 会话结束,因为服务端不支持此认证方式
var TP_SESS_STAT_STARTED = 100; // 已经连接成功了,开始记录录像了 var TP_SESS_STAT_STARTED = 100; // 已经连接成功了,开始记录录像了
var TP_SESS_STAT_ERR_START_INTERNAL = 104; // 会话结束,因为内部错误 var TP_SESS_STAT_ERR_START_INTERNAL = 104; // 会话结束,因为内部错误
var TP_SESS_STAT_ERR_START_BAD_PKG = 106; // 会话结束,因为收到错误的报文 var TP_SESS_STAT_ERR_START_BAD_PKG = 106; // 会话结束,因为收到错误的报文

View File

@ -1,2 +1,2 @@
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
TP_SERVER_VER = "3.0.3.12" TP_SERVER_VER = "3.0.4.16"

View File

@ -13,7 +13,7 @@ Revision 修订号。主版本号和次版本号都相同但修订号不同
Build 构建号。构建号用于表明此版本发布之前进行了多少次构建及测试。某些情况下此版本号可以省略。 Build 构建号。构建号用于表明此版本发布之前进行了多少次构建及测试。某些情况下此版本号可以省略。
TP_SERVER 3.0.3.12 # 整个服务端打包的版本 TP_SERVER 3.0.4.16 # 整个服务端打包的版本
TP_TPCORE 3.0.3.12 # 核心服务 tp_core 的版本 TP_TPCORE 3.0.4.16 # 核心服务 tp_core 的版本
TP_TPWEB 3.0.0.1 # web服务 tp_web 的版本一般除非升级Python否则不会变化 TP_TPWEB 3.0.0.1 # web服务 tp_web 的版本一般除非升级Python否则不会变化
TP_ASSIST 3.0.1.6 # 助手版本 TP_ASSIST 3.0.1.6 # 助手版本