Windows下全局流量转发的应用与实现

Windows下全局流量转发的应用与实现

引子

之前我写过一个 Socks5 代理 demo, 但是其并不能实现全局流量转发, 有些不支持 socks5 转发的软件就不能使用这种方式, 碰巧有个不可明说的项目需要做到这一点, 于是就针对全局流量转发做了一点研究, 首先提到流量转发, 可能是游戏打得比较多, 第一印象是网游加速器, 而目前的网游加速器大部分都有几个模式, 问了某个带佬后, 大致明白这几个模式分别是虚拟网卡 (Tun/Tap),Lsp,WFP 等方式, 而传统 HTTP 代理, 则会用到 Proxifier. 下面分别对这几种方式进行说明:

HTTP 代理(Proxifier)

HTTP 代理比较特殊, 因为很多浏览器插件(就像我使用的 SwitchyOmega) 或者浏览器本身就支持 Socks5, 但是对普通用户来说, 你不能奢望他们使用的浏览器恰好支持, 况且即使支持, 也不一定能指望他们会设置.
一般浏览器的代理选项默认会选择系统代理 (IE 代理), 这代理 模式虽然没说, 但是查阅还是可以知道只支持 HTTP 代理, 而我们要做的就是把 Socks5 转成 HTTP.
一般业内使用的是 Proxifier 比较多, 比如出名的 SS/SSR 之类.

Proxifier 有两种版本, 一个是需要安装的, 一个是不需要安装的 Portable Version, 两种原理是不一样的.Portable Version 使用的是 hook 技术, 使用 SetWindowsHookEx 将 dll 注入到目标进程, 然后该 dll 来 hook WinSock 相关的函数; 安装版的是用的 LSP(Layered Service Provider)技术, 这个技术已经被微软给废弃了, 因为不安全

因为 Proxifier 启动时可以通过赋给启动参数 - c 来让其调用配置文件, 所以在这个文件中对其进行配置, 比如, 在我这个项目中, 将 SSR 流量转发为 HTTP 代理的方式如下:

ConfFullPath = $"{Environment.CurrentDirectory}\\{ConfName}";
            string ConfStr = new StringBuilder().
                            AppendN($"listen-address {LocalAddress}:{Socks5LocalPort}").
                            AppendN("toggle 0").
                            AppendN("show-on-task-bar 0").
                            AppendN("activity-animation 0").
                            AppendN($"forward-socks5 / {LocalAddress}:{SSRLocalPort} .").
                            AppendN("max-client-connections 4096").
                            Append("hide-console").
                        ToString();
            if (File.Exists(ConfFullPath)) { File.Delete(ConfFullPath); }
            using (FileStream ConfFile = File.OpenWrite($"{Environment.CurrentDirectory}\\{ConfName}"))
            {
                ConfFile.Write(ConfStr.ToBytes(), 0, ConfStr.ToBytes().Length);
            }

            Instance = new Process
            {
                StartInfo =
                {
                    FileName = Path.GetFullPath("Privoxy.exe"),
                    WorkingDirectory = Environment.CurrentDirectory,
                    Arguments = $"-c {ConfName}",
                    CreateNoWindow = true,
                    UseShellExecute = true,
                    WindowStyle = ProcessWindowStyle.Hidden
                }
            };
C#

由此对 Instance 进行 Start 操作后 Privoxy 就会将参数的{LocalAddress}:{SSRLocalPort}转发到对应的{LocalAddress}:{Socks5LocalPort}.

Tun/Tap(虚拟网卡)

这个技术貌似是从 Openvpn 发展过来的,, 因为其 Tap-Windows 可以剥离出来使用, 所以但是很快被应用到其它场景之上, 很多强大的项目都是基于此, 例如 SSTAP 和相对比较新的 Netch, 使用它的话需要提前安装虚拟网卡, 也有 Tun2Socks 这种项目对其整个驱动进行封装, 方便调用.Netch 中是首先将虚拟网卡权重调到最高, 而我项目中, 则是用的路由表的方式, 首先将系统网卡的跃点修改到 150, 然后将代理服务器的走系统网卡, 再添加一条路由表将 Tun 网卡跃点修改为 20(只要 Tun 网卡跃点比系统网卡低就行). 代码如下:

  public Tun2(string ServerHost)
        {
            _savedServer = ServerHost;

            Instance = new Process()
            {
                StartInfo = new ProcessStartInfo()
                {
                    FileName = Path.GetFileName("tun2socks.exe"),
                    Arguments = $"-proxyType socks -proxyServer {LocalAddress}:{SSRLocalPort} -tunAddr 10.0.20.2 -tunGw 10.0.20.1 -tunMask 255.255.255.0 -tunDns 223.5.5.5,8.8.8.8 --fakeDns",
                    CreateNoWindow = false,
                    /*RedirectStandardError = true,
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false,*/
                    WindowStyle = ProcessWindowStyle.Hidden
                }
            };
            Configure();
            //修改跃点
            bool t = ChangeRoute("0.0.0.0", 0, AdpGateway.ToString(), AdpIndex, 150);
            //添加路由
            bool b = CreateRoute(_serverAddresses[0].ToString(), 32, AdpGateway.ToString(), AdpIndex, 20);
            Console.WriteLine(b);
        }

        public override void Start()
        {
            Instance.Start();
            bool c = CreateRoute("0.0.0.0", 0, "10.0.20.1", TunTapIndex, 50);
            Console.WriteLine(c);
        }
C#

网易 UU 此模式框架图:

WFP(Windows Filtering Platform -- Windows 筛选平台)

这个模式是由 Microsoft 在废弃上文中说到的 Lsp 技术中后开发的:

WFP 维基百科
Windows 筛选平台(Windows Filtering Platform,缩写 WFP;也译 Windows 过滤平台)是微软操作系统中的一套系统服务和应用程序接口,于 2006 年至 2007 年在 Windows Vista 中首次引入。它允许应用程序绑定到包处理环节,过滤下一代 TCP/IP 协议栈的流水线。它提供集成通信等功能,管理员可以将其配置为在每个应用程序的基础上调用处理逻辑。微软预期 WFP 将被防火墙及其他数据包处理或连接监控组件使用,如杀毒软件和家长控制软件。另外,WFP 也被用于实现网络地址转换(NAT)和存储 IPSec 策略配置。

不过这个东西太复杂了, 还得写内核驱动, 好在有开源项目对这个进行了封装, 可以直接调用接口
WinDivert 2.2: Windows Packet Divert
这个项目很强大, 可以拦截任意的网络封包并进行修改或者转发.
除此之外, 还有相对商业化, 闭源且收费的
Network filtering toolkit
比起 WinDivert, 它在多平台和多语言上都有相应的组件. 但和 Tun2 一样, 它也需要事先安装驱动.
值得一提的是,Netch 的 WFP 模式用的驱动就是 Windivert 的 Demo 版本驱动, 所以有 1000000 个连接的限制——虽然可以通过卸载重装实现清零操作.
由于对此研究不够, 所以并没有引用在自己项目中. 具体运用可以参考 Netch.

参考

联系我们

联系电话

4000-640-466

联系邮箱

service@f-li.cn

办公地址

上海黄浦区外滩源1号

谢谢,您的信息已成功发送。
请填写信息。