HttpWebRequest
は SOCKS プロキシをサポートしていないため、長い調査の結果、WebRequest
( SocksHttpWebRequestWebClient
のように車輪を再発明することなく) SOCKS サポートを追加する最良の方法は、着信要求をに転送する一時的な HTTP プロキシを作成することであると判断しました。 SOCKS プロキシ。
HTTP リクエストの転送は簡単で、魅力的に機能します。
HTTPS リクエストの転送も、理論的には簡単です。
は
HttpWebRequest
HTTP プロキシに接続し、以下を送信します。CONNECT google.com:443 HTTP/1.0 Host: google.com
SOCKS プロキシ経由で接続し
google.com:443
、クライアントに以下を送り返します。HTTP/1.0 200 Tunnel established
このドキュメントによると、この時点で、ストリーム間のすべてのバイトをコピーし、一方が接続を閉じると、もう一方も閉じます。
ただし、あるものNetworkStream
から別のものへのコピーは、期待どおりに機能しないようです。ある時点で、Read()
明らかな理由もなくハングしているように見えます。タイムアウトを設定すると、タイムアウトの大きさに関係なく、証明書エラーが発生します。
私が現在使用しているコードの簡素化されたバージョン:
/// <summary>
/// In theory, forwards any incoming bytes from one stream to another.
/// </summary>
/// <param name="httpProxyStream">The HTTP proxy, which we opened for <code>HttpWebRequest</code>.</param>
/// <param name="socksProxyStream">The SOCKS proxy, which we connect to and forward the traffic from the HTTP proxy.</param>
private void TunnelRequest(NetworkStream httpProxyStream, NetworkStream socksProxyStream)
{
while (true)
{
try
{
if (httpProxyStream.DataAvailable)
{
CopyStreamToStream(httpProxyStream, socksProxyStream);
}
if (socksProxyStream.DataAvailable)
{
CopyStreamToStream(socksProxyStream, httpProxyStream);
}
}
catch
{
break;
}
}
}
/// <summary>
/// Copies the first stream's content from the current position to the second stream.
/// </summary>
/// <param name="source">The source stream.</param>
/// <param name="destionation">The destionation stream.</param>
/// <param name="flush">if set to <c>true</c>, <c>Flush()</c> will be called on the destination stream after finish.</param>
/// <param name="bufferLength">Length of the buffer.</param>
public static void CopyStreamToStream(Stream source, Stream destionation, bool flush = true, int bufferLength = 4096)
{
var buffer = new byte[bufferLength];
while (true)
{
int i;
try
{
i = source.Read(buffer, 0, bufferLength);
}
catch
{
break;
}
if (i == 0)
{
break;
}
destionation.Write(buffer, 0, i);
}
if (flush)
{
destionation.Flush();
}
}
完全なクラスはここで入手できます: HttpToSocks.cs
私は今、このコードに何日もこだわっています。タスクはとても簡単ですが、うまくいきません. 私が正気を取り戻すのを手伝ってください.
編集:これは私の最大の行ではないことは承知していwhile(true)
ますが、多くのバリエーションの後、途中で終了しないようにコードに残っているため、証明書エラーが発生します。
編集 2:問題は修正されました。興味のある方は、完全なクラスをgit リポジトリで入手できます。