为什么不用FiddlerCore?

说到FiddlerCore大家可能会比较陌生,那么它哥Fiddler就比较熟悉了;抓包、模拟低带宽、修改请求我平时比较常用。Fiddler的本质就是一个HTTP代理服务器。

FiddlerCore是Fiddler去除了UI的核心组件,可以用于二次开发。如下图所示:

Fiddler主要有以下几点感觉很别扭:

  1. API命名不规范、属性/字段混用。

    .NET中普遍采用Pascal命名规范,而Fiddler的命名就像个大杂烩。例如:public成员用字段,CONFIG类名,oSession参数名
  2. 不支持异步。所有的回调都是同步。
  3. 框架设计不合理,不支持多实例,大量使用了静态方法。所有方法都堆到了Session类中不易于扩展,起码Request/Response也得分开啊。

单就以上几点我感觉这框架完全没有设计可言,如果没有别的选择FiddlerCore我或许就将就用了,好在Github上已经有人先一步重新实现了FiddlerCore

Titanium-Web-Proxy介绍

一个跨平台、轻量级、低内存、高性能的HTTP(S)代理服务器,开发语言为C#

https://github.com/justcoding121/Titanium-Web-Proxy

功能特性

  1. 支持HTTP(S)与HTTP 1.1的大部分功能
  2. 支持redirect/block/update 请求
  3. 支持更新Response
  4. 支持HTTP承载的WebSocket
  5. Support mutual SSL authentication
  6. 完全异步的代理
  7. 支持代理授权与自动代理检测
  8. Kerberos/NTLM authentication over HTTP protocols for windows domain

使用

安装NuGet包

Install-Package Titanium.Web.Proxy

支持

  • .Net Standard 1.6或更高
  • .Net Framework 4.5或更高

设置HTTP代理

  1. var proxyServer = new ProxyServer();
  2. //locally trust root certificate used by this proxy
  3. proxyServer.TrustRootCertificate = true;
  4. //optionally set the Certificate Engine
  5. //Under Mono only BouncyCastle will be supported
  6. //proxyServer.CertificateEngine = Network.CertificateEngine.BouncyCastle;
  7. proxyServer.BeforeRequest += OnRequest;
  8. proxyServer.BeforeResponse += OnResponse;
  9. proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
  10. proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
  11. var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
  12. {
  13. //Exclude HTTPS addresses you don't want to proxy
  14. //Useful for clients that use certificate pinning
  15. //for example dropbox.com
  16. // ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" }
  17. //Use self-issued generic certificate on all HTTPS requests
  18. //Optimizes performance by not creating a certificate for each HTTPS-enabled domain
  19. //Useful when certificate trust is not required by proxy clients
  20. // GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
  21. };
  22. //An explicit endpoint is where the client knows about the existence of a proxy
  23. //So client sends request in a proxy friendly manner
  24. proxyServer.AddEndPoint(explicitEndPoint);
  25. proxyServer.Start();
  26. //Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
  27. //A transparent endpoint usually requires a network router port forwarding HTTP(S) packets or DNS
  28. //to send data to this endPoint
  29. var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
  30. {
  31. //Generic Certificate hostname to use
  32. //when SNI is disabled by client
  33. GenericCertificateName = "google.com"
  34. };
  35. proxyServer.AddEndPoint(transparentEndPoint);
  36. //proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
  37. //proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
  38. foreach (var endPoint in proxyServer.ProxyEndPoints)
  39. Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
  40. endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
  41. //Only explicit proxies can be set as system proxy!
  42. proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
  43. proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
  44. //wait here (You can use something else as a wait function, I am using this as a demo)
  45. Console.Read();
  46. //Unsubscribe & Quit
  47. proxyServer.BeforeRequest -= OnRequest;
  48. proxyServer.BeforeResponse -= OnResponse;
  49. proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
  50. proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
  51. proxyServer.Stop();

