public override void Connect(EndPoint remoteEndPoint) { if (remoteEndPoint == null) { throw new ArgumentNullException("remoteEndPoint"); } if (!(remoteEndPoint is IPEndPoint || remoteEndPoint is DnsEndPoint)) { throw new ArgumentException("remoteEndPoint must be IPEndPoint or DnsEndPoint", "remoteEndPoint"); } try { #if SILVERLIGHT && !WINDOWS_PHONE ProxyEndPoint.ConnectAsync(ClientAccessPolicyProtocol, ProcessConnect, remoteEndPoint); #elif WINDOWS_PHONE ProxyEndPoint.ConnectAsync(ProcessConnect, remoteEndPoint); #else ProxyEndPoint.ConnectAsync(ProcessConnect, remoteEndPoint); #endif } catch (Exception e) { OnException(new Exception("Failed to connect proxy server", e)); } }
/// <summary> /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// </summary> private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource) { bufferSize = server.BufferSize; bufferPool = server.BufferPool; exceptionFunc = server.ExceptionFunc; }
public override void Connect(EndPoint remoteEndPoint) { DnsEndPoint targetEndPoint = remoteEndPoint as DnsEndPoint; if (targetEndPoint == null) { OnCompleted(new ProxyEventArgs(new Exception("The argument 'remoteEndPoint' must be a DnsEndPoint"))); return; } try { #if SILVERLIGHT && !WINDOWS_PHONE ProxyEndPoint.ConnectAsync(ClientAccessPolicyProtocol, ProcessConnect, targetEndPoint); #elif WINDOWS_PHONE ProxyEndPoint.ConnectAsync(ProcessConnect, remoteEndPoint); #else ProxyEndPoint.ConnectAsync(null, ProcessConnect, targetEndPoint); #endif } catch (Exception e) { OnException(new Exception("Failed to connect proxy server", e)); } }
public TestProxyServer(bool isReverseProxy, ProxyServer upStreamProxy = null) { ProxyServer = new ProxyServer(); ProxyEndPoint explicitEndPoint = isReverseProxy ? (ProxyEndPoint) new TransparentProxyEndPoint(IPAddress.Any, 0, true) : new ExplicitProxyEndPoint(IPAddress.Any, 0, true); ProxyServer.AddEndPoint(explicitEndPoint); if (upStreamProxy != null) { ProxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = upStreamProxy.ProxyEndPoints[0].Port }; ProxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = upStreamProxy.ProxyEndPoints[0].Port }; } ProxyServer.Start(); }
protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request) : this(server, endPoint, cancellationTokenSource) { CancellationTokenSource = cancellationTokenSource; ProxyClient = new ProxyClient(); WebSession = new HttpWebClient(request); LocalEndPoint = endPoint; WebSession.ProcessId = new Lazy <int>(() => { if (RunTime.IsWindows) { var remoteEndPoint = ClientEndPoint; // If client is localhost get the process id if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address)) { var ipVersion = endPoint.IpV6Enabled ? IpVersion.Ipv6 : IpVersion.Ipv4; return(TcpHelper.GetProcessIdByLocalPort(ipVersion, remoteEndPoint.Port)); } // can't access process Id of remote request from remote machine return(-1); } throw new PlatformNotSupportedException(); }); }
public int GetProcessId(ProxyEndPoint endPoint) { if (processId.HasValue) { return(processId.Value); } if (RunTime.IsWindows) { var remoteEndPoint = (IPEndPoint)RemoteEndPoint; // If client is localhost get the process id if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address)) { processId = TcpHelper.GetProcessIdByLocalPort(endPoint.IpAddress.AddressFamily, remoteEndPoint.Port); } else { // can't access process Id of remote request from remote machine processId = -1; } return(processId.Value); } throw new PlatformNotSupportedException(); }
protected override async Task handleClient(TcpClient tcpClient, ProxyEndPoint endPoint) { tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.LingerState = new LingerOption(true, TcpTimeWaitSeconds); using (var requestState = new TRequestState()) { await InvokeClientConnectionCreateEvent(tcpClient); var clientConnection = new TcpClientConnection(this, tcpClient); requestState.server = this; requestState.clientConnection = clientConnection; if (endPoint is TransparentProxyEndPoint tep) { await handleClient(tep, requestState); } else { await handleClient((ExplicitProxyEndPoint)endPoint, requestState); } } }
/// <summary> /// Constructor to initialize the proxy /// </summary> internal SessionEventArgs(int bufferSize, ProxyEndPoint endPoint, Func <SessionEventArgs, Task> httpResponseHandler) { this.bufferSize = bufferSize; this.httpResponseHandler = httpResponseHandler; ProxyClient = new ProxyClient(); WebSession = new HttpWebClient(bufferSize); LocalEndPoint = endPoint; WebSession.ProcessId = new Lazy <int>(() => { if (RunTime.IsWindows) { var remoteEndPoint = (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint; //If client is localhost get the process id if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address)) { return(NetworkHelper.GetProcessIdFromPort(remoteEndPoint.Port, endPoint.IpV6Enabled)); } //can't access process Id of remote request from remote machine return(-1); } throw new PlatformNotSupportedException(); }); }
/// <summary> /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// </summary> private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource) { BufferSize = server.BufferSize; BufferPool = server.BufferPool; ExceptionFunc = server.ExceptionFunc; TimeLine["Session Created"] = DateTime.Now; }
/// <summary> /// Asynchronously close this connection /// </summary> /// <returns> A task representating the closing process </returns> public async Task CloseAsync() { await KickUserAsync("Proxy connection shutdown"); if (_serverEndPoint != null) { _serverEndPoint.Close (); _serverEndPoint = null; } }
/// <summary> /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// </summary> private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource) { BufferSize = server.BufferSize; BufferPool = server.BufferPool; ExceptionFunc = server.ExceptionFunc; TimeLine["Session Created"] = DateTime.Now; Challenge = Guid.NewGuid().ToString("N"); }
/// <summary> /// Listen on the given end point on local machine /// </summary> /// <param name="endPoint"></param> private void Listen(ProxyEndPoint endPoint) { endPoint.listener = new TcpListener(endPoint.IpAddress, endPoint.Port); endPoint.listener.Start(); endPoint.Port = ((IPEndPoint)endPoint.listener.LocalEndpoint).Port; // accept clients asynchronously endPoint.listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint); }
public static void AddEndPoint(ProxyEndPoint endPoint) { ProxyEndPoints.Add(endPoint); if (proxyRunning) { Listen(endPoint); } }
protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request) : this(server) { CancellationTokenSource = cancellationTokenSource; ProxyClient = new ProxyClient(); HttpClient = new HttpWebClient(request); LocalEndPoint = endPoint; HttpClient.ProcessId = new Lazy <int>(() => ProxyClient.Connection.GetProcessId(endPoint)); }
protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request?request) : this(server) { CancellationTokenSource = cancellationTokenSource; ProxyClient = new ProxyClient(); HttpClient = new HttpWebClient(request); LocalEndPoint = endPoint; EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported; HttpClient.ProcessId = new Lazy <int>(() => ProxyClient.Connection.GetProcessId(endPoint)); }
/// <summary> /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// </summary> private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, HttpClientStream clientStream, ConnectRequest?connectRequest, Request request, CancellationTokenSource cancellationTokenSource) : base(clientStream.Connection) { BufferPool = server.BufferPool; ExceptionFunc = server.ExceptionFunc; TimeLine["Session Created"] = DateTime.Now; CancellationTokenSource = cancellationTokenSource; ClientStream = clientStream; HttpClient = new HttpWebClient(connectRequest, request, new Lazy <int>(() => clientStream.Connection.GetProcessId(endPoint))); LocalEndPoint = endPoint; }
/// <summary> /// Add a proxy end point /// </summary> /// <param name="endPoint"></param> public void AddEndPoint(ProxyEndPoint endPoint) { if (ProxyEndPoints.Any(x => x.IpAddress.Equals(endPoint.IpAddress) && endPoint.Port != 0 && x.Port == endPoint.Port)) { throw new Exception("Cannot add another endpoint to same port & ip address"); } ProxyEndPoints.Add(endPoint); if (proxyRunning) { Listen(endPoint); } }
/// <summary> /// Remove a proxy end point /// Will throw error if the end point does'nt exist /// </summary> /// <param name="endPoint"></param> public void RemoveEndPoint(ProxyEndPoint endPoint) { if (ProxyEndPoints.Contains(endPoint) == false) { throw new Exception("Cannot remove endPoints not added to proxy"); } ProxyEndPoints.Remove(endPoint); if (proxyRunning) { QuitListen(endPoint); } }
/// <summary> /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// </summary> private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, TcpClientConnection clientConnection, HttpClientStream clientStream, ConnectRequest?connectRequest, Request request, CancellationTokenSource cancellationTokenSource) { BufferPool = server.BufferPool; ExceptionFunc = server.ExceptionFunc; TimeLine["Session Created"] = DateTime.Now; CancellationTokenSource = cancellationTokenSource; ClientConnection = clientConnection; ClientStream = clientStream; HttpClient = new HttpWebClient(connectRequest, request, new Lazy <int>(() => clientConnection.GetProcessId(endPoint))); LocalEndPoint = endPoint; EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported; }
/// <summary> /// 构造函数 /// </summary> private Proxy() { _proxyServer = new ProxyServer(false, false, false) { TcpTimeWaitSeconds = 10, ConnectionTimeOutSeconds = 15, ReuseSocket = false, EnableConnectionPool = false, ForwardToUpstreamGateway = false }; // 阻止生成pfx文件 _proxyServer.CertificateManager.SaveFakeCertificates = false; _proxyServer.CertificateManager.RootCertificate = new X509Certificate2(); _proxyServer.BeforeResponse += BeforeResponse; _proxyServer.BeforeRequest += BeforeRequest; _endPoint = new ExplicitProxyEndPoint(IPAddress.Any, 18888, false); _proxyServer.AddEndPoint(_endPoint); _signTimer = new Timer(Defines.SignExpireTime) { AutoReset = true, Enabled = true, Interval = Defines.SignExpireTime }; _signTimer.Elapsed += _signTimerElapsed; _ruleJObject = (JObject)JsonConvert.DeserializeObject(System.Text.Encoding.UTF8.GetString(Resource.DataProcess)); _urlList = new List <string>(); if (_ruleJObject != null) { foreach (var it in _ruleJObject) { _urlList.Add(it.Key); } } _specialUrlDict = new Dictionary <string, ProcessDelegate> { { "Index/index", GetIndex }, { "Fairy/teamFairy", TeamFairy }, { "Mission/teamMove", TeamMove }, { "Mission/startMission", StartMission } }; using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0)) { socket.Connect(Defines.NetTestIP, 65530); LocalIPAddress = socket.LocalEndPoint is IPEndPoint endPoint?endPoint.Address.ToString() : ""; } }
private async void Listen(ProxyEndPoint endPoint) { endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port); endPoint.Listener.Start(); endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port; while (true) { TcpClient tcpClient = await endPoint.Listener.AcceptTcpClientAsync(); if (tcpClient != null) { Task.Run(async() => HandleClient(tcpClient, endPoint)); } } }
public override void Connect(EndPoint remoteEndPoint) { IPEndPoint targetEndPoint = remoteEndPoint as IPEndPoint; if (targetEndPoint == null) { OnCompleted(new ProxyEventArgs(new Exception("The argument 'remoteEndPoint' must be a IPEndPoint"))); return; } try { ProxyEndPoint.ConnectAsync(null, ProcessConnect, targetEndPoint); } catch (Exception e) { OnException(new Exception("Failed to connect proxy server", e)); } }
/// <summary> /// Listen on the given end point on local machine /// </summary> /// <param name="endPoint"></param> private void Listen(ProxyEndPoint endPoint) { endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port); try { endPoint.Listener.Start(); endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port; // accept clients asynchronously endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint); } catch (SocketException ex) { var pex = new Exception($"Endpoint {endPoint} failed to start. Check inner exception and exception data for details.", ex); pex.Data.Add("ipAddress", endPoint.IpAddress); pex.Data.Add("port", endPoint.Port); throw pex; } }
public override void Connect(EndPoint remoteEndPoint) { if (remoteEndPoint == null) { throw new ArgumentNullException("remoteEndPoint"); } if (!(remoteEndPoint is IPEndPoint || remoteEndPoint is DnsEndPoint)) { throw new ArgumentException("remoteEndPoint must be IPEndPoint or DnsEndPoint", "remoteEndPoint"); } try { ProxyEndPoint.ConnectAsync(this.ProcessConnect, remoteEndPoint); } catch (Exception e) { this.OnException(new Exception("Failed to connect proxy server", e)); } }
private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint) { UpdateClientConnectionCount(true); tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000; try { if (endPoint.GetType() == typeof(TransparentProxyEndPoint)) { await HandleClient(endPoint as TransparentProxyEndPoint, tcpClient); } else { await HandleClient(endPoint as ExplicitProxyEndPoint, tcpClient); } } finally { UpdateClientConnectionCount(false); try { if (tcpClient != null) { //This line is important! //contributors please don't remove it without discussion //It helps to avoid eventual deterioration of performance due to TCP port exhaustion //due to default TCP CLOSE_WAIT timeout for 4 minutes tcpClient.LingerState = new LingerOption(true, 0); tcpClient.Dispose(); } } catch { } } }
/// <summary> /// Handle the client. /// </summary> /// <param name="tcpClient">The client.</param> /// <param name="endPoint">The proxy endpoint.</param> /// <returns>The task.</returns> private async Task handleClient(TcpClient tcpClient, ProxyEndPoint endPoint) { tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.SendBufferSize = BufferSize; tcpClient.ReceiveBufferSize = BufferSize; await InvokeConnectionCreateEvent(tcpClient, true); using (var clientConnection = new TcpClientConnection(this, tcpClient)) { if (endPoint is TransparentProxyEndPoint) { TransparentProxyEndPoint tep = endPoint as TransparentProxyEndPoint; await handleClient(tep, clientConnection); } else { await handleClient((ExplicitProxyEndPoint)endPoint, clientConnection); } } }
public override void Connect(EndPoint remoteEndPoint) { if (remoteEndPoint == null) { throw new ArgumentNullException("remoteEndPoint"); } if (!(remoteEndPoint is IPEndPoint || remoteEndPoint is DnsEndPoint)) { throw new ArgumentException("remoteEndPoint must be IPEndPoint or DnsEndPoint", "remoteEndPoint"); } //check if our hostname matches an ip address or not Match isProxyIpAddress = Regex.Match(ProxyHostName, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"); Debug.WriteLine("[PROXY] Connecting to proxy: " + ProxyHostName); if (isProxyIpAddress.Success) { Debug.WriteLine("[PROXY] endpoint is IP endpoint"); } else { Debug.WriteLine("[PROXY] endpoint is a hostname/DNS endpoint"); isProxyHostname = true; } try { //save reference to remote endpoint if we need to do back-and-forth connecting lastEndpoint = remoteEndPoint; ProxyEndPoint.ConnectAsync(null, ProcessConnect, remoteEndPoint); } catch (Exception e) { OnException(new Exception("[PROXY] Failed to connect proxy server", e)); } }
public override void Connect(EndPoint remoteEndPoint) { if (remoteEndPoint == null) { throw new ArgumentNullException("remoteEndPoint"); } if (!(remoteEndPoint is IPEndPoint || remoteEndPoint is DnsEndPoint)) { throw new ArgumentException("remoteEndPoint must be IPEndPoint or DnsEndPoint", "remoteEndPoint"); } try { //save reference to remote endpoint if we need to do back-and-forth connecting lastEndpoint = remoteEndPoint; ProxyEndPoint.ConnectAsync(null, ProcessConnect, remoteEndPoint); } catch (Exception e) { OnException(new Exception("Failed to connect proxy server", e)); } }
/// <summary> /// Constructor to initialize the proxy /// </summary> internal SessionEventArgs(RequestStateBase state, ProxyEndPoint endPoint, HttpClientStream clientStream, ConnectRequest?connectRequest, CancellationTokenSource cancellationTokenSource) : base(state, endPoint, clientStream, connectRequest, new Request(), cancellationTokenSource) { }
/// <summary> /// Quit listening on the given end point /// </summary> /// <param name="endPoint"></param> private void QuitListen(ProxyEndPoint endPoint) { endPoint.listener.Stop(); endPoint.listener.Server.Close(); endPoint.listener.Server.Dispose(); }
public ProxyHttpServer(Int32 httpPort) { _httpStack = new HttpStack(httpPort); _httpStack.RequestHandler = HandleRequest; _proxyEndPoint = new ProxyEndPoint(this); }
/// <summary> /// This is the core request handler method for a particular connection from client /// </summary> /// <param name="client"></param> /// <param name="httpCmd"></param> /// <param name="clientStream"></param> /// <param name="clientStreamReader"></param> /// <param name="clientStreamWriter"></param> /// <param name="httpsHostName"></param> /// <returns></returns> private async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream, CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string httpsHostName, ProxyEndPoint endPoint, List <HttpHeader> connectHeaders, ExternalProxy customUpStreamHttpProxy = null, ExternalProxy customUpStreamHttpsProxy = null) { TcpConnection connection = null; //Loop through each subsequest request on this particular client connection //(assuming HTTP connection is kept alive by client) while (true) { if (string.IsNullOrEmpty(httpCmd)) { Dispose(clientStream, clientStreamReader, clientStreamWriter, null); break; } var args = new SessionEventArgs(BUFFER_SIZE, HandleHttpSessionResponse); args.ProxyClient.TcpClient = client; args.WebSession.ConnectHeaders = connectHeaders; args.WebSession.ProcessId = new Lazy <int>(() => { var remoteEndPoint = (IPEndPoint)args.ProxyClient.TcpClient.Client.RemoteEndPoint; //If client is localhost get the process id if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address)) { return(NetworkHelper.GetProcessIdFromPort(remoteEndPoint.Port, endPoint.IpV6Enabled)); } //can't access process Id of remote request from remote machine return(-1); }); try { //break up the line into three components (method, remote URL & Http Version) var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3); var httpMethod = httpCmdSplit[0]; //find the request HTTP version Version httpVersion = new Version(1, 1); if (httpCmdSplit.Length == 3) { var httpVersionString = httpCmdSplit[2].ToLower().Trim(); if (httpVersionString == "http/1.0") { httpVersion = new Version(1, 0); } } //Read the request headers in to unique and non-unique header collections string tmpLine; while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync())) { var header = tmpLine.Split(ProxyConstants.ColonSplit, 2); var newHeader = new HttpHeader(header[0], header[1]); //if header exist in non-unique header collection add it there if (args.WebSession.Request.NonUniqueRequestHeaders.ContainsKey(newHeader.Name)) { args.WebSession.Request.NonUniqueRequestHeaders[newHeader.Name].Add(newHeader); } //if header is alread in unique header collection then move both to non-unique collection else if (args.WebSession.Request.RequestHeaders.ContainsKey(newHeader.Name)) { var existing = args.WebSession.Request.RequestHeaders[newHeader.Name]; var nonUniqueHeaders = new List <HttpHeader>(); nonUniqueHeaders.Add(existing); nonUniqueHeaders.Add(newHeader); args.WebSession.Request.NonUniqueRequestHeaders.Add(newHeader.Name, nonUniqueHeaders); args.WebSession.Request.RequestHeaders.Remove(newHeader.Name); } //add to unique header collection else { args.WebSession.Request.RequestHeaders.Add(newHeader.Name, newHeader); } } var httpRemoteUri = new Uri(httpsHostName == null ? httpCmdSplit[1] : (string.Concat("https://", args.WebSession.Request.Host == null ? httpsHostName : args.WebSession.Request.Host, httpCmdSplit[1]))); args.WebSession.Request.RequestUri = httpRemoteUri; args.WebSession.Request.Method = httpMethod.Trim().ToUpper(); args.WebSession.Request.HttpVersion = httpVersion; args.ProxyClient.ClientStream = clientStream; args.ProxyClient.ClientStreamReader = clientStreamReader; args.ProxyClient.ClientStreamWriter = clientStreamWriter; if (httpsHostName == null && (await CheckAuthorization(clientStreamWriter, args.WebSession.Request.RequestHeaders.Values) == false)) { Dispose(clientStream, clientStreamReader, clientStreamWriter, args); break; } PrepareRequestHeaders(args.WebSession.Request.RequestHeaders, args.WebSession); args.WebSession.Request.Host = args.WebSession.Request.RequestUri.Authority; //If user requested interception do it if (BeforeRequest != null) { Delegate[] invocationList = BeforeRequest.GetInvocationList(); Task[] handlerTasks = new Task[invocationList.Length]; for (int i = 0; i < invocationList.Length; i++) { handlerTasks[i] = ((Func <object, SessionEventArgs, Task>)invocationList[i])(null, args); } await Task.WhenAll(handlerTasks); } //if upgrading to websocket then relay the requet without reading the contents if (args.WebSession.Request.UpgradeToWebSocket) { await TcpHelper.SendRaw(BUFFER_SIZE, ConnectionTimeOutSeconds, httpRemoteUri.Host, httpRemoteUri.Port, httpCmd, httpVersion, args.WebSession.Request.RequestHeaders, args.IsHttps, SupportedSslProtocols, new RemoteCertificateValidationCallback(ValidateServerCertificate), new LocalCertificateSelectionCallback(SelectClientCertificate), clientStream, tcpConnectionFactory, UpStreamEndPoint); Dispose(clientStream, clientStreamReader, clientStreamWriter, args); break; } //construct the web request that we are going to issue on behalf of the client. await HandleHttpSessionRequestInternal(connection, args, customUpStreamHttpProxy, customUpStreamHttpsProxy, false).ConfigureAwait(false); if (args.WebSession.Request.CancelRequest) { break; } //if connection is closing exit if (args.WebSession.Response.ResponseKeepAlive == false) { break; } // read the next request httpCmd = await clientStreamReader.ReadLineAsync(); } catch (Exception e) { ExceptionFunc(new ProxyHttpException("Error occured whilst handling session request", e, args)); Dispose(clientStream, clientStreamReader, clientStreamWriter, args); break; } } if (connection != null) { //dispose connection.Dispose(); } }
internal virtual async void HandleClient() { string kickMessage = "Failed to login"; bool success = true; try { ClientRemoteInterface clientRemoteInterface = ClientRemoteInterface.Create(new NetworkStream(_networkSocket), 60); _clientEndPoint = new ProxyEndPoint(clientRemoteInterface, clientRemoteInterface.EndPoint.Version); _clientEndPoint.RemoteEndPoint = (IPEndPoint) _networkSocket.RemoteEndPoint; Packet packet = await clientRemoteInterface.ReadPacketAsync (); var listPing = packet as PlayerListPing; var handshakeRequest = packet as HandshakeRequest; if (listPing != null) // send motd { _isMotDRequest = true; if (listPing.MagicByte == 1) { //Plugin Message begins @ 1.6 AdditionalServerListInformation additionalInformation = null; try { clientRemoteInterface.EndPoint.Stream.ReadTimeout = 1; } catch (InvalidOperationException) { } try { additionalInformation = await clientRemoteInterface.ReadAdditionalServerListInformationAsync(); } catch (TimeoutException timeOut) { } additionalInformation = additionalInformation ?? new AdditionalServerListInformation { Host = _server.LocalEndPoint.Address.ToString(), Port = _server.LocalEndPoint.Port, ProtocolVersion = (byte) _server.PublicMinecraftVersion }; additionalInformation.ProtocolVersion = ProtocolInformation.MaxSupportedClientVersion < additionalInformation.ProtocolVersion ? (byte) ProtocolInformation.MaxSupportedClientVersion : additionalInformation.ProtocolVersion; additionalInformation.ProtocolVersion = ProtocolInformation.MinSupportedClientVersion > additionalInformation.ProtocolVersion ? (byte) ProtocolInformation.MinSupportedClientVersion : additionalInformation.ProtocolVersion; string response = ProtocolHelper.BuildMotDString(additionalInformation.ProtocolVersion, _server.ServerVersionName, _server.MotD, _server.ConnectedUsers, _server.MaxUsers); await KickUserAsync(response); } else { string response = ProtocolHelper.BuildMotDString(_server.MotD, _server.ConnectedUsers, _server.MaxUsers); await KickUserAsync(response); } return; } if (handshakeRequest != null) { Username = handshakeRequest.UserName; Host = handshakeRequest.Host; ClientEndPoint.ProtocolVersion = handshakeRequest.ProtocolVersion; if (handshakeRequest.ProtocolVersion < ProtocolInformation.MinSupportedClientVersion) { await KickUserAsync("Outdated Client"); return; } else if (handshakeRequest.ProtocolVersion > ProtocolInformation.MaxSupportedClientVersion) { await KickUserAsync("Outdated Server"); return; } var args = new UserEventArgs(this); _server.PluginManager.TriggerPlugin.OnPlayerConnected(args); if (args.Canceled) { await ClientEndPoint.SendPacketAsync(new DisconnectPacket {Reason = args.CancelMessage}); _networkSocket.Close (); _server.RemoveConnection(this); return; } bool onlineMode = _server.OnlineModeEnabled(this); string serverId = onlineMode ? Session.GetSessionHash () : "-"; var randomBuffer = new byte[4]; _random.NextBytes(randomBuffer); await ClientEndPoint.SendPacketAsync(new EncryptionKeyRequest { ServerId = serverId, PublicKey = AsnKeyBuilder.PublicKeyToX509(_server.RSAKeyPair). GetBytes (), VerifyToken = randomBuffer }); do { packet = await ClientEndPoint.ReceivePacketAsync (); } while (packet is KeepAlive); var encryptionKeyResponse = (EncryptionKeyResponse) packet; byte[] verification = ProtocolSecurity.RsaDecrypt( encryptionKeyResponse.VerifyToken.ToArray (), _server.RSACryptoServiceProvider, true); byte[] sharedKey = ProtocolSecurity.RsaDecrypt( encryptionKeyResponse.SharedKey.ToArray (), _server.RSACryptoServiceProvider, true); if (verification.Length != randomBuffer.Length || !verification.Zip(randomBuffer, (a, b) => a == b).All(a => a)) { await KickUserAsync("Verify token failure"); _logger.Error("Failed to login a Client, Verify token failure"); return; } await ClientEndPoint.SendPacketAsync(new EncryptionKeyResponse {SharedKey = new byte[0]}); ClientEndPoint.ConnectionKey = sharedKey; ClientEndPoint.EnableAes (); //now everything is encrypted Packet p = await ClientEndPoint.ReceivePacketAsync (); if (!(p is RespawnRequestPacket)) { await KickUserAsync("Protocol failure"); _logger.Error("Failed to login a Client, Protocol failure"); return; } string hash = ProtocolSecurity.ComputeHash( Encoding.ASCII.GetBytes(serverId), ClientEndPoint.ConnectionKey, AsnKeyBuilder.PublicKeyToX509(_server.RSAKeyPair).GetBytes ()); if (onlineMode) { bool result; try { result = await _server.CheckUserAccountAsync(this, hash); } catch (OperationCanceledException ex) { Task t = KickUserAsync(ex.Message); return; } if (!result) { await KickUserAsync("User not premium"); return; } } _logger.InfoFormat("{0}[{1}] is connected", Username, _networkSocket.RemoteEndPoint); _server.PromoteConnection(this); Packet response = await InitializeServerAsync (); var logonResponse = response as LogOnResponse; if (logonResponse != null) { EntityID = logonResponse.EntityId; } await ClientEndPoint.SendPacketAsync(response); StartClientListening (); StartServerListening (); args = new UserEventArgs(this); _server.PluginManager.TriggerPlugin.OnUserConnectedCompleted(args); args.EnsureSuccess (); } } catch (TaskCanceledException) { return; } catch (OperationCanceledException ex) { kickMessage = ex.Message; success = false; _quitMessagePosted = true; _logger.Error(string.Format("Client login aborted ({0})", Username), ex); } catch (Exception ex) { success = false; _quitMessagePosted = true; if (!string.IsNullOrEmpty(Username)) _logger.Error(string.Format("Failed to login a client ({0})", Username), ex); } if (!success) await KickUserAsync(kickMessage); }
private void UnregisterServer() { if (ServerEndPoint != null) { ServerEndPoint.PacketReceived -= ServerPacketReceived; ServerEndPoint.ConnectionLost -= ServerConnectionLost; ServerEndPoint.Close (); _serverEndPoint = null; } }
/// <summary> /// Asynchronously initialize the server side of this connection /// </summary> /// <param name="serverEndPoint"> Information of the new server this connection should connect to. </param> /// <returns> A task which returns the LogOnPacket or DisconnectPacket of the established connection. </returns> public async Task<Packet> InitializeServerAsync(RemoteServerInfo serverEndPoint) { ProxyEndPoint server = null; try { UnregisterServer (); _serverEndPoint = null; if (!string.IsNullOrEmpty(serverEndPoint.KickMessage)) { await KickUserAsync(serverEndPoint.KickMessage); throw new OperationCanceledException("User got kicked."); } if (serverEndPoint.MinecraftVersion == 0) _server.GetServerVersion(this, serverEndPoint); if (serverEndPoint.MinecraftVersion == null) { var information =await MinecraftPinger.GetServerInformationAsync(serverEndPoint.EndPoint); if((serverEndPoint.MinecraftVersion = information.ProtocolVersion) == null) throw new InvalidOperationException("Could not auto detect server version"); } var socket = new Socket(serverEndPoint.EndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp) { ReceiveBufferSize = 1024*1024 }; await socket.ConnectTaskAsync(serverEndPoint.EndPoint); server = new ProxyEndPoint( ServerRemoteInterface.Create(new NetworkStream(socket), (int)serverEndPoint.MinecraftVersion), (int)serverEndPoint.MinecraftVersion); server.RemoteEndPoint = (IPEndPoint) socket.RemoteEndPoint; var handshakeRequest = new HandshakeRequest { UserName = Username, Host = Host, ProtocolVersion = (byte) serverEndPoint.MinecraftVersion }; await server.SendPacketAsync(handshakeRequest); Packet tp = await server.ReceivePacketAsync (); if (tp is DisconnectPacket) { throw new OperationCanceledException((tp as DisconnectPacket).Reason); } var encryptionKeyRequest = tp as EncryptionKeyRequest; server.ConnectionKey = ProtocolSecurity.GenerateAes128Key (); byte[] key = ProtocolSecurity.RsaEncrypt(server.ConnectionKey, encryptionKeyRequest.PublicKey.ToArray (), false); byte[] verifyToken = ProtocolSecurity.RsaEncrypt(encryptionKeyRequest.VerifyToken.ToArray (), encryptionKeyRequest.PublicKey.ToArray (), false); var encryptionKeyResponse = new EncryptionKeyResponse { SharedKey = key, VerifyToken = verifyToken }; await server.SendPacketAsync(encryptionKeyResponse); Packet p = await server.ReceivePacketAsync (); server.EnableAes (); await server.SendPacketAsync(new RespawnRequestPacket ()); return await server.ReceivePacketAsync (); } catch (Exception ex) { _quitMessagePosted = true; _logger.Error("Could not connect to remote server", ex); throw; } finally { _serverEndPoint = server; } }