/// <summary> /// Tries to work out whether the request came through a reverse proxy and, related to that, whether the request came from the Internet. /// </summary> /// <param name="request"></param> /// <remarks> /// Only reverse proxies that have a local address can influence this, if an Internet request comes with XFF headers they're just ignored. /// The code only checks the address of the machine that used the proxy, so if the request came through two reverse proxies on the LAN /// then it will always look like a local machine made the request. /// </remarks> private void DetermineReverseProxyAndIsInternetRequest(IRequest request) { IsInternetRequest = !IPEndPointHelper.IsLocalOrLanAddress(request.RemoteEndPoint); if (!IsInternetRequest) { var xForwardedFor = Request.Headers["X-Forwarded-For"]; if (xForwardedFor != null) { ProxyAddress = request.RemoteEndPoint.Address.ToString(); ClientAddress = xForwardedFor.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Last().Trim(); IPAddress clientIPAddress; if (IPAddress.TryParse(ClientAddress, out clientIPAddress)) { IsInternetRequest = !IPEndPointHelper.IsLocalOrLanAddress(new IPEndPoint(clientIPAddress, request.RemoteEndPoint.Port)); } else { ClientAddress = request.RemoteEndPoint.Address.ToString(); IsInternetRequest = true; } } } }
/// <summary> /// Tries to determine the true IP address of the client and the address of the proxy, if any. If the /// values have already been calculated and aren't going to change then this does nothing. /// </summary> private void DetermineClientAndProxyAddresses() { var translationBasis = String.Format("{0}-{1}", RemoteIpAddress, Headers["X-Forwarded-For"]); if (!String.Equals(translationBasis, Get <string>(EnvironmentKey.ClientIpAddressBasis))) { Set <string>(EnvironmentKey.ClientIpAddressBasis, translationBasis); var localOrLanRequest = IPEndPointHelper.IsLocalOrLanAddress(new IPEndPoint(ParseIpAddress(RemoteIpAddress), RemotePort.GetValueOrDefault())); var xff = localOrLanRequest ? Headers["X-Forwarded-For"] : null; if (!String.IsNullOrEmpty(xff)) { xff = xff.Split(',').Last().Trim(); IPAddress ipAddress; if (!IPAddress.TryParse(xff, out ipAddress)) { xff = null; } } if (String.IsNullOrEmpty(xff)) { Set <string>(EnvironmentKey.ClientIpAddress, RemoteIpAddress); Set <string>(EnvironmentKey.ProxyIpAddress, null); } else { Set <string>(EnvironmentKey.ClientIpAddress, xff); Set <string>(EnvironmentKey.ProxyIpAddress, RemoteIpAddress); } } }
public void IPEndPointHelper_IsLocalOrLanAddress_Returns_Correct_Values() { ExcelWorksheetData worksheet = new ExcelWorksheetData(TestContext); IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(worksheet.String("IPAddress")), 0); Assert.AreEqual(worksheet.Bool("Expected"), IPEndPointHelper.IsLocalOrLanAddress(endPoint)); }
/// <summary> /// Called on a background thread when a client connects. /// </summary> /// <param name="result"></param> private void IncomingTcpClient(IAsyncResult result) { TcpClient tcpClient = null; try { lock (_SyncLock) { tcpClient = _Listener == null || _Disposed ? null : _Listener.EndAcceptTcpClient(result); } } catch (SocketException) { // Exception spam } catch (ObjectDisposedException) { // Exception spam } catch (InvalidOperationException) { // Exception spam } catch (ThreadAbortException) { // We can ignore this, it'll get re-thrown automatically on the end of the try. We don't want to report it. } catch (Exception ex) { OnExceptionCaught(new EventArgs <Exception>(ex)); } if (tcpClient != null) { try { Client client = null; lock (_SyncLock) { if (_Disposed) { client = null; } else { client = new Client() { TcpClient = tcpClient, IPEndPoint = tcpClient.Client.RemoteEndPoint as IPEndPoint, }; if (client.IPEndPoint == null) { ((IDisposable)tcpClient).Dispose(); client = null; } else { tcpClient.NoDelay = IPEndPointHelper.IsLocalOrLanAddress(client.IPEndPoint); _ConnectedClients.Add(client); } } } if (client != null) { OnClientConnected(new BroadcastEventArgs(client.IPEndPoint, 0, Port, EventFormat)); } } catch (ThreadAbortException) { // We can ignore this, it'll get re-thrown automatically on the end of the try. We don't want to report it. } catch (Exception ex) { OnExceptionCaught(new EventArgs <Exception>(ex)); } } try { lock (_SyncLock) { if (_Listener != null && !_Disposed) { _Listener.BeginAcceptTcpClient(IncomingTcpClient, null); } } } catch (ThreadAbortException) { // We can ignore this, it'll get re-thrown automatically on the end of the try. We don't want to report it. } catch (Exception ex) { OnExceptionCaught(new EventArgs <Exception>(ex)); } }