简单的请求与响应处理

  1. //To access requestBody from OnResponse handler
  2. private IDictionary<Guid, string> requestBodyHistory
  3. = new ConcurrentDictionary<Guid, string>();
  4. public async Task OnRequest(object sender, SessionEventArgs e)
  5. {
  6. Console.WriteLine(e.WebSession.Request.Url);
  7. ////read request headers
  8. var requestHeaders = e.WebSession.Request.RequestHeaders;
  9. var method = e.WebSession.Request.Method.ToUpper();
  10. if ((method == "POST" || method == "PUT" || method == "PATCH"))
  11. {
  12. //Get/Set request body bytes
  13. byte[] bodyBytes = await e.GetRequestBody();
  14. await e.SetRequestBody(bodyBytes);
  15. //Get/Set request body as string
  16. string bodyString = await e.GetRequestBodyAsString();
  17. await e.SetRequestBodyString(bodyString);
  18. //store request Body/request headers etc with request Id as key
  19. //so that you can find it from response handler using request Id
  20. requestBodyHistory[e.Id] = bodyString;
  21. }
  22. //To cancel a request with a custom HTML content
  23. //Filter URL
  24. if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
  25. {
  26. await e.Ok("<!DOCTYPE html>" +
  27. "<html><body><h1>" +
  28. "Website Blocked" +
  29. "</h1>" +
  30. "<p>Blocked by titanium web proxy.</p>" +
  31. "</body>" +
  32. "</html>");
  33. }
  34. //Redirect example
  35. if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
  36. {
  37. await e.Redirect("https://www.paypal.com");
  38. }
  39. }
  40. //Modify response
  41. public async Task OnResponse(object sender, SessionEventArgs e)
  42. {
  43. //read response headers
  44. var responseHeaders = e.WebSession.Response.ResponseHeaders;
  45. //if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
  46. if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST")
  47. {
  48. if (e.WebSession.Response.ResponseStatusCode == "200")
  49. {
  50. if (e.WebSession.Response.ContentType!=null && e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html"))
  51. {
  52. byte[] bodyBytes = await e.GetResponseBody();
  53. await e.SetResponseBody(bodyBytes);
  54. string body = await e.GetResponseBodyAsString();
  55. await e.SetResponseBodyString(body);
  56. }
  57. }
  58. }
  59. //access request body/request headers etc by looking up using requestId
  60. if(requestBodyHistory.ContainsKey(e.Id))
  61. {
  62. var requestBody = requestBodyHistory[e.Id];
  63. }
  64. }
  65. /// Allows overriding default certificate validation logic
  66. public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
  67. {
  68. //set IsValid to true/false based on Certificate Errors
  69. if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
  70. e.IsValid = true;
  71. return Task.FromResult(0);
  72. }
  73. /// Allows overriding default client certificate selection logic during mutual authentication
  74. public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
  75. {
  76. //set e.clientCertificate to override
  77. return Task.FromResult(0);
  78. }

未来路线图

  • 支持HTTP 2.0
  • 支持Socks协议

推荐一个比FiddlerCore好用的HTTP(S)代理服务器的更多相关文章

  1. 推荐一个简单、轻量、功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler定时器

    在C#WINFORM或者是ASP.NET的WEB应用程序中,根据各种定时任务的需求,比如:每天的数据统计,每小时刷新系统缓存等等,这个时候我们得应用到定时器这个东东. .NET Framework有自 ...

  2. 推荐一个实用的css工具

    后台程序员整天在和数据打交道,天天的活就是抱着mysql抠数据,如果让他去写网站的样式,就让人感觉力不从心,所以推荐一个twitter的团队开发的东西,几乎囊括了网站所需的样式,http://www. ...

  3. 前端设计师也有必要学习seo,推荐一个seo博客

    做前端设计师有一段时间了,现在越来越觉得作为一个前端设计师,必须要懂一些seo的知识. 因为公司的seo们,总是在网站做好以后,提出各种各样的网站修改的需求. 如果前端设计师,能够了解一些基本的seo ...

  4. 。求推荐一个usb集线器的购买网址

    笔记本蓝屏了,虽然后来让笔记本自己呆了好久,它冷静下来后我重新启动它,它又恢复了正常,但是我至今也没搞懂蓝屏的原因,深切地领悟到没文化不可怕,像我这样一知半解的最可怕... ------LYQ --- ...

  5. 推荐一个 angular 图像加载插件

    推荐一个简单的 Angular 图片加载插件:vgSrc,插件根据图片资源的不同加载状态,显示不同图片,亲测兼容IE-8. 使用 推荐使用 bower 加载: bash bower install v ...

  6. 推荐一个linux下的web压力测试工具神器webbench

    推荐一个linux下的web压力测试工具神器webbench2014-04-30 09:35:29   来源:   评论:0 点击:880 用多了apache的ab工具之后你就会发现ab存在很多问题, ...

  7. 推荐一个sqlce,sqllite等数据库管理工具

    推荐一个sqlce,sqllite等数据库管理工具 下载地址: http://fishcodelib.com/files/DatabaseNet4.zip 支持sqlserver,sqlce, sql ...

  8. 推荐一个百度网盘搜索工具www.sososo.me

    推荐一个百度网盘搜索工具 http://www.sososo.me

  9. 推荐一个可以直接在Visual Studio中看到complexity的插件CodeMaid

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:推荐一个可以直接在Visual Studio中看到complexity的插件CodeMaid.

随机推荐

  1. /etc/profile /etc/bashrc ~/.bash_profile ~/.bashrc ~/.bash_logout 说明及区别

    /etc/profile:此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. 并从/etc/profile.d目录的配置文件中搜集shell的设置. /etc/bashrc:为每一 ...

  2. 怎样查看当前QQ的版本号是多少

    怎样查看当前QQ的版本号是多少.. -------------- -------------

  3. 【javascript】异步编年史,从“纯回调”到Promise

    异步和分块——程序的分块执行   一开始学习javascript的时候, 我对异步的概念一脸懵逼, 因为当时百度了很多文章,但很多各种文章不负责任的把笼统的描述混杂在一起,让我对这个 JS中的重要概念 ...

  4. jumpserver V0.4.0 在CentOs7上的安装

    基于 CentOS 7 一步一步安装 Jumpserver 0.4.0 环境 系统: CentOS 7 IP: 192.168.226.128 一. 准备Python3和Python虚拟环境 1.1 ...

  5. 34、锁问题与线程queue

    上一篇随笔我们学了全局解释器锁,前面也学了互斥锁,今天学习一些与锁相关的点,例如递归锁,信号量,Event,还会学习我们已经很熟悉的队列,不过这次的队列是作为一个模块出现的. 一.同步锁 1.join ...

  6. 7_linux下PHP、Apache、Mysql服务的安装

    1.首先安装之前,要确保你的虚拟机能连上外网. Mysql: 1.yum -y install mysql   连接数据库命令行模式 2.yum install mysql-server  安装mys ...

  7. .NET 自定义Json序列化时间格式

    .NET 自定义Json序列化时间格式 Intro 和 JAVA 项目组对接,他们的接口返回的数据是一个json字符串,里面的时间有的是Unix时间戳,有的是string类型,有的还是空,默认序列化规 ...

  8. node.js后台快速搭建在阿里云(二)(pm2和nginx篇)

    前期准备 阿里云服务器 node.js pm2 express nginx linux(推荐教程:鸟哥的私房菜) 简介 嗯……我只是个前端而已 在第一部分说完了express篇. 后面继续项目的部署, ...

  9. this和super的运用

    这几天看到类在继承时会用到this和super,这里就做了一点总结,与各位共同交流,有错误请各位指正~ this this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针. this ...

  10. mybatis 一对多和多对一关联查询

    首先  数据库量表之间字段关系(没有主外键) studentmajor表的id字段对应student表里major字段 两个实体类 package com.model; import java.uti ...