簡體   English   中英

通過代理(.NET)連接到IRC

[英]Connecting to IRC via a proxy (.NET)

通過.NET應用程序連接到IRC時,我希望隱藏我的IP。 我目前使用IrcDotNet庫,但它似乎不支持代理。

我對套接字沒有太多的經驗,所以我認為修改IrcDotNet比制作自己的IRC庫要容易得多。 我到處尋找用於處理可以在IrcDotNet中實現的代理連接的套接字庫。 我找到了一個稱為ProxySocket的代理,但它僅支持BeginConnect,而不支持IrcDotNet使用的新ASyncConnect方法。

為了進行分解,按喜好排序,這就是我想要的;

  1. 支持通過HTTP / SOCKS代理進行連接的IRC庫
  2. 一個套接字庫,支持通過ASyncConnect通過HTTP / SOCKS代理進行連接
  3. 有關如何擴展套接字類以支持通過ASyncConnect通過HTTP / SOCKS代理進行連接的示例代碼

我正在使用的IrcDotNet版本為0.4.1,可從https://launchpad.net/ircdotnet找到。

更新1:恐怕還是沒有運氣。 Fredrik92的回答雖然有用,但不適用於我正在使用的IrcDotNet版本(請參見上文)。

IRC.NET庫使用System.Net.Sockets命名空間中的標准Socket類。

因此,您只需在IRC.NET源代碼(@ http://ircdotnet.codeplex.com/SourceControl/latest )中修改IrcDotNet / IrcClient.cs文件即可。

您應該為啟用代理的IRC客戶端添加一個構造函數,並調用默認構造函數。

然后,您需要做的就是修改同一文件(幾乎在底部)中的Connect方法。 他們每次調用this.client.BeginConnect(..) ,都必須添加代碼以連接到代理(而不是遠程主機)。

現在,您只需要創建一個新的Connect-callback方法即可將HTTP CONNECT請求發送到代理。 閱讀來自HTTP代理的響應,然后其他所有內容都應該起作用。

在這種情況下,我會將HTTP請求作為原始ASCII字節寫入代理(而不是使用HttpWebRequest類),以便您完全控制返回的網絡流...

您應該添加某事。 像這樣對IrcClient類:

private bool useProxy = false;
private IWebProxy proxy;
private IEnumerable<Uri> proxyRemoteUris;

public IrcClient(IWebProxy proxy)
    : this()
{
   this.useProxy = true;
   this.proxy = proxy;
}

private void ProxyPerformHttpConnect(Uri remoteIrcUri)
{
  string httpConnectRequest = string.Format("CONNECT {0}:{1} HTTP/1.1\r\nHost: {2}\r\n\r\n",
    remoteIrcUri.Host, remoteIrcUri.Port, this.proxy.GetProxy(remoteIrcUri));
  byte[] httpConnectData = Encoding.ASCII.GetBytes(httpConnectRequest);

  this.stream.Write(httpConnectData, 0, httpConnectData.Length);

  bool responseReady = false;
  string responseText = string.Empty;
  // Byte-by-byte reading required, because StringReader will read more than just the HTTP response header
  do
  {
    int readByte = this.stream.ReadByte();
    if (readByte < 0)
      throw new WebException(message: null, status: WebExceptionStatus.ConnectionClosed);

    char readChar = (char)(readByte); // Only works because HTTP Headers are ASCII encoded.
    responseText += readChar;

    responseReady = responseText.EndsWith("\r\n\r\n");
  } while (!responseReady);

  int statusStart = responseText.IndexOf(' ') + 1;
  int reasonStart = responseText.IndexOf(' ', statusStart) + 1;
  int reasonEnd = responseText.IndexOfAny(new char[] { '\r', '\n'});
  HttpStatusCode responseStatus = (HttpStatusCode)(int.Parse(responseText.Substring(responseText.IndexOf(' ') + 1, length: 3)));
  if (responseStatus != HttpStatusCode.OK)
  {
    string reasonText = responseText.Substring(reasonStart, reasonEnd - reasonStart);
    if (string.IsNullOrWhiteSpace(reasonText))
      reasonText = null;
    throw new WebException(reasonText, WebExceptionStatus.ConnectFailure);
  }

  // Finished Response Header read...
}

private void ProxyConnectCallback(IAsyncResult ar)
{
  try
  {
    this.client.EndConnect(ar);
    this.stream = this.client.GetStream();

    bool proxyTunnelEstablished = false;
    WebException lastWebException = null;
    foreach (Uri remoteIrcUri in this.proxyRemoteUris)
    {
      if (this.client.Connected == false)
      {
        // Re-establish connection with proxy...
        Uri proxyUri = this.proxy.GetProxy(remoteIrcUri);
        this.client.Connect(proxyUri.Host, proxyUri.Port);
      }

      try
      {
        ProxyPerformHttpConnect(remoteIrcUri);
        proxyTunnelEstablished = true;
        break;
      }
      catch (WebException webExcept)
      {
        lastWebException = webExcept;                        
      }
    }

    if (!proxyTunnelEstablished)
    {
      OnConnectFailed(new IrcErrorEventArgs(lastWebException));
      return;
    }

    this.writer = new StreamWriter(this.stream, Encoding.Default);
    this.reader = new StreamReader(this.stream, Encoding.Default);

    HandleClientConnected((IrcRegistrationInfo)ar.AsyncState);
    this.readThread.Start();
    this.writeThread.Start();

    OnConnected(new EventArgs());
  }
  catch (Exception ex)
  {
    OnConnectFailed(new IrcErrorEventArgs(ex));
  }
}

因此,看起來IrcClient類的所有Connect方法中用於代理處理的代碼都是這樣。 像這樣:

// Code snippet to insert before the call to this.client.BeginConnect(...)
if (this.useProxy)
{
  // Assign host and port variables for EndPoint objects:
  // var host = remoteEP.Address;
  // var port = remoteEP.Port;
  this.proxyRemoteUris = new Uri[] { new Uri(string.Format("irc://{0}:{1}/", host, port)) };
  // Replace the line above with the following line in the method where an array of IP addresses is specified as a parameter
  // this.proxyRemoteUris = from ip in addresses select new Uri(string.Format("irc://{0}:{1}/", ip, port));
  Uri proxyUri = this.proxy.GetProxy(this.proxyRemoteUris.First());
  string proxyHost = proxyUri.Host;
  int proxyPort = proxyUri.Port;
  this.client.BeginConnect(proxyHost, proxyPort, ProxyConnectCallback, registrationInfo);
}
else
  // Original this.client.BeginConnect(...) call here...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM