2014-10-12

翻墙更舒畅:将ssh隧道设置为windows服务

利用境外vps主机配合putty/plink实现ssh隧道(ssh tunnel)来翻墙方便又安全,但是每次总要开个putty窗口,很是不爽。

今天将小站从aws迁移到linode后,突发奇想,可否将plink相关命令配置成一个windows服务,像linux下的守护进程那样,默默的在后台提供服务?

说干就干,搜索了一下,实现自定义的windows服务有两个工具可以使用,一个是sc,一个是instsrv 。

sc看起来比较符合使用习惯,首先就是他了。

把plink命令保存为脚本:

C:\Users\farnsworth>plink.exe -C -D 127.0.0.1:<local_port> <user_name>@<server_host_name> -pw <passwd>

通过sc create创建新的服务:

C:\Users\farnsworth>sc create my_ssh_tunnel binPath= "C:\Program Files\Putty\linode_ssh_tunnel.bat" \
 type= share start= auto DisplayName= "My-SSH-Tunnel"

[SC] CreateService 成功

PS:

注意sc命令的参数中“=”号后面必须要加个空格。

打开service面板,已经可以看到刚才创建的服务了:

尝试启动服务:

直接跪倒在地。

仔细检查了一下脚本,没有任何问题。搜索了一下“1053”错误码,原因是因为windows服务进程是需要有一定的规范的,要响应windows系统的诸如on_load之类的事件(不懂windows,on_load这个纯瞎举例),否则windows无法与服务进程进行沟通。

此路不通,难道要搞个vs写程序才能搞定?

细想一下,这种需求应该是普遍需求,linux下面不是有inetd这样的程序来托管简化守护进程的编写么?windows应该也有。顺着这个思路找了一下,果然有:

Using Srvany to run an application as a Windows Service?

What is Srvany?

微软官方说明文档:

How To Create a User-Defined Service

Srvany集成在了Windows Server 2003 Resource Kit Tools中,可从此处下载:

Windows Server 2003 Resource Kit Tools

正如上文设想的那样,Srvany的功能就是提供了一个类似于inetd一样的windows service框架,可以通过Srvany快速搭建自己的windows服务。

这回我们换用instsrv

首先删除之前用sc创建的服务


C:\Users\farnsworth>sc delete my_ssh_tunnel
[SC] DeleteService 成功

使用instsrv创建新服务


C:\Users\farnsworth>instsrv my_ssh_tunnel "C:\Program Files\Windows Resource Kits\Tools\srvany.exe"

The service was successfuly added!

Make sure that you go into the Control Panel and use
the Services applet to change the Account Name and
Password that this newly installed service will use
for its Security Context.

打开regedit,在[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\下找到my_ssh_tunnel:

在my_ssh_tunnel下,新建Parameters项

并在Parameters项中,创建如下三个键值:

Application:服务运行的程序的路径。
AppDirectory :服务运行的程序的文件夹路径。
AppParameters :服务运行的程序启动所需要的参数。

启动服务:

成功:

打开chrome,设置好SwitchySharp,打开google:

再次跪倒在地。

问题出在哪里呢?

仔细检查,发现在用instsrv创建服务的时候有提示:

难道是权限问题。

打开服务属性,切到“登录”tab,填入管理员账户:

重启服务后,再试:

bingo!

试一下重启操作系统。

重启成功之后,服务自行启动,但是发现不好使,必须要自己手动再重启一遍才行。猜想是因为服务依赖的问题,在网络没有成功连接的时候就启动了隧道服务,导致plink连接服务器失败。

搞了一会儿也没解决这个问题,本质上是因为我们的服务太简陋了,没有重试策略。

搞到这里没精力再继续研究下去了,暂且先这样,后续再研究。

update:

解决重启之后服务自动启动连接失败的问题其实很简单,在服务管理器里面把服务设置成“自动(延迟启动)即可”

开始享受吧~

 

 

–EOF–