From aee95b2cbaa73e21f0e2179c94a4ccdc7fb64424 Mon Sep 17 00:00:00 2001 From: Apex Liu Date: Wed, 19 May 2021 01:02:22 +0800 Subject: [PATCH] [ssh] fix not works with pub-key auth mode. [web] support alive check with PING. --- CMakeLists.txt | 8 +- client/tp-player/tp-player.pro | 1 + server/tp_core/protocol/ssh/ssh_session.cpp | 78 +++++++++++-------- .../www/teleport/static/js/asset/host-list.js | 35 ++++++--- .../www/teleport/webroot/app/base/configs.py | 9 +++ .../teleport/webroot/app/base/host_alive.py | 15 ++++ .../www/teleport/webroot/app/base/webapp.py | 12 ++- .../teleport/webroot/app/controller/host.py | 19 +++-- 8 files changed, 118 insertions(+), 59 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b42d06..09ec489 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,11 +3,9 @@ project(teleport) include(CMakeCfg.txt) -#if (OS_LINUX) -# add_subdirectory(server/tp_web/src) -#endif() - -add_subdirectory(server/tp_web/src) +if (OS_LINUX) + add_subdirectory(server/tp_web/src) +endif() add_subdirectory(server/tp_core/core) add_subdirectory(server/tp_core/protocol/ssh) diff --git a/client/tp-player/tp-player.pro b/client/tp-player/tp-player.pro index b300c8f..f91e01d 100644 --- a/client/tp-player/tp-player.pro +++ b/client/tp-player/tp-player.pro @@ -54,6 +54,7 @@ else:win32:CONFIG(debug, debug|release): { macx: { + CONFIG+=sdk_no_version_check INCLUDEPATH += $$PWD/../../external/macos/release/include } macx:CONFIG(release, debug|release): { diff --git a/server/tp_core/protocol/ssh/ssh_session.cpp b/server/tp_core/protocol/ssh/ssh_session.cpp index 5489a31..71f7f2c 100644 --- a/server/tp_core/protocol/ssh/ssh_session.cpp +++ b/server/tp_core/protocol/ssh/ssh_session.cpp @@ -548,11 +548,11 @@ int SshSession::_do_auth(const char* user, const char* secret) if (!m_conn_info) { - EXLOGE("[%s] no such session id: %s\n", m_dbg_name.c_str(), m_sid.c_str()); _set_last_error(TP_SESS_STAT_ERR_SESSION); m_auth_err_msg = "invalid session id: '"; m_auth_err_msg += m_sid; m_auth_err_msg += "'."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } @@ -565,11 +565,11 @@ int SshSession::_do_auth(const char* user, const char* secret) if (m_conn_info->protocol_type != TP_PROTOCOL_TYPE_SSH) { - EXLOGE("[ssh] session '%s' is not for SSH.\n", m_sid.c_str()); _set_last_error(TP_SESS_STAT_ERR_INTERNAL); m_auth_err_msg = "session "; m_auth_err_msg += m_sid; m_auth_err_msg += " is not for SSH."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } @@ -577,9 +577,9 @@ int SshSession::_do_auth(const char* user, const char* secret) if ((m_acc_name.empty() && _name == "INTERACTIVE_USER") || (!m_acc_name.empty() && _name != "INTERACTIVE_USER")) { - EXLOGE("[%s] conflict account info.\n", m_dbg_name.c_str()); _set_last_error(TP_SESS_STAT_ERR_SESSION); m_auth_err_msg = "account name of remote host should not be 'INTERACTIVE_USER'."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } @@ -640,13 +640,13 @@ int SshSession::_do_auth(const char* user, const char* secret) int rc = ssh_connect(m_rs_tp2srv); if (rc != SSH_OK) { - EXLOGE("[%s] can not connect to real SSH server %s. %s\n", m_dbg_name.c_str(), m_dbg_server.c_str(), ssh_get_error(m_rs_tp2srv)); _set_last_error(TP_SESS_STAT_ERR_CONNECT); m_auth_err_msg = "can not connect to remote host "; m_auth_err_msg += m_dbg_server; m_auth_err_msg += ", "; m_auth_err_msg += ssh_get_error(m_rs_tp2srv); m_auth_err_msg += "."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } @@ -693,11 +693,11 @@ int SshSession::_do_auth(const char* user, const char* secret) { if (!(((auth_methods & SSH_AUTH_METHOD_INTERACTIVE) == SSH_AUTH_METHOD_INTERACTIVE) || ((auth_methods & SSH_AUTH_METHOD_PASSWORD) == SSH_AUTH_METHOD_PASSWORD))) { - EXLOGE("[%s] configure to auth by password, but remote host not allow such auth mode.\n", m_dbg_name.c_str()); _set_last_error(TP_SESS_STAT_ERR_AUTH_TYPE); m_auth_err_msg = "both password and interactive authorize methods are not allowed by remote host "; m_auth_err_msg += m_dbg_server; m_auth_err_msg += "."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } @@ -734,6 +734,7 @@ int SshSession::_do_auth(const char* user, const char* secret) m_auth_err_msg += m_dbg_server; m_auth_err_msg += " with interactive authorize method failed, "; m_auth_err_msg += ssh_get_error(m_rs_tp2srv); + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); break; } @@ -760,7 +761,6 @@ int SshSession::_do_auth(const char* user, const char* secret) rc = ssh_userauth_kbdint_setanswer(m_rs_tp2srv, i, m_acc_secret.c_str()); if (rc < 0) { - EXLOGE("[%s] invalid password for interactive mode to login to remote host %s.\n", m_dbg_name.c_str(), m_dbg_server.c_str()); _set_last_error(TP_SESS_STAT_ERR_AUTH_DENIED); if (!m_auth_err_msg.empty()) @@ -770,9 +770,7 @@ int SshSession::_do_auth(const char* user, const char* secret) m_auth_err_msg += " with interactive authorize method failed, "; m_auth_err_msg += ssh_get_error(m_rs_tp2srv); - // m_auth_err_msg = "failed to login remote host "; - // m_auth_err_msg += m_dbg_server; - // m_auth_err_msg += " with interactive authorize method, access denied."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } @@ -819,77 +817,93 @@ int SshSession::_do_auth(const char* user, const char* secret) } } - EXLOGE("[%s] auth failed, mode=password/interactive, remote-host=%s.\n", m_dbg_name.c_str(), m_dbg_server.c_str()); _set_last_error(TP_SESS_STAT_ERR_AUTH_DENIED); - // if(!m_auth_err_msg.empty()) - // m_auth_err_msg += "\r\n"; - // m_auth_err_msg += "login remote host "; - // m_auth_err_msg += m_dbg_server; - // m_auth_err_msg += " failed, "; - // m_auth_err_msg += ssh_get_error(m_rs_tp2srv); - m_auth_err_msg += "failed to login remote host "; m_auth_err_msg += m_dbg_server; m_auth_err_msg += " with interactive and password authorize methods, access denied."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } else if (m_auth_type == TP_AUTH_TYPE_PRIVATE_KEY) { if ((auth_methods & SSH_AUTH_METHOD_PUBLICKEY) != SSH_AUTH_METHOD_PUBLICKEY) { - EXLOGE("[%s] configure to use public-key auth, but remote host not allow such auth mode.\n", m_dbg_name.c_str()); _set_last_error(TP_SESS_STAT_ERR_AUTH_TYPE); m_auth_err_msg = "public-key-authorize method is not allowed by remote host "; m_auth_err_msg += m_dbg_server; m_auth_err_msg += "."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } ssh_key key = nullptr; if (SSH_OK != ssh_pki_import_privkey_base64(m_acc_secret.c_str(), nullptr, nullptr, nullptr, &key)) { - EXLOGE("[%s] can not import private-key for auth.\n", m_dbg_name.c_str()); _set_last_error(TP_SESS_STAT_ERR_BAD_SSH_KEY); m_auth_err_msg = "can not load private key for login remote host "; m_auth_err_msg += m_dbg_server; - m_auth_err_msg += "."; + m_auth_err_msg += ", "; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } + int retry_count = 0; rc = ssh_userauth_publickey(m_rs_tp2srv, nullptr, key); + for (;;) + { + if (rc == SSH_AUTH_SUCCESS) + { + EXLOGW("[%s] login with public-key mode succeeded.\n", m_dbg_name.c_str()); + m_auth_passed = true; + ssh_key_free(key); + return SSH_AUTH_SUCCESS; + } + else if (rc == SSH_AUTH_AGAIN) + { + retry_count += 1; + if (retry_count >= 5) + break; + ex_sleep_ms(100); + rc = ssh_userauth_publickey(m_rs_tp2srv, nullptr, key); + continue; + } + + EXLOGE("[%s] failed to login with password mode, got %d.\n", m_dbg_name.c_str(), rc); + + break; + } + ssh_key_free(key); - if (rc == SSH_AUTH_SUCCESS) - { - EXLOGW("[%s] login with public-key mode succeeded.\n", m_dbg_name.c_str()); - m_auth_passed = true; - return SSH_AUTH_SUCCESS; - } - - EXLOGE("[%s] auth failed, mode=public-key, remote-host=%s.\n", m_dbg_name.c_str(), m_dbg_server.c_str()); _set_last_error(TP_SESS_STAT_ERR_AUTH_DENIED); - m_auth_err_msg = "failed to login remote host "; + + if (!m_auth_err_msg.empty()) + m_auth_err_msg += "\r\n"; + m_auth_err_msg += "login remote host "; m_auth_err_msg += m_dbg_server; - m_auth_err_msg += " with public-key authorize method, access denied."; + m_auth_err_msg += " with public-key authorize method failed. "; + m_auth_err_msg += ssh_get_error(m_rs_tp2srv); + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); + return SSH_AUTH_SUCCESS; } else if (m_auth_type == TP_AUTH_TYPE_NONE) { - EXLOGE("[%s] configure to login without auth, not allowed.\n", m_dbg_name.c_str()); _set_last_error(TP_SESS_STAT_ERR_AUTH_DENIED); m_auth_err_msg = "no authorize method for login remote host "; m_auth_err_msg += m_dbg_server; m_auth_err_msg += "."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } else { - EXLOGE("[%s] unknown auth mode: %d.\n", m_dbg_name.c_str(), m_auth_type); _set_last_error(TP_SESS_STAT_ERR_AUTH_DENIED); m_auth_err_msg = "unknown authorize method for login remote host "; m_auth_err_msg += m_dbg_server; m_auth_err_msg += "."; + EXLOGE("[%s] %s\n", m_dbg_name.c_str(), m_auth_err_msg.c_str()); return SSH_AUTH_SUCCESS; } } diff --git a/server/www/teleport/static/js/asset/host-list.js b/server/www/teleport/static/js/asset/host-list.js index 13bff2e..8416d60 100644 --- a/server/www/teleport/static/js/asset/host-list.js +++ b/server/www/teleport/static/js/asset/host-list.js @@ -85,15 +85,15 @@ $app.create_controls = function (cb_stack) { render: 'account', fields: {count: 'acc_count'} }, - { - title: "在线", - key: "_alive", - sort: false, - width: 90, - align: 'center', - render: 'host_alive', - fields: {id: 'id', alive: '_alive', alive_info: '_alive_info'} - }, + // { + // title: "在线", + // key: "_alive", + // sort: false, + // width: 90, + // align: 'center', + // render: 'host_alive', + // fields: {id: 'id', alive: '_alive', alive_info: '_alive_info'} + // }, { title: "状态", key: "state", @@ -121,6 +121,18 @@ $app.create_controls = function (cb_stack) { on_cell_created: $app.on_table_host_cell_created }; + if ($app.options._check_host_alive) { + table_host_options.columns.splice(-2, 0, { + title: "在线", + key: "_alive", + sort: false, + width: 60, + align: 'center', + render: 'host_alive', + fields: {id: 'id', alive: '_alive', alive_info: '_alive_info'} + }) + } + $app.table_host = $tp.create_table(table_host_options); cb_stack .add($app.table_host.load_data) @@ -355,7 +367,10 @@ $app.on_table_host_render_created = function (render) { render.host_alive = function (row_id, fields) { var _style, _alive; - if (fields.alive === 0) { + if (fields.alive === -1) { + _style = 'alive-unknown'; + _alive = '功能未启用'; + } else if (fields.alive === 0) { _style = 'alive-unknown'; _alive = '正在检测,请稍后刷新页面'; } else if (fields.alive === 1) { diff --git a/server/www/teleport/webroot/app/base/configs.py b/server/www/teleport/webroot/app/base/configs.py index 28d9695..ffdd665 100644 --- a/server/www/teleport/webroot/app/base/configs.py +++ b/server/www/teleport/webroot/app/base/configs.py @@ -298,6 +298,12 @@ class AppConfig(BaseAppConfig): 'DO NOT FORGET update this setting if you modified rpc::bind-port in core.ini.\n' 'core-server-rpc=http://127.0.0.1:52080/rpc' ) + # check_host_alive + self.set_default('common::check-host-alive', 0, + '0/1, default to 0.\n\n' + 'when enable, tp-web will check alive state of remote host with ICMP(ping).\n' + 'check-host-alive=0' + ) self.set_default('database::type', 'sqlite', 'database in use, should be sqlite/mysql, default to sqlite.\n' 'type=sqlite' @@ -355,6 +361,9 @@ class AppConfig(BaseAppConfig): if _tmp_str is not None: self.set_kv('common::core-server-rpc', _tmp_str) + _tmp_bool = _sec.getint('check-host-alive', False) + self.set_kv('common::check-host-alive', _tmp_bool) + _sec = cfg_parser['database'] _tmp_str = _sec.get('type', None) diff --git a/server/www/teleport/webroot/app/base/host_alive.py b/server/www/teleport/webroot/app/base/host_alive.py index 84ee00a..5ae43ab 100644 --- a/server/www/teleport/webroot/app/base/host_alive.py +++ b/server/www/teleport/webroot/app/base/host_alive.py @@ -85,6 +85,9 @@ class HostAlive(object): self._lock = threading.RLock() def init(self): + if not tp_cfg().common.check_host_alive: + return True + icmp_protocol = socket.getprotobyname('icmp') try: self._socket_ping = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp_protocol) @@ -112,11 +115,17 @@ class HostAlive(object): return True def stop(self): + if not tp_cfg().common.check_host_alive: + return + self._need_stop = True if self._thread_recv_ping_result is not None: self._thread_recv_ping_result.join() def add_host(self, host_ip, method=0, param=None, check_now=False): + if not tp_cfg().common.check_host_alive: + return True + if param is None: param = {} @@ -139,12 +148,18 @@ class HostAlive(object): log.w('Warning: check alive method not implement.\n') def remove_host(self, host_ip): + if not tp_cfg().common.check_host_alive: + return + with self._lock: if host_ip not in self._states: return del self._states[host_ip] def get_states(self, host_ip_list): + if not tp_cfg().common.check_host_alive: + return {} + with self._lock: ret = dict() time_now = int(time.time()) diff --git a/server/www/teleport/webroot/app/base/webapp.py b/server/www/teleport/webroot/app/base/webapp.py index dbdbeb8..b537045 100644 --- a/server/www/teleport/webroot/app/base/webapp.py +++ b/server/www/teleport/webroot/app/base/webapp.py @@ -129,12 +129,15 @@ class WebApp: if not tp_session().init(): log.e('can not initialize session manager.\n') return 0 + if not tp_stats().init(): log.e('can not initialize system status collector.\n') return 0 - # if not tp_host_alive().init(): - # log.e('can not initialize host state inspector.\n') - # return 0 + + if cfg.common.check_host_alive: + if not tp_host_alive().init(): + log.e('can not initialize host state inspector.\n') + return 0 settings = { # @@ -189,7 +192,8 @@ class WebApp: except: log.e('\n') - # tp_host_alive().stop() + if tp_cfg().common.check_host_alive: + tp_host_alive().stop() tp_cron().stop() return 0 diff --git a/server/www/teleport/webroot/app/controller/host.py b/server/www/teleport/webroot/app/controller/host.py index c90eae6..f1aa486 100644 --- a/server/www/teleport/webroot/app/controller/host.py +++ b/server/www/teleport/webroot/app/controller/host.py @@ -28,7 +28,8 @@ class HostListHandler(TPBaseHandler): err, groups = group.get_host_groups_for_user(self.current_user['id'], self.current_user['privilege']) param = { - 'host_groups': groups + 'host_groups': groups, + '_check_host_alive': tp_cfg().common.check_host_alive } self.render('asset/host-list.mako', page_param=json.dumps(param)) @@ -111,13 +112,15 @@ class DoGetHostsHandler(TPBaseJsonHandler): else: ip_list.append(row_data[x]['ip']) ip_list = list(set(ip_list)) - host_states = tp_host_alive().get_states(ip_list) - for x in range(len(row_data)): - if row_data[x]['router_ip'] != '': - row_data[x]['_alive_info'] = host_states[row_data[x]['router_ip']] - else: - row_data[x]['_alive_info'] = host_states[row_data[x]['ip']] - row_data[x]['_alive'] = row_data[x]['_alive_info']['state'] + + if tp_cfg().common.check_host_alive: + host_states = tp_host_alive().get_states(ip_list) + for x in range(len(row_data)): + if row_data[x]['router_ip'] != '': + row_data[x]['_alive_info'] = host_states[row_data[x]['router_ip']] + else: + row_data[x]['_alive_info'] = host_states[row_data[x]['ip']] + row_data[x]['_alive'] = row_data[x]['_alive_info']['state'] ret = dict() ret['page_index'] = page_index