推薦一個比FiddlerCore好用的HTTP(S)代理伺服器

来源:http://www.cnblogs.com/mondol/archive/2017/09/22/7577587.html
-Advertisement-
Play Games

為什麼不用FiddlerCore? 說到FiddlerCore大家可能會比較陌生,那麼它哥Fiddler就比較熟悉了;抓包、模擬低帶寬、修改請求我平時比較常用。Fiddler的本質就是一個HTTP代理伺服器。 FiddlerCore是Fiddler去除了UI的核心組件,可以用於二次開發。如下圖所示: ...


為什麼不用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代理

var proxyServer = new ProxyServer();

//locally trust root certificate used by this proxy 
proxyServer.TrustRootCertificate = true;

//optionally set the Certificate Engine
//Under Mono only BouncyCastle will be supported
//proxyServer.CertificateEngine = Network.CertificateEngine.BouncyCastle;

proxyServer.BeforeRequest += OnRequest;
proxyServer.BeforeResponse += OnResponse;
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;


var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
{
//Exclude HTTPS addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example dropbox.com
// ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" }

//Use self-issued generic certificate on all HTTPS requests
//Optimizes performance by not creating a certificate for each HTTPS-enabled domain
//Useful when certificate trust is not required by proxy clients
// GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
};

//An explicit endpoint is where the client knows about the existence of a proxy
//So client sends request in a proxy friendly manner
proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.Start();

//Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
//A transparent endpoint usually requires a network router port forwarding HTTP(S) packets or DNS
//to send data to this endPoint
var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
{
    //Generic Certificate hostname to use
    //when SNI is disabled by client
    GenericCertificateName = "google.com"
};

proxyServer.AddEndPoint(transparentEndPoint);

//proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };

foreach (var endPoint in proxyServer.ProxyEndPoints)
Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
    endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);

//Only explicit proxies can be set as system proxy!
proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);

//wait here (You can use something else as a wait function, I am using this as a demo)
Console.Read();

//Unsubscribe & Quit
proxyServer.BeforeRequest -= OnRequest;
proxyServer.BeforeResponse -= OnResponse;
proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;

proxyServer.Stop();

簡單的請求與響應處理

//To access requestBody from OnResponse handler
private IDictionary<Guid, string> requestBodyHistory 
        = new ConcurrentDictionary<Guid, string>();

public async Task OnRequest(object sender, SessionEventArgs e)
{
    Console.WriteLine(e.WebSession.Request.Url);

    ////read request headers
    var requestHeaders = e.WebSession.Request.RequestHeaders;

    var method = e.WebSession.Request.Method.ToUpper();
    if ((method == "POST" || method == "PUT" || method == "PATCH"))
    {
    //Get/Set request body bytes
    byte[] bodyBytes = await e.GetRequestBody();
    await e.SetRequestBody(bodyBytes);

    //Get/Set request body as string
    string bodyString = await e.GetRequestBodyAsString();
    await e.SetRequestBodyString(bodyString);
    
    //store request Body/request headers etc with request Id as key
    //so that you can find it from response handler using request Id
    requestBodyHistory[e.Id] = bodyString;
    }

    //To cancel a request with a custom HTML content
    //Filter URL
    if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
    {
    await e.Ok("<!DOCTYPE html>" +
          "<html><body><h1>" +
          "Website Blocked" +
          "</h1>" +
          "<p>Blocked by titanium web proxy.</p>" +
          "</body>" +
          "</html>");
    }
    //Redirect example
    if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
    {
    await e.Redirect("https://www.paypal.com");
    }
}

//Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
{
    //read response headers
    var responseHeaders = e.WebSession.Response.ResponseHeaders;

    //if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
    if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST")
    {
    if (e.WebSession.Response.ResponseStatusCode == "200")
    {
        if (e.WebSession.Response.ContentType!=null && e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html"))
        {
        byte[] bodyBytes = await e.GetResponseBody();
        await e.SetResponseBody(bodyBytes);

        string body = await e.GetResponseBodyAsString();
        await e.SetResponseBodyString(body);
        }
    }
    }
    
    //access request body/request headers etc by looking up using requestId
    if(requestBodyHistory.ContainsKey(e.Id))
    {
    var requestBody = requestBodyHistory[e.Id];
    }
}

/// Allows overriding default certificate validation logic
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
    //set IsValid to true/false based on Certificate Errors
    if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
    e.IsValid = true;

    return Task.FromResult(0);
}

/// Allows overriding default client certificate selection logic during mutual authentication
public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
{
    //set e.clientCertificate to override
    return Task.FromResult(0);
}

未來路線圖

  • 支持HTTP 2.0
  • 支持Socks協議

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  •   小編以前寫過一篇軟體的源碼編譯安裝,今天小編再給大家帶來一篇內核的編譯安裝。   今天,就以centos7 編譯安裝最新版本4.13.2 內核為例,給大家詳解。編譯安裝之前,檢查一下自己的磁碟空間,大約需10G左右。 一、去官網(www.kernel.or ...
  • 現已進入刷臉的時代,例如,人臉支付、人臉識別的門禁、人流監控等等。如何在Firefly開源板上快速搭建DEMO,並快速產品化?為了讓更多產品可以用上人臉識別技術,Firefly推出了一款高性能人臉識別SDK。此SDK的人臉識別的演算法,運行效率高,識別精確度高,性能優異,可以直接應用於商業產品。 下文 ...
  • 原文發表於cu:2016-08-25 參考文檔: 本文針對Nginx幾個常用特性做簡單驗證(高手請略過),通過簡單的驗證熟悉配置。 一.環境準備 1. 操作系統 CentOS-7-x86_64-Everything-1511 2. Nginx版本 Nginx-1.11.3: http://nginx ...
  • 伺服器:提供計算服務的設備。它是網路環境中的高性能電腦,它偵聽網路上的其他電腦(客戶端)提交的服務請求,並提供相應的服務。 伺服器是指管理和傳輸信息的一種電腦系統。 例如:網路游戲, 100個人同時線上,就代表有100個"客戶端", 這100個人游戲時所產生的數據變化,就傳輸到伺服器上計算並存 ...
  • 入手了Firefly-RK3288的開發板,自己從零開始搭建編譯環境開荒第一步:安裝Ubuntu12.04,使用安裝盤安裝(安裝的過程就不詳寫了,下麵貼圖) 安裝完後,更新ubuntu 第二步:從官網上下載SDK,進行編譯環境的安裝下載SDK有兩種方式,一是下載壓縮包,二是通過git下載。我選擇了下 ...
  • 第1章 linux文件屬性相關 1.1 linux文件屬性 1.2 磁碟的使用過程 1、磁碟(房子) 2、分區(劃分隔斷) 3、格式化創建文件系統(裝修) 4、掛載(安裝門窗) 5、存放文件(住人) 1、磁碟(房子) 2、分區(劃分隔斷) 3、格式化創建文件系統(裝修) 4、掛載(安裝門窗) 5、存 ...
  • 前言 1.為什麼要建域 工作組的分散管理模式不適合大型的網路環境下工作,域模式就是針對大型的網路管理需求設計的,就是共用用戶賬號,電腦賬號和安全策略的電腦集合。域中集中存儲用戶賬號的電腦就是域控器,域中用戶賬號, 電腦賬號和安全策略被存儲在域控制器上一個名為Active Directory的 ...
  • /// /// 獲取功能變數名稱的頂級功能變數名稱 /// /// /// public static string GetTopDomainName(string domain) { //https://www.safsd.asdfasdf.baidu.com.cn/ssssd... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...