mirror of https://github.com/tp4a/teleport
改进:TP核心服务每60秒向已连接的客户端和远程主机发送keep-alive消息,防止连接中断。但仍保留无操作超时就断开的限制。
parent
7b46c3bc63
commit
e7635e7756
|
@ -6,7 +6,8 @@ SshProxy g_ssh_proxy;
|
||||||
SshProxy::SshProxy() :
|
SshProxy::SshProxy() :
|
||||||
ExThreadBase("ssh-proxy-thread"),
|
ExThreadBase("ssh-proxy-thread"),
|
||||||
m_bind(NULL) {
|
m_bind(NULL) {
|
||||||
m_timer_counter = 0;
|
m_timer_counter_check_noop = 0;
|
||||||
|
m_timer_counter_send_keep_alive= 0;
|
||||||
m_noop_timeout_sec = 900; // default to 15 minutes.
|
m_noop_timeout_sec = 900; // default to 15 minutes.
|
||||||
m_listener_running = false;
|
m_listener_running = false;
|
||||||
}
|
}
|
||||||
|
@ -59,21 +60,33 @@ bool SshProxy::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SshProxy::timer() {
|
void SshProxy::timer() {
|
||||||
// timer() will be called per one second, and I will do my job per 5 seconds.
|
// timer() will be called per one second
|
||||||
m_timer_counter++;
|
m_timer_counter_check_noop++;
|
||||||
if (m_timer_counter < 5)
|
m_timer_counter_send_keep_alive++;
|
||||||
return;
|
|
||||||
|
|
||||||
m_timer_counter = 0;
|
// check no-op per 5 seconds.
|
||||||
|
if (m_timer_counter_check_noop >= 5) {
|
||||||
|
m_timer_counter_check_noop = 0;
|
||||||
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
ex_u32 t_now = (ex_u32) time(NULL);
|
ex_u32 t_now = (ex_u32)time(NULL);
|
||||||
|
|
||||||
ts_ssh_sessions::iterator it;
|
ts_ssh_sessions::iterator it;
|
||||||
for (it = m_sessions.begin(); it != m_sessions.end(); ++it) {
|
for (it = m_sessions.begin(); it != m_sessions.end(); ++it) {
|
||||||
it->first->save_record();
|
it->first->save_record();
|
||||||
if (0 != m_noop_timeout_sec)
|
if (0 != m_noop_timeout_sec)
|
||||||
it->first->check_noop_timeout(t_now, m_noop_timeout_sec);
|
it->first->check_noop_timeout(t_now, m_noop_timeout_sec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send keep-alive every 60 seconds
|
||||||
|
if (m_timer_counter_send_keep_alive >= 60) {
|
||||||
|
m_timer_counter_send_keep_alive = 0;
|
||||||
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
ts_ssh_sessions::iterator it;
|
||||||
|
for (it = m_sessions.begin(); it != m_sessions.end(); ++it) {
|
||||||
|
it->first->send_keep_alive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ssh_bind m_bind;
|
ssh_bind m_bind;
|
||||||
int m_timer_counter;
|
int m_timer_counter_check_noop;
|
||||||
|
int m_timer_counter_send_keep_alive;
|
||||||
|
|
||||||
ExThreadLock m_lock;
|
ExThreadLock m_lock;
|
||||||
bool m_listener_running;
|
bool m_listener_running;
|
||||||
|
|
|
@ -399,7 +399,7 @@ void SshSession::save_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SshSession::check_noop_timeout(ex_u32 t_now, ex_u32 timeout) {
|
void SshSession::check_noop_timeout(ex_u32 t_now, ex_u32 timeout) {
|
||||||
ExThreadSmartLock locker(m_lock);
|
// ExThreadSmartLock locker(m_lock);
|
||||||
tp_channels::iterator it = m_channels.begin();
|
tp_channels::iterator it = m_channels.begin();
|
||||||
for (; it != m_channels.end(); ++it) {
|
for (; it != m_channels.end(); ++it) {
|
||||||
if ((*it)->need_close)
|
if ((*it)->need_close)
|
||||||
|
@ -415,6 +415,15 @@ void SshSession::check_noop_timeout(ex_u32 t_now, ex_u32 timeout) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SshSession::send_keep_alive() {
|
||||||
|
EXLOGD("[ssh] send keep-alive.\n");
|
||||||
|
if(m_srv_session)
|
||||||
|
ssh_send_keepalive(m_srv_session);
|
||||||
|
if (m_cli_session)
|
||||||
|
ssh_send_keepalive(m_cli_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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) {
|
||||||
// here, `user` is the session-id we need.
|
// here, `user` is the session-id we need.
|
||||||
SshSession *_this = (SshSession *) userdata;
|
SshSession *_this = (SshSession *) userdata;
|
||||||
|
|
|
@ -1,156 +1,157 @@
|
||||||
#ifndef __SSH_SESSION_H__
|
#ifndef __SSH_SESSION_H__
|
||||||
#define __SSH_SESSION_H__
|
#define __SSH_SESSION_H__
|
||||||
|
|
||||||
#include "ssh_recorder.h"
|
#include "ssh_recorder.h"
|
||||||
|
|
||||||
#include <ex.h>
|
#include <ex.h>
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <libssh/server.h>
|
#include <libssh/server.h>
|
||||||
#include <libssh/callbacks.h>
|
#include <libssh/callbacks.h>
|
||||||
#include <libssh/sftp.h>
|
#include <libssh/sftp.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#define TS_SSH_CHANNEL_TYPE_UNKNOWN 0
|
#define TS_SSH_CHANNEL_TYPE_UNKNOWN 0
|
||||||
#define TS_SSH_CHANNEL_TYPE_SHELL 1
|
#define TS_SSH_CHANNEL_TYPE_SHELL 1
|
||||||
#define TS_SSH_CHANNEL_TYPE_SFTP 2
|
#define TS_SSH_CHANNEL_TYPE_SFTP 2
|
||||||
|
|
||||||
#define TP_SSH_CLIENT_SIDE 1
|
#define TP_SSH_CLIENT_SIDE 1
|
||||||
#define TP_SSH_SERVER_SIDE 2
|
#define TP_SSH_SERVER_SIDE 2
|
||||||
|
|
||||||
class SshProxy;
|
class SshProxy;
|
||||||
class SshSession;
|
class SshSession;
|
||||||
|
|
||||||
class TP_SSH_CHANNEL_PAIR {
|
class TP_SSH_CHANNEL_PAIR {
|
||||||
|
|
||||||
friend class SshSession;
|
friend class SshSession;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TP_SSH_CHANNEL_PAIR();
|
TP_SSH_CHANNEL_PAIR();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int type; // TS_SSH_CHANNEL_TYPE_SHELL or TS_SSH_CHANNEL_TYPE_SFTP
|
int type; // TS_SSH_CHANNEL_TYPE_SHELL or TS_SSH_CHANNEL_TYPE_SFTP
|
||||||
|
|
||||||
ssh_channel cli_channel;
|
ssh_channel cli_channel;
|
||||||
ssh_channel srv_channel;
|
ssh_channel srv_channel;
|
||||||
|
|
||||||
TppSshRec rec;
|
TppSshRec rec;
|
||||||
ex_u32 last_access_timestamp;
|
ex_u32 last_access_timestamp;
|
||||||
|
|
||||||
int state;
|
int state;
|
||||||
int db_id;
|
int db_id;
|
||||||
int channel_id; // for debug only.
|
int channel_id; // for debug only.
|
||||||
|
|
||||||
int win_width; // window width, in char count.
|
int win_width; // window width, in char count.
|
||||||
|
|
||||||
bool is_first_server_data;
|
bool is_first_server_data;
|
||||||
bool need_close;
|
bool need_close;
|
||||||
|
|
||||||
// for ssh command record cache.
|
// for ssh command record cache.
|
||||||
bool server_ready;
|
bool server_ready;
|
||||||
bool maybe_cmd;
|
bool maybe_cmd;
|
||||||
bool process_srv;
|
bool process_srv;
|
||||||
bool client_single_char;
|
bool client_single_char;
|
||||||
std::list<char> cmd_char_list;
|
std::list<char> cmd_char_list;
|
||||||
std::list<char>::iterator cmd_char_pos;
|
std::list<char>::iterator cmd_char_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<TP_SSH_CHANNEL_PAIR*> tp_channels;
|
typedef std::list<TP_SSH_CHANNEL_PAIR*> tp_channels;
|
||||||
|
|
||||||
class SshSession : public ExThreadBase
|
class SshSession : public ExThreadBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SshSession(SshProxy* proxy, ssh_session sess_client);
|
SshSession(SshProxy* proxy, ssh_session sess_client);
|
||||||
virtual ~SshSession();
|
virtual ~SshSession();
|
||||||
|
|
||||||
SshProxy* get_proxy(void) { return m_proxy; }
|
SshProxy* get_proxy(void) { return m_proxy; }
|
||||||
|
|
||||||
TP_SSH_CHANNEL_PAIR* _get_channel_pair(int channel_side, ssh_channel channel);
|
TP_SSH_CHANNEL_PAIR* _get_channel_pair(int channel_side, ssh_channel channel);
|
||||||
|
|
||||||
void client_ip(const char* ip) { m_client_ip = ip; }
|
void client_ip(const char* ip) { m_client_ip = ip; }
|
||||||
const char* client_ip(void) const { return m_client_ip.c_str(); }
|
const char* client_ip(void) const { return m_client_ip.c_str(); }
|
||||||
void client_port(ex_u16 port) { m_client_port = port; }
|
void client_port(ex_u16 port) { m_client_port = port; }
|
||||||
ex_u16 client_port(void) const { return m_client_port; }
|
ex_u16 client_port(void) const { return m_client_port; }
|
||||||
|
|
||||||
// save record cache into file. be called per 5 seconds.
|
// save record cache into file. be called per 5 seconds.
|
||||||
void save_record();
|
void save_record();
|
||||||
//
|
//
|
||||||
void check_noop_timeout(ex_u32 t_now, ex_u32 timeout);
|
void check_noop_timeout(ex_u32 t_now, ex_u32 timeout);
|
||||||
|
void send_keep_alive();
|
||||||
const ex_astr& sid() { return m_sid; }
|
|
||||||
|
const ex_astr& sid() { return m_sid; }
|
||||||
protected:
|
|
||||||
void _thread_loop();
|
protected:
|
||||||
void _on_stop();
|
void _thread_loop();
|
||||||
void _on_stopped();
|
void _on_stop();
|
||||||
|
void _on_stopped();
|
||||||
// record an error when session connecting or auth-ing.
|
|
||||||
void _session_error(int err_code);
|
// record an error when session connecting or auth-ing.
|
||||||
// when client<->server channel created, start to record.
|
void _session_error(int err_code);
|
||||||
bool _record_begin(TP_SSH_CHANNEL_PAIR* cp);
|
// when client<->server channel created, start to record.
|
||||||
// stop record because channel closed.
|
bool _record_begin(TP_SSH_CHANNEL_PAIR* cp);
|
||||||
void _record_end(TP_SSH_CHANNEL_PAIR* cp);
|
// stop record because channel closed.
|
||||||
|
void _record_end(TP_SSH_CHANNEL_PAIR* cp);
|
||||||
void _process_ssh_command(TP_SSH_CHANNEL_PAIR* cp, int from, const ex_u8* data, int len);
|
|
||||||
void _process_sftp_command(TP_SSH_CHANNEL_PAIR* cp, const ex_u8* data, int len);
|
void _process_ssh_command(TP_SSH_CHANNEL_PAIR* cp, int from, const ex_u8* data, int len);
|
||||||
|
void _process_sftp_command(TP_SSH_CHANNEL_PAIR* cp, const ex_u8* data, int len);
|
||||||
private:
|
|
||||||
void _run(void);
|
private:
|
||||||
|
void _run(void);
|
||||||
void _close_channels(void);
|
|
||||||
void _check_channels(void);
|
void _close_channels(void);
|
||||||
|
void _check_channels(void);
|
||||||
static int _on_auth_password_request(ssh_session session, const char *user, const char *password, void *userdata);
|
|
||||||
static ssh_channel _on_new_channel_request(ssh_session session, void *userdata);
|
static int _on_auth_password_request(ssh_session session, const char *user, const char *password, void *userdata);
|
||||||
static int _on_client_pty_request(ssh_session session, ssh_channel channel, const char *term, int x, int y, int px, int py, void *userdata);
|
static ssh_channel _on_new_channel_request(ssh_session session, void *userdata);
|
||||||
static int _on_client_shell_request(ssh_session session, ssh_channel channel, void *userdata);
|
static int _on_client_pty_request(ssh_session session, ssh_channel channel, const char *term, int x, int y, int px, int py, void *userdata);
|
||||||
static void _on_client_channel_close(ssh_session session, ssh_channel channel, void* userdata);
|
static int _on_client_shell_request(ssh_session session, ssh_channel channel, void *userdata);
|
||||||
static int _on_client_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
|
static void _on_client_channel_close(ssh_session session, ssh_channel channel, void* userdata);
|
||||||
static int _on_client_pty_win_change(ssh_session session, ssh_channel channel, int width, int height, int pxwidth, int pwheight, void *userdata);
|
static int _on_client_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
|
||||||
|
static int _on_client_pty_win_change(ssh_session session, ssh_channel channel, int width, int height, int pxwidth, int pwheight, void *userdata);
|
||||||
static int _on_client_channel_subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata);
|
|
||||||
static int _on_client_channel_exec_request(ssh_session session, ssh_channel channel, const char *command, void *userdata);
|
static int _on_client_channel_subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata);
|
||||||
|
static int _on_client_channel_exec_request(ssh_session session, ssh_channel channel, const char *command, void *userdata);
|
||||||
static int _on_server_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
|
|
||||||
static void _on_server_channel_close(ssh_session session, ssh_channel channel, void* userdata);
|
static int _on_server_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
|
||||||
|
static void _on_server_channel_close(ssh_session session, ssh_channel channel, void* userdata);
|
||||||
private:
|
|
||||||
SshProxy* m_proxy;
|
private:
|
||||||
ssh_session m_cli_session;
|
SshProxy* m_proxy;
|
||||||
ssh_session m_srv_session;
|
ssh_session m_cli_session;
|
||||||
|
ssh_session m_srv_session;
|
||||||
ExThreadLock m_lock;
|
|
||||||
|
ExThreadLock m_lock;
|
||||||
ex_astr m_client_ip;
|
|
||||||
ex_u16 m_client_port;
|
ex_astr m_client_ip;
|
||||||
|
ex_u16 m_client_port;
|
||||||
TPP_CONNECT_INFO* m_conn_info;
|
|
||||||
|
TPP_CONNECT_INFO* m_conn_info;
|
||||||
ex_astr m_sid;
|
|
||||||
ex_astr m_conn_ip;
|
ex_astr m_sid;
|
||||||
ex_u16 m_conn_port;
|
ex_astr m_conn_ip;
|
||||||
ex_astr m_acc_name;
|
ex_u16 m_conn_port;
|
||||||
ex_astr m_acc_secret;
|
ex_astr m_acc_name;
|
||||||
ex_u32 m_flags;
|
ex_astr m_acc_secret;
|
||||||
int m_auth_type;
|
ex_u32 m_flags;
|
||||||
|
int m_auth_type;
|
||||||
bool m_is_logon;
|
|
||||||
|
bool m_is_logon;
|
||||||
int m_ssh_ver;
|
|
||||||
|
int m_ssh_ver;
|
||||||
// 一个ssh_session中可以打开多个ssh_channel
|
|
||||||
tp_channels m_channels;
|
// 一个ssh_session中可以打开多个ssh_channel
|
||||||
|
tp_channels m_channels;
|
||||||
bool m_have_error;
|
|
||||||
|
bool m_have_error;
|
||||||
bool m_recving_from_srv; // 是否正在从服务器接收数据?
|
|
||||||
bool m_recving_from_cli; // 是否正在从客户端接收数据?
|
bool m_recving_from_srv; // 是否正在从服务器接收数据?
|
||||||
|
bool m_recving_from_cli; // 是否正在从客户端接收数据?
|
||||||
struct ssh_server_callbacks_struct m_srv_cb;
|
|
||||||
struct ssh_channel_callbacks_struct m_cli_channel_cb;
|
struct ssh_server_callbacks_struct m_srv_cb;
|
||||||
struct ssh_channel_callbacks_struct m_srv_channel_cb;
|
struct ssh_channel_callbacks_struct m_cli_channel_cb;
|
||||||
};
|
struct ssh_channel_callbacks_struct m_srv_channel_cb;
|
||||||
|
};
|
||||||
#endif // __SSH_SESSION_H__
|
|
||||||
|
#endif // __SSH_SESSION_H__
|
||||||
|
|
Loading…
Reference in New Issue