diff --git a/acinclude.m4 b/acinclude.m4
index e9c5a5d..99be01c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -324,6 +324,48 @@ AC_DEFUN([LOCATE_SPHINX],
 ])
 AC_SUBST(SPHINX_BUILD)
 
+##################
+# Locate libssh2 #
+##################
+AC_DEFUN([LOCATE_LIBSSH2],
+[
+	AC_ARG_WITH(libssh2, [  --with-libssh2=DIR  root directory for libssh2 installation],
+	[
+		if test "$withval" != no
+		then
+			LIBSSH2_HOME="$withval"
+			if test ! -f "${LIBSSH2_HOME}/include/libssh2.h"
+			then
+				AC_MSG_ERROR([Could not find your LIBSSH2 installation in ${LIBSSH2_HOME}])
+			else
+				LIBSSH2_INCLUDE=-I${LIBSSH2_HOME}/include
+				LIBSSH2_LIB=-L${LIBSSH2_HOME}/lib
+			fi
+		fi
+	],
+	[
+		LIBSSH2_HOME=/usr/local
+		if test ! -f "${LIBSSH2_HOME}/include/libssh2.h"
+		then
+			LIBSSH2_HOME=/usr
+			if test ! -f "${LIBSSH2_HOME}/include/libssh2.h"
+			then
+				LIBSSH2_HOME=/mingw
+				if test ! -f "${LIBSSH2_HOME}/include/libssh2.h"
+				then
+					AC_MSG_ERROR([Could not find your LIBSSH2 installation. You might need to use the --with-libssh2=DIR configure option])
+				fi
+			fi
+		fi
+
+		LIBSSH2_INCLUDE=-I${LIBSSH2_HOME}/include
+		LIBSSH2_LIB=-L${LIBSSH2_HOME}/lib
+	])
+
+	CPPFLAGS="${CPPFLAGS} ${LIBSSH2_INCLUDE}"
+	LDFLAGS="${LDFLAGS} ${LIBSSH2_LIB}"
+])
+
 ########################################
 # Enable Database Designer in pgAdmin3 #
 ########################################
@@ -847,6 +889,18 @@ AC_SUBST(XSLT_CONFIG)
 AC_SUBST(pgadmin3_LDADD)
 
 #########################
+# Setup libssh2 headers #
+#########################
+AC_DEFUN([SETUP_LIBSSH2],
+[
+	if test -n "${LIBSSH2_HOME}"
+	then
+		pgadmin3_LDADD="${pgadmin3_LDADD} -L$LIBSSH2_HOME/lib -lssh2"
+	fi
+])
+AC_SUBST(pgadmin3_LDADD)
+
+#########################
 # Configuration summary #
 #########################
 AC_DEFUN([SUMMARY],
@@ -882,6 +936,9 @@ AC_DEFUN([SUMMARY],
 	echo "libxslt xslt-config binary:		$XSLT_CONFIG"
 	echo "libxslt version:			libxslt "`$XSLT_CONFIG --version`
 	echo
+	echo "libssh2 include directory:		$LIBSSH2_INCLUDE"
+	echo "libssh2 lib directory:			$LIBSSH2_LIB"
+	echo
 	if test "$HAVE_DATABASEDESIGNER" = yes
 	then
 		echo "Building Database Designer:		Yes"
diff --git a/configure.ac.in b/configure.ac.in
index e05eb0b..7add491 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -63,6 +63,9 @@ CHECK_LIBXML2
 LOCATE_LIBXSLT
 SETUP_LIBXSLT
 
+LOCATE_LIBSSH2
+SETUP_LIBSSH2
+
 LOCATE_SPHINX
 AM_CONDITIONAL([SPHINX_BUILD], [test x$SPHINX_BUILD != x])
 
diff --git a/pgadmin/dlg/dlgServer.cpp b/pgadmin/dlg/dlgServer.cpp
index 2839480..52515ca 100644
--- a/pgadmin/dlg/dlgServer.cpp
+++ b/pgadmin/dlg/dlgServer.cpp
@@ -54,6 +54,14 @@
 #define pickerSSLCrl      CTRL_FILEPICKER("pickerSSLCrl")
 #define chkSSLCompression CTRL_CHECKBOX("chkSSLCompression")
 
+#define chkSSHTunnel		 CTRL_CHECKBOX("chkSSHTunnel")
+#define txtTunnelHost		 CTRL_TEXT("txtTunnelHost")
+#define txtTunnelUsername	 CTRL_TEXT("txtTunnelUsername")
+#define radioBtnPassword	 CTRL_RADIOBUTTON("radioBtnPassword")
+#define radioBtnKeyfile      CTRL_RADIOBUTTON("radioBtnKeyfile")
+#define txtTunnelPassword	 CTRL_TEXT("txtTunnelPassword")
+#define pickerPublicKeyFile	 CTRL_FILEPICKER("pickerPublicKeyFile")
+#define pickerPrivateKeyFile CTRL_FILEPICKER("pickerPrivateKeyFile")
 
 BEGIN_EVENT_TABLE(dlgServer, dlgProperty)
 	EVT_NOTEBOOK_PAGE_CHANGED(XRCID("nbNotebook"),     dlgServer::OnPageSelect)
@@ -80,6 +88,9 @@ BEGIN_EVENT_TABLE(dlgServer, dlgProperty)
 	EVT_COMBOBOX(XRCID("cbGroup"),                     dlgProperty::OnChange)
 	EVT_CHECKBOX(XRCID("chkSSLCompression"),           dlgProperty::OnChange)
 	EVT_BUTTON(wxID_OK,                                dlgServer::OnOK)
+	EVT_CHECKBOX(XRCID("chkSSHTunnel"),                dlgServer::OnCheckSSHTunnel)
+	EVT_RADIOBUTTON(XRCID("radioBtnPassword"),         dlgServer::OnChangeAuthOption)
+	EVT_RADIOBUTTON(XRCID("radioBtnKeyfile"),          dlgServer::OnChangeAuthOption)
 END_EVENT_TABLE();
 
 
@@ -134,6 +145,10 @@ dlgServer::dlgServer(pgaFactory *f, frmMain *frame, pgServer *node)
 			groupitem = browser->GetNextChild(browser->GetRootItem(), groupcookie);
 		}
 	}
+
+	EnableSSHTunnelControls(false);
+	radioBtnPassword->SetValue(true);
+	radioBtnKeyfile->SetValue(false);
 }
 
 
@@ -197,6 +212,13 @@ void dlgServer::OnOK(wxCommandEvent &ev)
 		server->SetSSLRootCert(pickerSSLRootCert->GetPath());
 		server->SetSSLCrl(pickerSSLCrl->GetPath());
 		server->iSetSSLCompression(chkSSLCompression->GetValue());
