備忘録

備忘録

C#でTitanium-Web-Proxyを利用してProxyサーバを構築する方法

Ⅰ. はじめに

タイトルの通り「C#でTitanium-Web-Proxyを利用してProxyサーバを構築する方法」です。
Titanium-Web-Proxyはクロスプラットフォーム対応しています。
Websocketには対応しておらずデータをリレーするだけです。

WebSocketのプロキシサーバが必要な場合はFiddlerCoreを利用して下さい。
C# FiddlerCoreのサンプル

Ⅱ. やり方

1. Titanium-Web-Proxy をダウンロードする
Install-Package Titanium.Web.Proxy
2. サンプルプログラム
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Titanium.Web.Proxy;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models;

namespace CrossPlatformProxyServer
{
  class Program
  {
    static void Main(string[] args)
    {
      var proxy = new ProxyServer();
      proxy.CertificateManager.EnsureRootCertificate();
      proxy.CertificateManager.TrustRootCertificate(true);

      proxy.BeforeRequest += ProxyServer_BeforeRequest;
      proxy.BeforeResponse += Proxy_BeforeResponse;

      // 0.0.0.0:8008でプロキシサーバを起動する
      var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8008, true);
      proxy.AddEndPoint(explicitEndPoint);
      proxy.Start();

      // OSのプロキシ設定を変更する
      proxy.SetAsSystemHttpProxy(explicitEndPoint);
      proxy.SetAsSystemHttpsProxy(explicitEndPoint);

      // ルート証明書だけを保存する
      // var bytes = proxy.CertificateManager.RootCertificate.Export(X509ContentType.Cert);
      // File.WriteAllBytes("root-ca.cer", bytes);

      // 上位プロキシを設定する
      // proxy.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8009 };
      // proxy.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8009 };

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

      // wait here
      Console.ReadLine();

      proxy.Stop();
    }

    private static Task Proxy_BeforeResponse(object sender, SessionEventArgs e)
    {
      return Task.FromResult(0);
    }

    private static async Task ProxyServer_BeforeRequest(object sender, SessionEventArgs e)
    {
      Console.WriteLine(e.WebSession.Request.Url);

      if (e.WebSession.Request.HasBody)
      {
        // リクエストBodyを取得する
        // ※SetRequestBodyString する前に必ず GetRequestBodyAsString を呼び出す必要がある。
        var str = await e.GetRequestBodyAsString();

        // リクエストBodyを書き換える
        e.SetRequestBodyString("abc");
      }
    }
  }
}