背景

由于国内网络环境异常不稳定,所以网络加速器这类应用程序,对于我们游戏玩家,特别是外服游戏玩家来说,是必须品.

最开始用的是proxifier,但是它不支持udp链接,而且很贵,最重要的是它是基于LSP劫持实现的加速,兼容性差,甚至会触发反作弊(比如战眼就会主动拦截),已经不用了.但此应用的功能性是最好的,同时多规则多线路甚至级联加速.

后来了解到sockscap32,是破解版,支持tcp和udp,规则设置有点复杂,但总体上可以满足加速需要,大部分游戏都能兼容,原理未知.一直用到下面这个出现才停止使用.

sockscap64是我用的第3款应用,也是我目前用过最好用的加速器,它是基于进程的不用设置规则,而且可以存储多个加速线路,但同时只能使用1个线路.由于他是注入dll的,所以可能会触发反作弊,但可以确认的是沃尔沃的VAC是通过的.

正题

这几天在v2ex上看到一个名为”netch”的加速器,下载试用了一下,效果不错,支持tcp/udp,而且是开源的

经过仔细查看源码,该应用的作者是利用了现成的NFSDK的可执行核心来实现加速的,由NF驱动和一个由C/C++编译的调用NF驱动的可执行文件组成

NF驱动安装到系统后,可以直接由C/C++编译的可执行文件调用,官网同时提到了支持C#和Delphi,但C#和Delphi必须使用一个经过包装的C/C++链接库的方式去调用,不能直接调用驱动(实际上C#是可以的)

NF驱动基于TDI或WFP实现,w7开始windows默认使用WFP了,LSP早晚要被废弃,就连那些做传奇登录器劫持的人都不用LSP了

看了一下手册(同时官网也有demo),于是决定做一个自己用的加速器,由drive.sys和C++.dll和C#.gui组成

实现步骤 一

  1. C++的导出动态库
  2. 调用此动态库的C#类

首先,根据demo写出需要的方法,并且生成导出dll,我这里偷懒直接使用了官方demo里面的SocksRedirector.cpp,只是实现代理的功能,已经足够了

虚拟机里面下载并安装vs2005(官方demo),我告诉你有下,简体中文版2.5G,安装完成后打开,右键项目属性,目标平台改为x64,编译出SocksRedirector.dll

拿到生成好的动态链接库,分析一下依赖,发现有个nfapi.dll,这个应该就是动态链接库与驱动的中间层了,官方demo里面有编译好的,找到x64目录下的nfapi.dll拷贝到和SocksRedirector.dll一起

注意,可能需要在运行环境上装vc2005再发行包

非托管的东西都准备好了,现在来写托管的.首先创建一个C#的控制台应用程序,并创建一个类,我这里叫$project/NFAPI/SocksRedirect.cs

using System;
using System.Runtime.InteropServices;

namespace iPEX_Test.NFAPI {
public class SocksRedirect {
///

/// 选项枚举
///

public enum OPTION_TYPE{
OT_NONE,
OT_DRIVER_NAME, // NFSDK driver name, by default - netfilter2
OT_PROTOCOL, // "tcp" or "udp". Default value is empty, which means any protocol
OT_PROCESS_NAME, // Add process name to list
OT_REMOTE_ADDRESS, // Add remote IP or network (e.g. 192.168.137.0/24) to list
OT_REMOTE_PORT, // Add remote port to list
OT_ACTION, // "redirect" - redirect to proxy, "bypass" - don't redirect. By default - redirect.
OT_PROXY_ADDRESS, // SOCKS5 proxy IP:port, e.g. 192.168.137.105:1080
OT_PROXY_USER_NAME, // SOCKS5 proxy user name
OT_PROXY_PASSWORD // SOCKS5 proxy user password
};

private const String DllName="SocksRedirector";

// Initialize the library
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean drv_init();

// Stop redirection and free the library
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void drv_free();

// Delete all added options
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean clearOptions();

// Start adding options for a rule
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void startRule();

// Push added options to list of rules
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void endRule();

// Add an option as a string with specified type
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean addOption(OPTION_TYPE optionType,String optionValue);

// Start or stop redirection
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean enable(Int32 start);
}
}

注意,导出函数名需要与dll中的一致,否则需要指定入口点,由于我是有部分修改的,请以实际情况为准

可以看到我一共导出了7个函数,从上往下依次是:驱动初始化,驱动释放,清除选项,开始添加选项,停止添加选项,添加一个选项,挂载

Options和Rule其实差不多意思,我这里直接抄了官方demo的命名

结语

第一部分就此结束了,下一部分将实现通过C#调用刚才的导出类来让驱动挂载并实现网络代理.