+		server->iSetSSHTunnel(chkSSHTunnel->GetValue());
+		server->SetTunnelHost(txtTunnelHost->GetValue());
+		server->SetTunnelUserName(txtTunnelUsername->GetValue());
+		server->iSetAuthModePwd(radioBtnPassword->GetValue());
+		server->SetTunnelPassword(txtTunnelPassword->GetValue());
+		server->SetPublicKeyFile(pickerPublicKeyFile->GetPath());
+		server->SetPrivateKeyFile(pickerPrivateKeyFile->GetPath());
 		wxColour colour = colourPicker->GetColour();
 		wxString sColour = colour.GetAsString(wxC2S_HTML_SYNTAX);
 		server->iSetColour(sColour);
@@ -225,7 +247,14 @@ void dlgServer::OnOK(wxCommandEvent &ev)
 			    server->GetRestore(),
 			    server->GetSSL(),
 			    server->GetColour(),
-			    server->GetGroup());
+			    server->GetGroup(),
+			    server->GetSSHTunnel(),
+			    server->GetTunnelHost(),
+			    server->GetTunnelUserName(),
+			    server->GetAuthModePwd(),
+			    server->GetTunnelPassword(),
+			    server->GetPublicKeyFile(),
+			    server->GetPrivateKeyFile());
 			newserver->iSetDbRestriction(server->GetDbRestriction().Trim());
 			newserver->iSetServiceID(server->GetServiceID().Trim());
 			newserver->iSetDiscoveryID(server->GetDiscoveryID().Trim());
@@ -413,6 +442,23 @@ int dlgServer::Go(bool modal)
 
 		chkSSLCompression->SetValue(server->GetSSLCompression());
 
+		chkSSHTunnel->SetValue(server->GetSSHTunnel());
+		txtTunnelHost->SetValue(server->GetTunnelHost());
+		txtTunnelUsername->SetValue(server->GetTunnelUserName());
+		if (server->GetAuthModePwd())
+		{
+			radioBtnPassword->SetValue(true);
+			radioBtnKeyfile->SetValue(false);
+		}
+		else
+		{
+			radioBtnPassword->SetValue(false);
+			radioBtnKeyfile->SetValue(true);
+		}
+		txtTunnelPassword->SetValue(server->GetTunnelPassword());
+		pickerPublicKeyFile->SetPath(server->GetPublicKeyFile());
+		pickerPrivateKeyFile->SetPath(server->GetPrivateKeyFile());
+
 		stPassword->Disable();
 		txtPassword->Disable();
 		if (connection)
@@ -438,6 +484,17 @@ int dlgServer::Go(bool modal)
 			pickerSSLCrl->Disable();
 			chkSSLCompression->Disable();
 			EnableOK(false);
+			chkSSHTunnel->Enable(false);
+			EnableSSHTunnelControls(false);
+		}
+		else
+		{
+			if (server->GetSSHTunnel())
+			{
+				chkSSHTunnel->Enable(true);
+				EnableSSHTunnelControls(true);
+				EnableAuthenticationOptions();
+			}
 		}
 	}
 	else
@@ -467,13 +524,30 @@ wxString dlgServer::GetPassword()
 pgObject *dlgServer::CreateObject(pgCollection *collection)
 {
 	wxString name = GetName();
+	pgServer *obj = NULL;
 
-	pgServer *obj = new pgServer(GetName(), txtHostAddr->GetValue(), txtDescription->GetValue(),
-	                             txtService->GetValue(), cbDatabase->GetValue(),
-	                             txtUsername->GetValue(), StrToLong(txtPort->GetValue()),
-	                             chkTryConnect->GetValue() && chkStorePwd->GetValue(),
-	                             txtRolename->GetValue(), chkRestore->GetValue(), cbSSL->GetCurrentSelection(),
-	                             colourPicker->GetColourString(), cbGroup->GetValue());
+	if (chkSSHTunnel->GetValue())
+	{
+		obj = new pgServer(GetName(), txtHostAddr->GetValue(), txtDescription->GetValue(),
+		                   txtService->GetValue(), cbDatabase->GetValue(),
+		                   txtUsername->GetValue(), StrToLong(txtPort->GetValue()),
+		                   chkTryConnect->GetValue() && chkStorePwd->GetValue(),
+		                   txtRolename->GetValue(), chkRestore->GetValue(), cbSSL->GetCurrentSelection(),
+		                   colourPicker->GetColourString(), cbGroup->GetValue(),
+		                   chkSSHTunnel->GetValue(), txtTunnelHost->GetValue(), txtTunnelUsername->GetValue(),
+		                   radioBtnPassword->GetValue(),
+		                   txtTunnelPassword->GetValue(), pickerPublicKeyFile->GetPath(),
+		                   pickerPrivateKeyFile->GetPath());
+	}
+	else
+	{
+		obj = new pgServer(GetName(), txtHostAddr->GetValue(), txtDescription->GetValue(),
+		                   txtService->GetValue(), cbDatabase->GetValue(),
+		                   txtUsername->GetValue(), StrToLong(txtPort->GetValue()),
+		                   chkTryConnect->GetValue() && chkStorePwd->GetValue(),
+		                   txtRolename->GetValue(), chkRestore->GetValue(), cbSSL->GetCurrentSelection(),
+		                   colourPicker->GetColourString(), cbGroup->GetValue());
+	}
 
 	obj->iSetDbRestriction(txtDbRestriction->GetValue().Trim());
 
@@ -550,3 +624,48 @@ wxString dlgServer::GetSql()
 {
 	return wxEmptyString;
 }
+
+void dlgServer::OnCheckSSHTunnel(wxCommandEvent &ev)
+{
+	if (chkSSHTunnel->IsChecked())
+	{
+		EnableSSHTunnelControls(true);
+		EnableAuthenticationOptions();
+	}
+	else
+	{
+		EnableSSHTunnelControls(false);
+	}
+}
+
+void dlgServer::OnChangeAuthOption(wxCommandEvent &ev)
+{
+	EnableAuthenticationOptions();
+}
+
+void dlgServer::EnableSSHTunnelControls(const bool& bEnable)
+{
+	txtTunnelHost->Enable(bEnable);
+	txtTunnelUsername->Enable(bEnable);
+	pickerPublicKeyFile->Enable(bEnable);
+	pickerPrivateKeyFile->Enable(bEnable);
+	radioBtnPassword->Enable(bEnable);
+	radioBtnKeyfile->Enable(bEnable);
+	txtTunnelPassword->Enable(bEnable);
+}
+
+void dlgServer::EnableAuthenticationOptions()
+{
+	if (radioBtnPassword->GetValue())
+	{
+		pickerPrivateKeyFile->Enable(false);
+		pickerPublicKeyFile->Enable(false);
+		txtTunnelPassword->Enable(true);
+	}
+	else
+	{
+		pickerPrivateKeyFile->Enable(true);
+		pickerPublicKeyFile->Enable(true);
+		txtTunnelPassword->Enable(false);
+	}
+}
\ No newline at end of file
diff --git a/pgadmin/frm/frmMain.cpp b/pgadmin/frm/frmMain.cpp
index 12a9e1e..88234b8 100644
--- a/pgadmin/frm/frmMain.cpp
+++ b/pgadmin/frm/frmMain.cpp
@@ -1195,6 +1195,13 @@ void frmMain::StoreServers()
 					settings->Write(key + wxT("SSLRootCert"), server->GetSSLRootCert());
 					settings->Write(key + wxT("SSLCrl"), server->GetSSLCrl());
 					settings->WriteBool(key + wxT("SSLCompression"), server->GetSSLCompression());
+					settings->WriteBool(key + wxT("SSHTunnel"), server->GetSSHTunnel());
+					settings->Write(key + wxT("TunnelHost"), server->GetTunnelHost());
+					settings->Write(key + wxT("TunnelUserName"), server->GetTunnelUserName());
+					settings->WriteBool(key + wxT("TunnelModePwd"), server->GetAuthModePwd());
+					settings->Write(key + wxT("TunnelPassword"), server->GetTunnelPassword());
+					settings->Write(key + wxT("PublicKeyFile"), server->GetPublicKeyFile());
+					settings->Write(key + wxT("PrivateKeyFile"), server->GetPrivateKeyFile());
 
 					pgCollection *coll = browser->FindCollection(databaseFactory, server->GetId());
 					if (coll)
diff --git a/pgadmin/include/dlg/dlgServer.h b/pgadmin/include/dlg/dlgServer.h
index 0fd8f33..71b4dad 100644
--- a/pgadmin/include/dlg/dlgServer.h
+++ b/pgadmin/include/dlg/dlgServer.h
@@ -46,6 +46,11 @@ private:
 	void OnPageSelect(wxNotebookEvent &event);
 	void OnChangeColour(wxColourPickerEvent &ev);
 	void OnChangeFile(wxFileDirPickerEvent &ev);
+	void OnCheckSSHTunnel(wxCommandEvent &ev);
+	void OnChangeAuthOption(wxCommandEvent &ev);
+
+	void EnableSSHTunnelControls(const bool& bEnable);
+	void EnableAuthenticationOptions();
 
 	DECLARE_EVENT_TABLE()
 };
