介绍:
Titanium.Web.Proxy是用 C# 编写的轻量级 HTTP(S) 代理服务器,类似于转包工具Fiddler,但是比 Fiddler 强大很多。
特点:
- 采用服务器连接池、证书缓存和缓冲池的多线程完全异步代理
- 查看/修改/重定向/阻止请求和响应
- 支持相互 SSL 认证、代理认证和自动上游代理检测
- Windows 域的基于 HTTP 协议的 Kerberos/NTLM 身份验证
- SOCKS4/5 代理支持
应用:
在访问指定域名网站中,对其网页进行注入对网页内容做修改
1,首先,使用Visual Studio 2019新建一个C#控制台应用程序的项目,在项目中使用使用NuGet引用 Titanium.Web.Proxy 包,注意NuGet的镜像源;
2,然后开始代码实现,在Program.cs中:
using System; namespace WebProxy { internal class Program { private static void Main(string[] args) { Proxy p = new(); p.Start(); Console.Read(); p.Stop(); } } }
3,新建项目项Proxy.cs文件:
using System; using System.Net; using System.Threading; using System.Threading.Tasks; using Titanium.Web.Proxy; using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.Models; namespace WebProxy { public class Proxy { private readonly SemaphoreSlim @lock = new(1); private readonly ProxyServer proxyServer; private readonly ExplicitProxyEndPoint explicitEndPoint; public const string LocalDomain = "www.baidu.com"; public Proxy() { proxyServer = new ProxyServer(); proxyServer.BeforeResponse += OnResponse; //绑定监听端口 Random rnd = new Random(); explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 56801, true); Console.WriteLine("监听地址127.0.0.1:56801"); //隧道请求连接前事件,HTTPS用 explicitEndPoint.BeforeTunnelConnectRequest += ExplicitEndPoint_BeforeTunnelConnectRequest; //代理服务器注册监听地址 proxyServer.AddEndPoint(explicitEndPoint); } public void Start() { Console.WriteLine("开始监听"); proxyServer.Start(); proxyServer.SetAsSystemHttpProxy(explicitEndPoint); proxyServer.SetAsSystemHttpsProxy(explicitEndPoint); } public void Stop() { if (proxyServer.ProxyRunning) { proxyServer.BeforeResponse -= OnResponse; explicitEndPoint.BeforeTunnelConnectRequest -= ExplicitEndPoint_BeforeTunnelConnectRequest; Console.WriteLine("结束监听"); // 结束监听 proxyServer.Stop(); } else { Console.WriteLine("监听没开启"); } try { proxyServer.DisableAllSystemProxies(); } catch { Console.WriteLine("清除代理"); } proxyServer.Dispose(); } private async Task ExplicitEndPoint_BeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { string hostname = e.HttpClient.Request.RequestUri.Host; await WaitMessage("Tunnel to: " + hostname); e.DecryptSsl = false; if (hostname.StartsWith(LocalDomain)) { e.DecryptSsl = true; } } public async Task OnResponse(object sender, SessionEventArgs e) { var request = e.HttpClient.Request; if (request.Host.Contains(LocalDomain)) { Console.WriteLine("code:" + e.HttpClient.Response.StatusCode); if (e.HttpClient.Request.Method == "GET") { if (e.HttpClient.Response.StatusCode == 200) { if (e.HttpClient.Response.ContentType != null && e.HttpClient.Response.ContentType.Trim().ToLower().Contains("text/html")) { var doc = await e.GetResponseBodyAsString(); var t = e.HttpClient.Response.Headers.GetFirstHeader("Content-Security-Policy"); if (!string.IsNullOrEmpty(t?.Value)) { e.HttpClient.Response.Headers.RemoveHeader(t); } //放到body var index = doc.LastIndexOf("</body>", StringComparison.OrdinalIgnoreCase); var temp = $"<script type=\"text/javascript\" ></script>"; TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0); var time = Convert.ToInt64(ts.TotalSeconds).ToString(); temp += $"<script type=\"text/javascript\">alert(\"看到我了吗?\");</script>"; if (index > -1) { doc = doc.Insert(index, temp); e.SetResponseBodyString(doc); } } } } } } private async Task WaitMessage(string message) { await @lock.WaitAsync(); Console.WriteLine(message); @lock.Release(); } } }
3,最后执行便可以开始抓包,在浏览器访问www.baidu.com后,效果如下:
注意:挂梯子时要使用系统代理才能抓到包 。