翻入墙内 | 反向SSH Tunnel | Reverse SSH Tunnel

状况 | Case 因为GFW的关系,越来越多的网友熟练掌握了使用SSH Tunnel“翻墙”的方法——这种方法使我们通过墙外一台主机作为代理中转访问国际互联网。网上关于SSH翻墙的文章已经很多,无须赘述,提及此只为特别感谢郭嘉。 少数情况下,我们不仅需要翻出墙,可能还需要从墙外翻回来。比如你交友不慎,某个邪恶国家友人强烈要求感受一下国内的网络环境;你如此勤奋以至于希望在家中仍然能够连接到公司网络开工,公司却出于体恤员工的考虑没有提供VPN,此时就需要手段先“翻”到公司的院子里。反向的SSH Tunnel就是这样的手段。 原理 | Principle 在一般的SSH转发模型中,我们从大中华局域网中的Desktop B去SSH连接外部SSH Server X,将A的Px端口映射到X的SSH Server端口(22)。连接建立后我们就可以在应用中指定127.0.0.1:Px为代理。发往127.0.0.1.Px的请求将通过Tunnel发送到X:22,并根据SSH协议中转发的规定转发到外部网络。(此部分图中未表现)。 在反向SSH Tunnel中,我们由大中华局域网内Desktop B用SSH连接外部主机Desktop A上的SSH Server,并建立一个反向Tunnel,将A:Port1映射到B:Port2。相比于一般的正向Tunnel,反向Tunnel允许SSH连接的被动方A将Port1上的请求通过Tunnel转发到B:Port2上。而B上应有一个应用监听Port2,对Port2上的请求做适宜的处理。对于一般的网络代理而言,此“应用”即为SSH Server。SSH Server监听22端口,并对来自SSH Tunnel的请求通过本地网络转发,起到代理的作用。 实例 | Practice 用到反向SSH Tunnel,是因为之前有这样一个需求:我们有一个开发中的网站,将要在外部Web Server(Host A)上布署测试环境,需要在外部主机上获取代码并持续更新。代码通过公司内部的SVN Server(Host S)进行版本控制,公司外部无法访问。我们不希望在外部主机上通过VPN一类软件登录公司网络,而是在必要的时候由内部网络发起连接。因此我们使用反向SSH Tunnel。 创建反向SSH Tunnel的过程由内网的桌面(Host B)来完成 1root@B#ssh -NfR {PORT_A}:localhost:{PORT_B} {HOST_A} -l {USER@HOST_A} 如 1root@desktop#ssh -Nf$ 8080:localhost:9090 www.example.com -l webadmin 输入密码确认后,一个从desktop:8080到www.example.com:9090的反向Tunnel就建好了。在Host A上用 1netstat -ntl | grep [...]

小心动态链接库链接静态库时的内存错误

最近写的模块,在独立的应用程序中测试是没问题的,但把它装配成DLL后,再在另一个应用程序中调用时却出现了内存错误。程序的模块链接关系大概是这样的: module就是我所写的模块,在这里被封装为DLL,因为要使用json相关的功能,该DLL链接了一个静态库 (jsoncpp.lib)。最后在应用程序中导入并使用module.dll,同时因为在应用程序中也需要用到json,所以应用程序也链接了jsoncpp.lib。 以下用一些伪代码来描述这些模块间的调用关系,以具现出这个错误。 jsoncpp.lib为c++提供了功能齐全的json操作,其核心的类是Json::Value。(阅读本篇文章你无需了解太多json) module.dll中导出了一个接口: //ModuleClass.h #include "json/value.h" #if defined MODULE_EXPORTS #define MODULE_EXPORTS __declspec(dllexport) #else #define MODULE_EXPORTS __declspec(dllimport) #endif class ModuleClass { public: MODULE_EXPORTS void AllocSomeMemory( Json::Value &root ) { // 这将申请一些内存,因为会new出一个Json::Value,并append到root上 root.append( "testString" ); } }; 应用程序: #include "json/value.h" #include "ModuleClass.h" int main() { Json::Value root; ModuleClass::AllocSomeMemory( root ); } 在Debug模式下,当main函数执行完毕,对Json::Value root进行析构时,程序便出现了异常。分析下,很显然,调用ModuleClass::MallocMemoryHere时申请的内存,是在module.dll中申请的,而对这些内存的析构则是在应用程序(.exe)中进行的(析构root会同时析构append在root上的所有子Json::Value)。不过,这是异常的真正原因么? 追踪到异常的出错点:dbgheap.c文件中那句ASSERT语句。 [...]

Posted in: C++ by Benny Chen No Comments , ,