diff --git a/pgadmin/include/pgAdmin3.h b/pgadmin/include/pgAdmin3.h
index 7a9bbdd..9a0f61d 100644
--- a/pgadmin/include/pgAdmin3.h
+++ b/pgadmin/include/pgAdmin3.h
@@ -19,6 +19,10 @@
 #include <wx/listctrl.h>
 #include <wx/xrc/xmlres.h>
 
+#ifdef WIN32
+#include <winsock2.h>
+#endif
+
 #include "utils/misc.h"
 #include <ctl/ctlTree.h>
 #include "ctl/ctlSQLBox.h"
diff --git a/pgadmin/include/schema/pgServer.h b/pgadmin/include/schema/pgServer.h
index c73cec3..192441b 100644
--- a/pgadmin/include/schema/pgServer.h
+++ b/pgadmin/include/schema/pgServer.h
@@ -17,7 +17,7 @@
 
 
 class frmMain;
-
+class CSSHTunnelThread;
 
 class pgServerFactory : public pgaFactory
 {
@@ -41,7 +41,12 @@ extern pgServerFactory serverFactory;
 class pgServer : public pgObject
 {
 public:
-	pgServer(const wxString &newServer = wxT(""), const wxString &newHostAddr = wxT(""), const wxString &newDescription = wxT(""), const wxString &newService = wxT(""), const wxString &newDatabase = wxT(""), const wxString &newUsername = wxT(""), int newPort = 5432, bool storePwd = false, const wxString &newRolename = wxT(""), bool restore = true, int sslMode = 0, const wxString &colour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW).GetAsString(wxC2S_HTML_SYNTAX), const wxString &group = wxEmptyString);
+	pgServer(const wxString &newServer = wxT(""), const wxString &newHostAddr = wxT(""), const wxString &newDescription = wxT(""),
+		const wxString &newService = wxT(""), const wxString &newDatabase = wxT(""), const wxString &newUsername = wxT(""), int newPort = 5432,
+		bool storePwd = false, const wxString &newRolename = wxT(""), bool restore = true, int sslMode = 0,
+		const wxString &colour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW).GetAsString(wxC2S_HTML_SYNTAX), const wxString &group = wxEmptyString,
+		bool sshTunnel = false, const wxString &newTunnelHost = wxEmptyString, const wxString &newTunnelUserName = wxEmptyString, bool authModePwd = true,
+		const wxString &newTunnelPassword = wxEmptyString, const wxString &newPublicKey = wxEmptyString, const wxString &newPrivateKey = wxEmptyString);
 	~pgServer();
 	int GetIconId();
 
@@ -433,11 +438,86 @@ public:
 		sslcompression = b;
 	}
 
+	//SSH Tunnel
+	bool GetSSHTunnel() const
+	{
+		return sshTunnel;
+	}
+	void iSetSSHTunnel(const bool b)
+	{
+		sshTunnel = b;
+	}
+	bool GetAuthModePwd() const
+	{
+		return authModePwd;
+	}
+	void iSetAuthModePwd(const bool b)
+	{
+		authModePwd = b;
+	}
+	wxString GetLocalListenHost() const
+	{
+		return local_listenhost;
+	}
+	void SetLocalListenHost(const wxString &s)
+	{
+		local_listenhost = s;
+	}
+	int GetLocalListenPort() const
+	{
+		return local_listenport;
+	}
+	void SetLocalListenPort(int newVal)
+	{
+		local_listenport = newVal;
+	}
+	wxString GetTunnelHost() const
+	{
+		return tunnelHost;
+	}
+	void SetTunnelHost(const wxString &s)
+	{
+		tunnelHost = s;
+	}
+	wxString GetTunnelUserName() const
+	{
+		return tunnelUserName;
+	}
+	void SetTunnelUserName(const wxString &s)
+	{
+		tunnelUserName = s;
+	}
+	wxString GetTunnelPassword() const
+	{
+		return tunnelPassword;
+	}
+	void SetTunnelPassword(const wxString &s)
+	{
+		tunnelPassword = s;
+	}
+	wxString GetPublicKeyFile() const
+	{
+		return publicKeyFile;
+	}
+	void SetPublicKeyFile(const wxString &s)
+	{
+		publicKeyFile = s;
+	}
+	wxString GetPrivateKeyFile() const
+	{
+		return privateKeyFile;
+	}
+	void SetPrivateKeyFile(const wxString &s)
+	{
+		privateKeyFile = s;
+	}
+
 	void ShowDependencies(frmMain *form, ctlListView *Dependencies, const wxString &where = wxEmptyString);
 	void ShowDependents(frmMain *form, ctlListView *referencedBy, const wxString &where = wxEmptyString);
 
 private:
 	wxString passwordFilename();
+	bool createSSHTunnel(wxString &errorMsg);
 
 	pgConn *conn;
 	long serverIndex;
@@ -460,6 +540,12 @@ private:
 	wxString receiveLoc, replayLoc, replayTimestamp;
 	wxDateTime confLoadedSince;
 
+	//SSH Tunnel
+	CSSHTunnelThread *tunnelObj;
+	bool sshTunnel, authModePwd;
+	int local_listenport;
+	wxString tunnelHost, tunnelUserName, tunnelPassword, publicKeyFile, privateKeyFile, local_listenhost;
+
 #ifdef WIN32
 	SC_HANDLE scmHandle;
 	SC_HANDLE serviceHandle;
@@ -602,4 +688,4 @@ public:
 	bool CheckEnable(pgObject *obj);
 };
 
-#endif
+#endif
\ No newline at end of file
diff --git a/pgadmin/include/utils/module.mk b/pgadmin/include/utils/module.mk
index bdc8ba4..3d18e95 100644
--- a/pgadmin/include/utils/module.mk
+++ b/pgadmin/include/utils/module.mk
@@ -22,7 +22,8 @@ pgadmin3_SOURCES += \
 	$(srcdir)/include/utils/sysProcess.h \
 	$(srcdir)/include/utils/sysSettings.h \
 	$(srcdir)/include/utils/utffile.h \
-	$(srcdir)/include/utils/macros.h
+	$(srcdir)/include/utils/macros.h \
+	$(srcdir)/include/utils/sshTunnel.h 
 
 EXTRA_DIST += \
         $(srcdir)/include/utils/module.mk
diff --git a/pgadmin/include/utils/sshTunnel.h b/pgadmin/include/utils/sshTunnel.h
new file mode 100644
index 0000000..6f8274a
--- /dev/null
+++ b/pgadmin/include/utils/sshTunnel.h
@@ -0,0 +1,105 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+//
+// Copyright (C) 2002 - 2012, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+// sshTunnel.h - Used to create SSH Tunnel
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+#ifndef __SSH_TUNNELING
+#define __SSH_TUNNELING
+
+#ifdef WIN32
+#include <ws2tcpip.h>
+#undef ssize_t
+#define ssize_t SSIZE_T
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <netdb.h>
+#endif
+
+#include <errno.h>
+#include <libssh2.h>
+
+#include <wx/wx.h>
+#include <wx/thread.h>
+#include <wx/arrstr.h>
+#include <wx/arrimpl.cpp>
+
+enum enAuthenticationMethod
+{
+	AUTH_NONE = 0,
+	AUTH_PASSWORD,
+	AUTH_PUBLICKEY
+};
+
+class CSSHTunnelThread :
+		public wxThread
+{
+public:
+	CSSHTunnelThread(const wxString tunnelhost, const wxString remote_desthost, const unsigned int remote_destport,
+	                 const wxString username, const wxString password, const wxString publickey, const wxString privatekey,
+	                 const enAuthenticationMethod& enAuthMethod);
+	virtual ~CSSHTunnelThread(void);
+	virtual void *Entry();
+	wxString Initialize();
+	void Cleanup();
+
+	wxString GetLocalListenIP() const
+	{
+		return m_local_listenip;
+	}
+
+	unsigned int GetLocalListenPort() const
+	{
+		return m_local_listenport;
+	}
+
+private:
+	unsigned long resolveDNS(const char * host, wxArrayString &arrIPAddress);
+
+	int m_listensock, m_sock, m_forwardsock;
+	struct sockaddr_in m_sin;
+	socklen_t m_sinlen;
+	LIBSSH2_CHANNEL *m_channel;
+	LIBSSH2_SESSION *m_session;
+
+	wxString m_publickey;
+	wxString m_privatekey;
+	wxString m_username;
+	wxString m_password;
+	wxString m_tunnelhost;
+	wxString m_errMsg;
+	wxString m_local_listenip;
+	wxString m_remote_desthost;
+	unsigned int m_local_listenport;
+	unsigned int m_remote_destport;
+	enAuthenticationMethod m_enAuthMethod;
+};
+
+class CSubThread :
+		public wxThread
+{
+public:
+	CSubThread(const struct sockaddr_in sin, const wxString remote_desthost, const unsigned int remote_destport,
+	           LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, int forwardsock);
+	virtual ~CSubThread(void);
+	virtual void *Entry();
+
+private:
+	struct sockaddr_in m_sin;
+	wxString m_remote_desthost;
+	unsigned int m_remote_destport;
+	LIBSSH2_SESSION *m_session;
+	LIBSSH2_CHANNEL *m_channel;
+	int m_forwardsock;
+};
+
+#endif
diff --git a/pgadmin/precomp.cpp b/pgadmin/precomp.cpp
index 58d2abb..edee794 100644
--- a/pgadmin/precomp.cpp
+++ b/pgadmin/precomp.cpp
@@ -9,6 +9,10 @@
 //
 //////////////////////////////////////////////////////////////////////////
 
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#endif
+
 #include <wx/wxprec.h>
 
 #include "pgAdmin3.h"
diff --git a/pgadmin/schema/pgServer.cpp b/pgadmin/schema/pgServer.cpp
index 28b5308..56bf54b 100644
--- a/pgadmin/schema/pgServer.cpp
+++ b/pgadmin/schema/pgServer.cpp
@@ -37,10 +37,14 @@
 #include "utils/registry.h"
 #include "frm/frmReport.h"
 #include "dlg/dlgServer.h"
+#include "utils/sshTunnel.h"
 
 #define DEFAULT_PG_DATABASE wxT("postgres")
 
