/// <summary> /// Initializes a new instance of the <see cref="ProxyClient" /> class. /// </summary> /// <param name="client"> /// The underlaying Net.Sockets.Socket /// </param> /// <param name="parent"> /// The parent ProxyController class /// </param> public ProxyClient(Socket client, ProxyController parent) { this.SmartRequestBuffer = new byte[0]; this.SmartResponseBuffer = new byte[0]; this.lastSendingSpeedCalculationTime = this.lastReceivingSpeedCalculationTime = Environment.TickCount; this.oldSentBytes = this.oldReceivedBytes = this.ReceivedBytes = this.SentBytes = 0; if (client != null && client.ProtocolType == ProtocolType.Tcp) { this.RequestType = RequestTypes.Tcp; } else if (client != null && client.ProtocolType == ProtocolType.Udp) { this.RequestType = RequestTypes.Udp; } this.Status = StatusCodes.Connected; this.LastError = string.Empty; this.NoDataTimeOut = 60; this.IsSmartForwarderEnable = parent.SmartPear.ForwarderHttpEnable || parent.SmartPear.ForwarderHttpsEnable || parent.SmartPear.ForwarderSocksEnable; this.SendPacketSize = 1024; this.ReceivePacketSize = 8192; this.IsClosed = false; this.Controller = parent; this.UnderlyingSocket = client; if (this.UnderlyingSocket != null) { this.UnderlyingSocket.Blocking = false; this.UnderlyingSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment, true); } }
/// <summary> /// Initializes a new instance of the <see cref="DnsResolver" /> class. /// </summary> /// <param name="parent"> /// The parent proxy controller class to forward DNS requests. /// </param> public DnsResolver(ProxyController parent) { this.parent = parent; this.DnsResolverServerIp = IPAddress.Parse("8.8.4.4"); this.DnsResolverSupported = true; this.DnsResolverUdpSupported = true; }
/// <summary> /// Render the error message on the specified Proxy Client /// </summary> /// <param name="client"> /// The client. /// </param> /// <param name="title"> /// The title. /// </param> /// <param name="message"> /// The message. /// </param> /// <param name="code"> /// The HTTP code. /// </param> /// <param name="sslStream"> /// The SSL stream if any. /// </param> /// <returns> /// <see cref="bool" /> showing if the process ended successfully. /// </returns> public bool RenderError( ProxyClient client, string title, string message, HttpHeaderCode code = HttpHeaderCode.C500ServerError, SslStream sslStream = null) { try { if (client.RequestAddress == string.Empty) { return(false); } Uri url; if (!Uri.TryCreate(client.RequestAddress, UriKind.Absolute, out url)) { return(false); } bool https = false; if (url.Scheme.Equals("HTTP", StringComparison.OrdinalIgnoreCase)) { if (!this.EnableOnHttp) { return(false); } } else if (url.Scheme.Equals("HTTPS", StringComparison.OrdinalIgnoreCase) || url.Scheme.Equals("SOCKS", StringComparison.OrdinalIgnoreCase)) { if (!((this.EnableOnPort80 && url.Port == 80) || (this.EnableOnPort443 && url.Port == 443))) { return(false); } https = url.Port == 443; } else { return(false); } if (client.IsReceivingStarted || !client.IsSendingStarted) { return(false); } string html = Resources.HTTPErrorTemplate; html = html.Replace("%VERSION", Assembly.GetEntryAssembly().GetName().Version.ToString()); html = html.Replace("%TITLE", title); html = html.Replace("%MESSAGE", Common.ConvertToHtmlEntities(message)); string conString = "Not Connected"; if (client.Controller.ActiveServer != null) { conString = client.Controller.ActiveServer.ToString(); } List <string> args = new List <string>(); if (client.Controller.SmartPear.ForwarderHttpEnable) { args.Add("P:HTTP"); } if (client.Controller.SmartPear.ForwarderHttpsEnable) { args.Add("P:HTTPS"); } if (client.Controller.SmartPear.ForwarderSocksEnable && client.Controller.SmartPear.ForwarderHttpsEnable) { args.Add("P:SOCKS"); } if (args.Count > 0) { conString = args.Aggregate(conString + " (", (current, arg) => current + (" " + arg + "; ")) + ")"; } html = html.Replace("%CONSTRING", conString); string statusCode; switch (code) { case HttpHeaderCode.C200Ok: statusCode = "200 OK"; break; case HttpHeaderCode.C501NotImplemented: statusCode = "501 Not Implemented"; break; case HttpHeaderCode.C502BadGateway: statusCode = "502 Bad Gateway"; break; case HttpHeaderCode.C504GatewayTimeout: statusCode = "504 Gateway Timeout"; break; case HttpHeaderCode.C417ExpectationFailed: statusCode = "417 Expectation Failed"; break; case HttpHeaderCode.C404NotFound: statusCode = "404 Not Found"; break; default: statusCode = "500 Internal Server Error"; break; } const string NewLineSep = "\r\n"; string header = "HTTP/1.1 " + statusCode + NewLineSep + "Server: PeaRoxy Error Renderer" + NewLineSep + "Content-Length: " + html.Length + NewLineSep + "Connection: close" + NewLineSep + "Content-Type: text/html;" + NewLineSep + NewLineSep; byte[] db = Encoding.ASCII.GetBytes(header + html); if (!Common.IsSocketConnected(client.UnderlyingSocket)) { return(false); } if (https) { string certAddress = url.DnsSafeHost; if (!Common.IsIpAddress(certAddress)) { if (string.IsNullOrEmpty(certAddress)) { return(false); } } certAddress = GetCertForDomain(certAddress); if (string.IsNullOrEmpty(certAddress)) { return(false); } try { X509Certificate certificate = new X509Certificate2(certAddress, string.Empty); if (sslStream == null) { client.UnderlyingSocket.Blocking = true; Stream stream = new NetworkStream(client.UnderlyingSocket); sslStream = new SslStream(stream) { ReadTimeout = 30 * 1000, WriteTimeout = 30 * 1000 }; sslStream.AuthenticateAsServer(certificate); } sslStream.BeginWrite( db, 0, db.Length, delegate(IAsyncResult ar) { try { sslStream.EndWrite(ar); sslStream.Flush(); sslStream.Close(); client.UnderlyingSocket.Close(); } catch (Exception) { } }, null); } catch { } } else { client.UnderlyingSocket.BeginSend( db, 0, db.Length, SocketFlags.None, delegate(IAsyncResult ar) { try { client.UnderlyingSocket.EndSend(ar); client.UnderlyingSocket.Close(); } catch (Exception) { } }, null); } return(true); } catch (Exception e) { ProxyController.LogIt(e.Message + " - " + e.StackTrace); } return(false); }
internal void Accepting() { try { if (this.DnsResolverSupported && this.dnsTcpListenerSocket.Poll(0, SelectMode.SelectRead)) { ProxyClient c = new ProxyClient(this.dnsTcpListenerSocket.Accept(), this.parent) { ReceivePacketSize = this.parent .ReceivePacketSize, SendPacketSize = this.parent .SendPacketSize, NoDataTimeOut = 10, RequestType = ProxyClient .RequestTypes .Dns, IsSendingStarted = true, }; lock (this.parent.ConnectedClients) this.parent.ConnectedClients.Add(c); this.parent.ActiveServer.Clone().Establish(this.DnsResolverServerIp.ToString(), 53, c); } if (this.DnsResolverSupported && this.DnsResolverUdpSupported) { if (this.dnsUdpListenerSocket == null) { this.dnsUdpListenerSocket = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) { EnableBroadcast = true }; this.dnsUdpListenerSocket.Bind(this.localDnsIp); } try { if (this.dnsUdpListenerSocket.Poll(0, SelectMode.SelectRead)) { byte[] globalBuffer = new byte[500]; EndPoint remoteEp = new IPEndPoint(IPAddress.Any, 0); int i = this.dnsUdpListenerSocket.ReceiveFrom(globalBuffer, ref remoteEp); byte[] buffer = new byte[i + 2]; Array.Copy(globalBuffer, 0, buffer, 2, i); Task.Factory.StartNew( delegate { try { buffer[0] = (byte)Math.Floor((double)i / 256); buffer[1] = (byte)(i % 256); IPAddress ip = this.parent.Ip; // Connecting to our self on same port, But TCP if (ip.Equals(IPAddress.Any)) { ip = IPAddress.Loopback; } Socket tcpLinkForUdp = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); tcpLinkForUdp.Connect(ip, 53); tcpLinkForUdp.Send(buffer); buffer = new byte[tcpLinkForUdp.ReceiveBufferSize]; i = tcpLinkForUdp.Receive(buffer); if (i != 0) { int neededBytes = (buffer[0] * 256) + buffer[1] + 2; Array.Resize(ref buffer, Math.Max(i, neededBytes)); if (i < neededBytes) { int timeout = Environment.TickCount + 2000; int received = i; while (received < neededBytes && timeout > Environment.TickCount && Common.IsSocketConnected(tcpLinkForUdp)) { i = tcpLinkForUdp.Receive( buffer, received, buffer.Length - received, SocketFlags.None); received += i; if (i == 0) { break; } Thread.Sleep(16); } } } this.dnsUdpListenerSocket.SendTo( buffer, 2, buffer.Length - 2, SocketFlags.None, remoteEp); } catch (Exception e) { ProxyController.LogIt("DNS Resolver UDP Error: " + e.Message); } }); } } catch (Exception) { this.dnsUdpListenerSocket.Close(); this.dnsUdpListenerSocket = null; } } } catch { } }
/// <summary> /// The close method which supports mentioning a message about the reason /// </summary> /// <param name="title"> /// The title. /// </param> /// <param name="message"> /// The message. /// </param> /// <param name="code"> /// The HTTP code. /// </param> /// <param name="async"> /// Indicating if the closing process should treat the client as an asynchronous client /// </param> /// <param name="sslstream"> /// The SSL stream if any. /// </param> public void Close( string title = null, string message = null, ErrorRenderer.HttpHeaderCode code = ErrorRenderer.HttpHeaderCode.C500ServerError, bool async = false, SslStream sslstream = null) { this.Status = StatusCodes.Closing; try { if (title != null) { if (message == null) { message = "No more information."; } this.LastError = title + "\r\n" + message; } if (this.UnderlyingSocket != null) { // Testing or not if (this.LastError != string.Empty && title != null) { ProxyController.LogIt(title); } if (title == null || !this.Controller.ErrorRenderer.RenderError(this, title, message, code, sslstream)) { if (async) { byte[] db = new byte[0]; if (this.UnderlyingSocket != null) { this.UnderlyingSocket.BeginSend( db, 0, db.Length, SocketFlags.None, delegate(IAsyncResult ar) { try { this.UnderlyingSocket.Close(); // Close request connection it-self this.UnderlyingSocket.EndSend(ar); } catch (Exception) { } }, null); } } else { if (this.UnderlyingSocket != null) { this.UnderlyingSocket.Close(); } } } } } catch { } this.IsClosed = true; this.Controller.ClientDisconnected(this); }