-pgServer::pgServer(const wxString &newName, const wxString &newHostAddr, const wxString &newDescription, const wxString &newService, const wxString &newDatabase, const wxString &newUsername, int newPort, bool _storePwd, const wxString &newRolename, bool _restore, int _ssl, const wxString &_colour, const wxString &_group)
+pgServer::pgServer(const wxString &newName, const wxString &newHostAddr, const wxString &newDescription, const wxString &newService,
+	const wxString &newDatabase, const wxString &newUsername, int newPort, bool _storePwd, const wxString &newRolename, bool _restore,
+	int _ssl, const wxString &_colour, const wxString &_group, bool _sshTunnel, const wxString &newTunnelHost, const wxString &newTunnelUserName,
+	bool _authModePwd, const wxString &newTunnelPassword, const wxString &newPublicKey, const wxString &newPrivateKey)
 	: pgObject(serverFactory, newName)
 {
 	description = newDescription;
@@ -65,6 +69,17 @@ pgServer::pgServer(const wxString &newName, const wxString &newHostAddr, const w
 	restore = _restore;
 	superUser = false;
 	createPrivilege = false;
+
+	// SSH Tunnel
+	tunnelObj = NULL;
+	sshTunnel = _sshTunnel;
+	tunnelHost = newTunnelHost;
+	tunnelUserName = newTunnelUserName;
+	authModePwd = _authModePwd;
+	tunnelPassword = newTunnelPassword;
+	publicKeyFile = newPublicKey;
+	privateKeyFile = newPrivateKey;
+
 #ifdef WIN32
 	scmHandle = 0;
 	serviceHandle = 0;
@@ -76,6 +91,12 @@ pgServer::~pgServer()
 	if (conn)
 		delete conn;
 
+	if(tunnelObj)
+	{
+		delete tunnelObj;
+		tunnelObj = NULL;
+	}
+
 #ifdef WIN32
 	if (serviceHandle)
 		CloseServiceHandle(serviceHandle);
@@ -188,7 +209,16 @@ pgConn *pgServer::CreateConn(wxString dbName, OID oid, wxString applicationname)
 		dbName = GetDatabaseName();
 		oid = dbOid;
 	}
-	pgConn *conn = new pgConn(GetName(), service, hostaddr, dbName, username, password, port, rolename, ssl, oid, applicationname, sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
+
+	pgConn *conn = NULL;
+	if(sshTunnel)
+	{
+		conn = new pgConn(local_listenhost, service, hostaddr, dbName, username, password, local_listenport, rolename, ssl, oid, applicationname, sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
+	}
+	else
+	{
+		conn = new pgConn(GetName(), service, hostaddr, dbName, username, password, port, rolename, ssl, oid, applicationname, sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
+	}
 
 	if (conn && conn->GetStatus() != PGCONN_OK)
 	{
@@ -666,23 +696,46 @@ int pgServer::Connect(frmMain *form, bool askPassword, const wxString &pwd, bool
 
 		form->StartMsg(_("Connecting to database"));
 
+		wxString host, errMsg;
+		int iPort;
+		if(sshTunnel)
+		{
+			// Create SSH Tunnel if required
+			if(!tunnelObj)
+			{
+				if(!createSSHTunnel(errMsg))
+				{
+					wxMessageBox(errMsg, _("SSH Tunnel"), wxICON_ERROR | wxOK);
+					return PGCONN_BAD;
+				}
+			}
+
+			host = local_listenhost;
+			iPort = local_listenport;
+		}
+		else
+		{
+			host = GetName();
+			iPort = port;
+		}
+
 		if (database.IsEmpty())
 		{
-			conn = new pgConn(GetName(), service, hostaddr, DEFAULT_PG_DATABASE, username, password, port, rolename, ssl, 0, appearanceFactory->GetLongAppName() + _(" - Browser"), sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
+			conn = new pgConn(host, service, hostaddr, DEFAULT_PG_DATABASE, username, password, iPort, rolename, ssl, 0, appearanceFactory->GetLongAppName() + _(" - Browser"), sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
 			if (conn->GetStatus() == PGCONN_OK)
 				database = DEFAULT_PG_DATABASE;
 			else if (conn->GetStatus() == PGCONN_BAD && conn->GetLastError().Find(
 			             wxT("database \"") DEFAULT_PG_DATABASE wxT("\" does not exist")) >= 0)
 			{
 				delete conn;
-				conn = new pgConn(GetName(), service, hostaddr, wxT("template1"), username, password, port, rolename, ssl, 0, appearanceFactory->GetLongAppName() + _(" - Browser"), sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
+				conn = new pgConn(host, service, hostaddr, wxT("template1"), username, password, iPort, rolename, ssl, 0, appearanceFactory->GetLongAppName() + _(" - Browser"), sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
 				if (conn && conn->GetStatus() == PGCONN_OK)
 					database = wxT("template1");
 			}
 		}
 		else
 		{
-			conn = new pgConn(GetName(), service, hostaddr, database, username, password, port, rolename, ssl, 0, appearanceFactory->GetLongAppName() + _(" - Browser"), sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
+			conn = new pgConn(host, service, hostaddr, database, username, password, iPort, rolename, ssl, 0, appearanceFactory->GetLongAppName() + _(" - Browser"), sslcert, sslkey, sslrootcert, sslcrl, sslcompression);
 			if (!conn)
 			{
 				form->EndMsg(false);
@@ -1216,6 +1269,48 @@ bool pgServer::AddNamedRestorePoint()
 	return false;
 }
 
+bool pgServer::createSSHTunnel(wxString &errorMsg)
+{
+	bool retVal = false;
+
+	tunnelObj = new CSSHTunnelThread(tunnelHost, GetName(), port, tunnelUserName, tunnelPassword, publicKeyFile,
+		privateKeyFile, authModePwd ? AUTH_PASSWORD : AUTH_PUBLICKEY);
+
+	if(tunnelObj)
+	{
+		errorMsg = tunnelObj->Initialize();
+		if(errorMsg == wxEmptyString)
+		{
+			if ( tunnelObj->Create() != wxTHREAD_NO_ERROR )
+			{
+				delete tunnelObj;
+				tunnelObj = NULL;
+				errorMsg = _("Unable to create SSH Tunnling Thread");
+			}
+			else
+			{
+				if (tunnelObj->Run() != wxTHREAD_NO_ERROR )
+				{
+					delete tunnelObj;
+					tunnelObj = NULL;
+					errorMsg = _("Unable to start SSH Tunnling Thread");
+				}
+
+				SetLocalListenHost(tunnelObj->GetLocalListenIP());
+				SetLocalListenPort(tunnelObj->GetLocalListenPort());
+				retVal = true;
+			}
+		}
+		else
+		{
+			delete tunnelObj;
+			tunnelObj = NULL;
+		}
+	}
+
+	return retVal;
+}
+
 
 pgServerCollection::pgServerCollection(pgaFactory *factory)
 	: pgCollection(factory)
@@ -1289,6 +1384,7 @@ pgObject *pgServerFactory::CreateObjects(pgCollection *obj, ctlTree *browser, co
 	wxString key, servername, hostaddr, description, service, database, username, lastDatabase, lastSchema;
 	wxString storePwd, rolename, restore, serviceID, discoveryID, dbRestriction, colour;
 	wxString group, sslcert, sslkey, sslrootcert, sslcrl, sslcompression;
+	wxString sshTunnel, authModePwd, tunnelHost, tunnelUserName, tunnelPassword, publicKeyFile, privateKeyFile;
 	pgServer *server = 0;
 
 	wxArrayString discoveredServers;
@@ -1327,6 +1423,13 @@ pgObject *pgServerFactory::CreateObjects(pgCollection *obj, ctlTree *browser, co
 		settings->Read(key + wxT("SSLRootCert"), &sslrootcert, wxEmptyString);
 		settings->Read(key + wxT("SSLCrl"), &sslcrl, wxEmptyString);
 		settings->Read(key + wxT("SSLCompression"), &sslcompression, wxT("true"));
+		settings->Read(key + wxT("SSHTunnel"), &sshTunnel, wxT("false"));
+		settings->Read(key + wxT("TunnelHost"), &tunnelHost, wxEmptyString);
+		settings->Read(key + wxT("TunnelUserName"), &tunnelUserName, wxEmptyString);
+		settings->Read(key + wxT("TunnelModePwd"), &authModePwd, wxT("true"));
+		settings->Read(key + wxT("TunnelPassword"), &tunnelPassword, wxEmptyString);
+		settings->Read(key + wxT("PublicKeyFile"), &publicKeyFile, wxEmptyString);
+		settings->Read(key + wxT("PrivateKeyFile"), &privateKeyFile, wxEmptyString);
 
 		// Sanitize the colour
 		colour = colour.Trim();
@@ -1361,7 +1464,8 @@ pgObject *pgServerFactory::CreateObjects(pgCollection *obj, ctlTree *browser, co
 		}
 
 		// Add the Server node
-		server = new pgServer(servername, hostaddr, description, service, database, username, port, StrToBool(storePwd), rolename, StrToBool(restore), ssl);
+		server = new pgServer(servername, hostaddr, description, service, database, username, port, StrToBool(storePwd), rolename, StrToBool(restore), ssl,
+			colour, group, StrToBool(sshTunnel), tunnelHost, tunnelUserName, StrToBool(authModePwd), tunnelPassword, publicKeyFile, privateKeyFile);
 		server->iSetLastDatabase(lastDatabase);
 		server->iSetLastSchema(lastSchema);
 		server->iSetService(service);
@@ -1369,8 +1473,6 @@ pgObject *pgServerFactory::CreateObjects(pgCollection *obj, ctlTree *browser, co
 		server->iSetDiscoveryID(discoveryID);
 		server->iSetDiscovered(false);
 		server->iSetDbRestriction(dbRestriction);
-		server->iSetColour(colour);
-		server->iSetGroup(group);
 		server->iSetServerIndex(loop);
 		server->SetSSLCert(sslcert);
 		server->SetSSLKey(sslkey);
@@ -1378,6 +1480,7 @@ pgObject *pgServerFactory::CreateObjects(pgCollection *obj, ctlTree *browser, co
 		server->SetSSLCrl(sslcrl);
 		server->iSetSSLCompression(StrToBool(sslcompression));
 
+
 		found = false;
 		if (browser->ItemHasChildren(obj->GetId()))
 		{
@@ -1992,4 +2095,4 @@ bool addnamedrestorepointServiceFactory::CheckEnable(pgObject *obj)
 		return server->GetConnected() && server->connection()->BackendMinimumVersion(9, 1) && !server->GetInRecovery();
 	}
 	return false;
-}
+}
\ No newline at end of file
diff --git a/pgadmin/ui/dlgServer.xrc b/pgadmin/ui/dlgServer.xrc
index c0bbd77..a959a3e 100644
--- a/pgadmin/ui/dlgServer.xrc
+++ b/pgadmin/ui/dlgServer.xrc
@@ -348,6 +348,111 @@
               </object>
             </object>
           </object>
+          <object class="notebookpage">
+            <label>SSH Tunnel</label>
+            <object class="wxPanel" name="pnlSSH">
+                <object class="wxFlexGridSizer">
+                  <cols>2</cols>
+                  <vgap>10</vgap>
+                  <hgap>5</hgap>
+                  <growablecols>1</growablecols>
+                  <object class="sizeritem">
+                    <object class="wxStaticText" name="stSSHTunnel">
+                      <label>Use SSH Tunneling</label>
+                    </object>
+                    <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxCheckBox" name="chkSSHTunnel">
+                      <label></label>
+                      <checked>0</checked>
+                    </object>
+                    <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxStaticText" name="stTunnelHost">
+                      <label>Tunnel host</label>
+                    </object>
+                    <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxTextCtrl" name="txtTunnelHost"/>
+                    <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxStaticText" name="stTunnelUsername">
+                      <label>Username</label>
+                    </object>
+                    <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxTextCtrl" name="txtTunnelUsername"/>
+                    <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxRadioButton" name="radioBtnPassword">
+                      <label>Password</label>
+                      <style>wxRB_GROUP</style>
+                    </object>
+                    <flag>wxALIGN_CENTRE_VERTICAL</flag>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxRadioButton" name="radioBtnKeyfile">
+                      <label>Certificate file</label>
+                    </object>
+                    <flag>wxALIGN_CENTRE_VERTICAL</flag>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxStaticText" name="stTunnelPassword">
+                      <label>Password</label>
+                    </object>
+                    <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxTextCtrl" name="txtTunnelPassword">
+                      <style>wxTE_PASSWORD</style>
+                    </object>
+                    <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxStaticText" name="stPublicKeyFile">
+                      <label>Public Key file</label>
+                    </object>
+                    <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxFilePickerCtrl" name="pickerPublicKeyFile">
+                      <message>Select Public Key File</message>
+                    </object>
+                    <flag>wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxStaticText" name="stPrivateKeyFile">
+                      <label>Private Key file</label>
+                    </object>
+                    <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                  <object class="sizeritem">
+                    <object class="wxFilePickerCtrl" name="pickerPrivateKeyFile">
+                      <message>Select Private Key File</message>
+                    </object>
+                    <flag>wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                    <border>4</border>
+                  </object>
+                </object>
+            </object>
+          </object>
         </object>
         <flag>wxEXPAND|wxALIGN_CENTRE|wxALL</flag>
         <border>3</border>
diff --git a/pgadmin/utils/module.mk b/pgadmin/utils/module.mk
index 350aaa6..b01d295 100644
--- a/pgadmin/utils/module.mk
+++ b/pgadmin/utils/module.mk
@@ -21,7 +21,8 @@ pgadmin3_SOURCES += \
 	$(srcdir)/utils/sysSettings.cpp \
 	$(srcdir)/utils/tabcomplete.c \
 	$(srcdir)/utils/utffile.cpp \
-	$(srcdir)/utils/macros.cpp
+	$(srcdir)/utils/macros.cpp \
+	$(srcdir)/utils/sshTunnel.cpp
 
 EXTRA_DIST += \
 	$(srcdir)/utils/module.mk \
diff --git a/pgadmin/utils/sshTunnel.cpp b/pgadmin/utils/sshTunnel.cpp
new file mode 100644
index 0000000..1206bb1
--- /dev/null
+++ b/pgadmin/utils/sshTunnel.cpp
@@ -0,0 +1,393 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+//
+// Copyright (C) 2002 - 2012, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+// sshTunnel.cpp - Used to create SSH Tunnel
+//
+//////////////////////////////////////////////////////////////////////////
+
+// App headers
+#include "pgAdmin3.h"
+#include "utils/sshTunnel.h"
+
+CSSHTunnelThread::CSSHTunnelThread(const wxString tunnelhost, const wxString remote_desthost, const unsigned int remote_destport,
+                                   const wxString username, const wxString password, const wxString publickey, const wxString privatekey,
+                                   const enAuthenticationMethod& enAuthMethod)
+		: m_tunnelhost(tunnelhost), m_remote_desthost(remote_desthost), m_remote_destport(remote_destport), m_username(username),
+		m_password(password), m_publickey(publickey), m_privatekey(privatekey), m_enAuthMethod(enAuthMethod)
+{
+	m_local_listenip = wxEmptyString;
+	m_local_listenport = 0;
+	m_errMsg = wxEmptyString;
+	m_listensock = -1, m_sock = -1, m_forwardsock = -1;
+	m_channel = NULL;
+	m_session = NULL;
+}
+
+CSSHTunnelThread::~CSSHTunnelThread(void)
+{
+}
+
+wxString CSSHTunnelThread::Initialize()
+{
+	int rc, auth = AUTH_NONE;
+	const char *fingerprint;
+	char *userauthlist;
+	m_errMsg = _("Unable to create SSH Tunnel. For more information see the logs!!!");
+
+#ifdef WIN32
+	char sockopt;
+	WSADATA wsadata;
+
+	WSAStartup(MAKEWORD(2, 0), &wsadata);
+#else
+	int sockopt;
+#endif
+
+	wxArrayString arrTunnelHostIP;
+	unsigned long errorno = resolveDNS(m_tunnelhost.mb_str(), arrTunnelHostIP);
+
+	if (errorno == 0)
+	{
+		/* Connect to SSH server */
+		m_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+		m_sin.sin_family = AF_INET;
+		if (INADDR_NONE == (m_sin.sin_addr.s_addr = inet_addr(arrTunnelHostIP.Item(0).mb_str())))
+		{
+			wxLogError(_("Error in inet address!\n"));
+			return m_errMsg;
+		}
+		m_sin.sin_port = htons(22);
+		if (connect(m_sock, (struct sockaddr*)(&m_sin),
+		            sizeof(struct sockaddr_in)) != 0)
+		{
+			wxLogError(_("Could not connect to socket"));
+			return m_errMsg;
+		}
+
+		/* Create a session instance */
+		m_session = libssh2_session_init();
+
+		if (!m_session)
+		{
+			wxLogError(_("Could not initialize SSH session!\n"));
+			return m_errMsg;
+		}
+
+		/* ... start it up. This will trade welcome banners, exchange keys,
+		* and setup crypto, compression, and MAC layers
+		*/
+		rc = libssh2_session_handshake(m_session, m_sock);
+
+		if (rc)
+		{
+			wxLogError(_("Error when starting up SSH session: %d\n"), rc);
+			return m_errMsg;
+		}
+
+		/* At this point we havn't yet authenticated.  The first thing to do
+		* is check the hostkey's fingerprint against our known hosts Your app
+		* may have it hard coded, may go to a file, may present it to the
+		* user, that's your call
+		*/
+		fingerprint = libssh2_hostkey_hash(m_session, LIBSSH2_HOSTKEY_HASH_SHA1);
+
+		/* check what authentication methods are available */
+		userauthlist = libssh2_userauth_list(m_session, m_username.mb_str(), strlen(m_username.mb_str()));
+
+		if (strstr(userauthlist, "password"))
+			auth |= AUTH_PASSWORD;
+		if (strstr(userauthlist, "publickey"))
+			auth |= AUTH_PUBLICKEY;
+
+		if ((auth & AUTH_PASSWORD) && (m_enAuthMethod == AUTH_PASSWORD))
+			auth = AUTH_PASSWORD;
+		if ((auth & AUTH_PUBLICKEY) && (m_enAuthMethod == AUTH_PUBLICKEY))
+			auth = AUTH_PUBLICKEY;
+
+		if (auth & AUTH_PASSWORD)
+		{
+			if (libssh2_userauth_password(m_session, m_username.mb_str(), m_password.mb_str()))
+			{
+				m_errMsg = _("Authentication by password failed to create SSH Tunnel.\n");
+				Cleanup();
+				return m_errMsg;
+			}
+		}
+		else if (auth & AUTH_PUBLICKEY)
+		{
+			if (libssh2_userauth_publickey_fromfile(m_session, m_username.mb_str(), m_publickey.mb_str(),
+			                                        m_privatekey.mb_str(), m_password.mb_str()))
+			{
+				m_errMsg = _("Authentication by public key failed to create SSH Tunnel.\n");
+				Cleanup();
+				return m_errMsg;
+			}
+		}
+		else
+		{
+			wxLogError(_("No supported authentication methods found!\n"));
+			Cleanup();
+			return m_errMsg;
+		}
+
+		//Get the IP Address of local machine
+		char hostname[256];
+		gethostname(hostname, sizeof(hostname));
+		wxArrayString arrLocalIP;
+		resolveDNS(hostname, arrLocalIP);
+
+		m_listensock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+		m_sin.sin_family = AF_INET;
+		// Give port no to 0 so that bind will automatically select the available port.
+		m_sin.sin_port = htons(0);
+		if (INADDR_NONE == (m_sin.sin_addr.s_addr = inet_addr(arrLocalIP.Item(0).mb_str())))
+		{
+			wxLogError(_("inet_addr failed"));
+			Cleanup();
+			return m_errMsg;
+		}
+
+		sockopt = 1;
+		setsockopt(m_listensock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
+		m_sinlen = sizeof(m_sin);
+		if (-1 == bind(m_listensock, (struct sockaddr *)&m_sin, m_sinlen))
+		{
+			wxLogError(_("bind failed"));
+			Cleanup();
+			return m_errMsg;
+		}
+		if (getsockname(m_listensock, (struct sockaddr *)&m_sin, &m_sinlen) == -1)
+		{
+			wxLogError(_("getsockname() failed"));
+			Cleanup();
+			return m_errMsg;
+		}
+
+		if (-1 == listen(m_listensock, 2))
+		{
+			wxLogError(_("listen failed"));
+			Cleanup();
+			return m_errMsg;
+		}
+
+		m_local_listenip = wxString(inet_ntoa(m_sin.sin_addr), wxConvLibc);
+		m_local_listenport = ntohs(m_sin.sin_port);
+
+		wxLogInfo(wxT("Waiting for TCP connection on %s:%d...\n"),
+		          m_local_listenip.c_str(), m_local_listenport);
+
+		return wxEmptyString;
+	}
+
+	return m_errMsg;
+}
+
+void * CSSHTunnelThread::Entry()
+{
+	while (1)
+	{
+		m_forwardsock = accept(m_listensock, (struct sockaddr *) & m_sin, &m_sinlen);
+		if (-1 == m_forwardsock)
+		{
+			wxLogError(_("accept failed"));
+			Cleanup();
+			break;
+		}
+		// Create thread for read/write.
+		CSubThread *subThread = new CSubThread(m_sin, m_remote_desthost, m_remote_destport, m_session, m_channel, m_forwardsock);
+		if ( subThread->Create() != wxTHREAD_NO_ERROR )
+		{
+			delete subThread;
+			subThread = NULL;
+		}
+		else
+		{
+			if (subThread->Run() != wxTHREAD_NO_ERROR )
+			{
+				delete subThread;
+				subThread = NULL;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+void CSSHTunnelThread::Cleanup()
+{
+
+#ifdef WIN32
+	closesocket(m_forwardsock);
+	closesocket(m_listensock);
+#else
+	close(m_forwardsock);
+	close(m_listensock);
+#endif
+
+	if (m_channel)
+		libssh2_channel_free(m_channel);
+
+	libssh2_session_disconnect(m_session, "Client disconnecting normally");
+
+	libssh2_session_free(m_session);
+
+#ifdef WIN32
+	closesocket(m_sock);
+#else
+	close(m_sock);
+#endif
+
+	libssh2_exit();
+}
+
+unsigned long CSSHTunnelThread::resolveDNS(const char * host, wxArrayString &arrIPAddress)
+{
+	unsigned long errorno = 0;
+	struct in_addr addr;
+	struct hostent* remoteHost = gethostbyname(host);
+	if (remoteHost != NULL)
+	{
+		if (remoteHost->h_addrtype == AF_INET)
+		{
+			int i = 0;
+			while (remoteHost->h_addr_list[i] != 0)
+			{
+				addr.s_addr = *(u_long *) remoteHost->h_addr_list[i++];
+				arrIPAddress.Add(wxString((char*) inet_ntoa(addr), wxConvLocal));
+			}
+		}
+	}
+	else
+	{
+		errorno = errno;
+	}
+
+	return errorno;
+}
+
+CSubThread::CSubThread(const struct sockaddr_in sin, const wxString remote_desthost, const unsigned int remote_destport,
+                       LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, int forwardsock)
+		: m_sin(sin), m_remote_desthost(remote_desthost), m_remote_destport(remote_destport),
+		m_session(session), m_channel(channel), m_forwardsock(forwardsock)
+{
+}
+
+CSubThread::~CSubThread(void)
+{
+}
+
+void *
+CSubThread::Entry()
+{
+	fd_set fds;
+	struct timeval tv;
+	ssize_t len, wr;
+	char buf[16384];
+	int rc, i = 0;
+
+	const char *shost = inet_ntoa(m_sin.sin_addr);
+	unsigned int sport = ntohs(m_sin.sin_port);
+
+	wxLogInfo(wxT("\nForwarding connection from %s:%d here to remote %s:%d\n"), inet_ntoa(m_sin.sin_addr),
+	          sport, m_remote_desthost.c_str(), m_remote_destport);
+
+	/* Must use blocking here to avoid connect errors */
+	libssh2_session_set_blocking(m_session, 1);
+
+	m_channel = libssh2_channel_direct_tcpip_ex(m_session, m_remote_desthost.mb_str(),
+	            m_remote_destport, shost, sport);
+
+	if (!m_channel)
+	{
+		wxLogError(_("Could not open the direct-tcpip channel!\n (Note that this can be a problem at the server! Please review the server logs.)\n"));
+		goto shutdown;
+	}
+
+	/* Must use non-blocking IO hereafter due to the current libssh2 API */
+	libssh2_session_set_blocking(m_session, 0);
+
+	while (1)
+	{
+		FD_ZERO(&fds);
+		FD_SET(m_forwardsock, &fds);
+		tv.tv_sec = 0;
+		tv.tv_usec = 100000;
+		rc = select(m_forwardsock + 1, &fds, NULL, NULL, &tv);
+		if (-1 == rc)
+		{
+			wxLogError(_("select failed"));
+			goto shutdown;
+		}
+		if (rc && FD_ISSET(m_forwardsock, &fds))
+		{
+			len = recv(m_forwardsock, buf, sizeof(buf), 0);
+			if (len < 0)
+			{
+				wxLogError(_("read failed"));
+				goto shutdown;
+			}
+			else if (0 == len)
+			{
+				wxLogInfo(_("The client at %s:%d disconnected!\n"), shost, sport);
+				goto shutdown;
+			}
+			wr = 0;
+			do
+			{
+				i = libssh2_channel_write(m_channel, buf, len);
+
+				if (i < 0)
+				{
+					wxLogError(_("libssh2_channel_write: %d\n"), i);
+					goto shutdown;
+				}
+				wr += i;
+			}
+			while (i > 0 && wr < len);
+		}
+		while (1)
+		{
+			len = libssh2_channel_read(m_channel, buf, sizeof(buf));
+
+			if (LIBSSH2_ERROR_EAGAIN == len)
+				break;
+			else if (len < 0)
+			{
+				wxLogError(_("libssh2_channel_read: %d"), (int)len);
+				goto shutdown;
+			}
+			wr = 0;
+			while (wr < len)
+			{
+				i = send(m_forwardsock, buf + wr, len - wr, 0);
+				if (i <= 0)
+				{
+					wxLogError(_("write failed"));
+					goto shutdown;
+				}
+				wr += i;
+			}
+			if (libssh2_channel_eof(m_channel))
+			{
+				wxLogInfo(_("The server at %s:%d disconnected!\n"),
+				          m_remote_desthost.c_str(), m_remote_destport);
+				goto shutdown;
+			}
+		}
+	}
+shutdown:
+#ifdef WIN32
+	closesocket(m_forwardsock);
+#else
+	close(m_forwardsock);
+#endif
+
+	if (m_channel)
+		libssh2_channel_free(m_channel);
+
+	return NULL;
+}
