/// <summary> /// IP end point format: "IP:Port number". /// IPV6 formats: [xx:xx:xx:xx:xx:xx:xx:xx]:port number, [xx:xx:xx:xx:xx:xx:xx:xx], xx:xx:xx:xx:xx:xx:xx:xx. /// IPV4 formats: x.x.x.x:port number, x.x.x.x. /// Extract IP address from "IP:Port number" end point format. /// </summary> private static string ExtractIpAddress(string endPoint) { IPAddress ipAddress = null; if (IPEndPointParser.TryParse(endPoint, out IPEndPoint ipEndPoint)) { ipAddress = ipEndPoint.Address; } return(ipAddress?.ToString()); }
public void TestInvalid() { IPEndPoint ep; Assert.False(IPEndPointParser.TryParse(null, out ep)); Assert.False(IPEndPointParser.TryParse("", out ep)); Assert.False(IPEndPointParser.TryParse("132", out ep)); Assert.False(IPEndPointParser.TryParse("300.0.0.1:1000", out ep)); Assert.False(IPEndPointParser.TryParse("gggg::1", out ep)); Assert.False(IPEndPointParser.TryParse("127.0.0.1:-1", out ep)); Assert.False(IPEndPointParser.TryParse("::1:70000", out ep)); }
public IPEndPoint EndPoint() { if (string.IsNullOrWhiteSpace(Host)) { return(null); } if (IPEndPointParser.TryParse(Host, out var endpoint)) { return(endpoint); } return(null); }
public void Should_TryParse() { IPEndPoint res; IPEndPointParser.TryParse("127.0.0.1", out res).Should().BeTrue(); res.Should().BeEquivalentTo(new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 0)); IPEndPointParser.TryParse("192.168.1.10:80", out res).Should().BeTrue(); res.Should().BeEquivalentTo(new IPEndPoint(new IPAddress(new byte[] { 192, 168, 1, 10 }), 80)); var ipV6 = "2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d"; var ipV6Bytes = new byte[] { 32, 1, 13, 184, 17, 163, 9, 215, 31, 52, 138, 46, 7, 160, 118, 93 }; IPEndPointParser.TryParse(ipV6, out res).Should().BeTrue(); res.Should().BeEquivalentTo(new IPEndPoint(new IPAddress(ipV6Bytes), 0)); IPEndPointParser.TryParse($"[{ipV6}]", out res).Should().BeTrue(); res.Should().BeEquivalentTo(new IPEndPoint(new IPAddress(ipV6Bytes), 0)); IPEndPointParser.TryParse($"[{ipV6}]:80", out res).Should().BeTrue(); res.Should().BeEquivalentTo(new IPEndPoint(new IPAddress(ipV6Bytes), 80)); }
public void ApplyForwarders(HttpContext context) { // Gather expected headers. Enabled headers must have the same number of entries. string[] forwardedFor = null, forwardedProto = null, forwardedHost = null; bool checkFor = false, checkProto = false, checkHost = false; int entryCount = 0; if ((_options.ForwardedHeaders & ForwardedHeaders.XForwardedFor) == ForwardedHeaders.XForwardedFor) { checkFor = true; forwardedFor = context.Request.Headers.GetCommaSeparatedValues(XForwardedForHeaderName); entryCount = Math.Max(forwardedFor.Length, entryCount); } if ((_options.ForwardedHeaders & ForwardedHeaders.XForwardedProto) == ForwardedHeaders.XForwardedProto) { checkProto = true; forwardedProto = context.Request.Headers.GetCommaSeparatedValues(XForwardedProtoHeaderName); if (_options.RequireHeaderSymmetry && checkFor && forwardedFor.Length != forwardedProto.Length) { _logger.LogDebug(1, "Parameter count mismatch between X-Forwarded-For and X-Forwarded-Proto."); return; } entryCount = Math.Max(forwardedProto.Length, entryCount); } if ((_options.ForwardedHeaders & ForwardedHeaders.XForwardedHost) == ForwardedHeaders.XForwardedHost) { checkHost = true; forwardedHost = context.Request.Headers.GetCommaSeparatedValues(XForwardedHostHeaderName); if (_options.RequireHeaderSymmetry && ((checkFor && forwardedFor.Length != forwardedHost.Length) || (checkProto && forwardedProto.Length != forwardedHost.Length))) { _logger.LogDebug(1, "Parameter count mismatch between X-Forwarded-Host and X-Forwarded-For or X-Forwarded-Proto."); return; } entryCount = Math.Max(forwardedHost.Length, entryCount); } // Apply ForwardLimit, if any if (_options.ForwardLimit.HasValue && entryCount > _options.ForwardLimit) { entryCount = _options.ForwardLimit.Value; } // Group the data together. var sets = new SetOfForwarders[entryCount]; for (int i = 0; i < sets.Length; i++) { // They get processed in reverse order, right to left. var set = new SetOfForwarders(); if (checkFor && i < forwardedFor.Length) { set.IpAndPortText = forwardedFor[forwardedFor.Length - i - 1]; } if (checkProto && i < forwardedProto.Length) { set.Scheme = forwardedProto[forwardedProto.Length - i - 1]; } if (checkHost && i < forwardedHost.Length) { set.Host = forwardedHost[forwardedHost.Length - i - 1]; } sets[i] = set; } // Gather initial values var connection = context.Connection; var request = context.Request; var currentValues = new SetOfForwarders() { RemoteIpAndPort = connection.RemoteIpAddress != null ? new IPEndPoint(connection.RemoteIpAddress, connection.RemotePort) : null, // Host and Scheme initial values are never inspected, no need to set them here. }; var checkKnownIps = _options.KnownNetworks.Count > 0 || _options.KnownProxies.Count > 0; bool applyChanges = false; int entriesConsumed = 0; for ( ; entriesConsumed < sets.Length; entriesConsumed++) { var set = sets[entriesConsumed]; if (checkFor) { // For the first instance, allow remoteIp to be null for servers that don't support it natively. if (currentValues.RemoteIpAndPort != null && checkKnownIps && !CheckKnownAddress(currentValues.RemoteIpAndPort.Address)) { // Stop at the first unknown remote IP, but still apply changes processed so far. _logger.LogDebug(1, $"Unknown proxy: {currentValues.RemoteIpAndPort}"); break; } IPEndPoint parsedEndPoint; if (IPEndPointParser.TryParse(set.IpAndPortText, out parsedEndPoint)) { applyChanges = true; set.RemoteIpAndPort = parsedEndPoint; currentValues.IpAndPortText = set.IpAndPortText; currentValues.RemoteIpAndPort = set.RemoteIpAndPort; } else if (_options.RequireHeaderSymmetry) { _logger.LogDebug(2, $"Failed to parse forwarded IPAddress: {currentValues.IpAndPortText}"); return; } } if (checkProto) { if (!string.IsNullOrEmpty(set.Scheme)) { applyChanges = true; currentValues.Scheme = set.Scheme; } else if (_options.RequireHeaderSymmetry) { _logger.LogDebug(3, $"Failed to parse forwarded scheme: {set.Scheme}"); return; } } if (checkHost) { if (!string.IsNullOrEmpty(set.Host)) { applyChanges = true; currentValues.Host = set.Host; } else if (_options.RequireHeaderSymmetry) { _logger.LogDebug(4, $"Failed to parse forwarded host: {set.Host}"); return; } } } if (applyChanges) { if (checkFor && currentValues.RemoteIpAndPort != null) { if (connection.RemoteIpAddress != null) { // Save the original request.Headers[XOriginalForName] = new IPEndPoint(connection.RemoteIpAddress, connection.RemotePort).ToString(); } if (forwardedFor.Length > entriesConsumed) { // Truncate the consumed header values request.Headers[XForwardedForHeaderName] = forwardedFor.Take(forwardedFor.Length - entriesConsumed).ToArray(); } else { // All values were consumed request.Headers.Remove(XForwardedForHeaderName); } connection.RemoteIpAddress = currentValues.RemoteIpAndPort.Address; connection.RemotePort = currentValues.RemoteIpAndPort.Port; } if (checkProto && currentValues.Scheme != null) { // Save the original request.Headers[XOriginalProtoName] = request.Scheme; if (forwardedProto.Length > entriesConsumed) { // Truncate the consumed header values request.Headers[XForwardedProtoHeaderName] = forwardedProto.Take(forwardedProto.Length - entriesConsumed).ToArray(); } else { // All values were consumed request.Headers.Remove(XForwardedProtoHeaderName); } request.Scheme = currentValues.Scheme; } if (checkHost && currentValues.Host != null) { // Save the original request.Headers[XOriginalHostName] = request.Host.ToString(); if (forwardedHost.Length > entriesConsumed) { // Truncate the consumed header values request.Headers[XForwardedHostHeaderName] = forwardedHost.Take(forwardedHost.Length - entriesConsumed).ToArray(); } else { // All values were consumed request.Headers.Remove(XForwardedHostHeaderName); } request.Host = HostString.FromUriComponent(currentValues.Host); } } }
public virtual Url parse(string url) { if (string.IsNullOrWhiteSpace(url)) { throw new ArgumentException("Illegal format address string [" + url + "], should not be blank! "); } Url parsedUrl = tryGet(url); if (null != parsedUrl) { return(parsedUrl); } IPAddress ip = null; int port = 0; Properties properties = null; int size = url.Length; int pos = 0; //for (int i = 0; i < size; ++i) //{ // if (RemotingAddressParser_Fields.COLON == url[i]) // { // ip = url.Substring(pos, i - pos); // pos = i; // // should not end with COLON // if (i == size - 1) // { // throw new ArgumentException("Illegal format address string [" + url + "], should not end with COLON[:]! "); // } // break; // } // // must have one COLON // if (i == size - 1) // { // throw new ArgumentException("Illegal format address string [" + url + "], must have one COLON[:]! "); // } //} for (int i = 0; i < size; ++i) { if (RemotingAddressParser_Fields.QUES == url[i]) { var ipEndPointString = url.Substring(pos, i - pos); IPEndPointParser.TryParse(ipEndPointString, out var ipEndPoint); ip = ipEndPoint.Address; port = ipEndPoint.Port; pos = i; if (i == size - 1) { // should not end with QUES throw new ArgumentException("Illegal format address string [" + url + "], should not end with QUES[?]! "); } break; } // end without a QUES if (i == size - 1) { var ipEndPointString = url.Substring(pos, i - pos + 1); var ipOrHostAndPortSplitIndex = ipEndPointString.LastIndexOf(':'); var ipOrHost = ipEndPointString.Substring(0, ipOrHostAndPortSplitIndex); var portString = ipEndPointString.Substring(ipOrHostAndPortSplitIndex + 1); if (int.TryParse(portString, out var portParsed)) { port = portParsed; } else { throw new ArgumentException("Illegal format address string [" + url + "], must have a valid port! "); } if (port <= 0) { throw new ArgumentException("Illegal format address string [" + url + "], must have a valid port! "); } if (IPAddress.TryParse(ipOrHost, out var ipAddress)) { ip = ipAddress; } else { var addresses = Dns.GetHostAddresses(ipOrHost); if (addresses.Length == 0) { throw new ArgumentException("Unable to retrieve address from specified host name!"); } ip = addresses[0]; } pos = size; } } if (pos < (size - 1)) { properties = new Properties(); while (pos < (size - 1)) { string key = null; string value = null; for (int i = pos; i < size; ++i) { if (RemotingAddressParser_Fields.EQUAL == url[i]) { key = url.Substring(pos + 1, i - (pos + 1)); pos = i; if (i == size - 1) { // should not end with EQUAL throw new ArgumentException("Illegal format address string [" + url + "], should not end with EQUAL[=]! "); } break; } if (i == size - 1) { // must have one EQUAL throw new ArgumentException("Illegal format address string [" + url + "], must have one EQUAL[=]! "); } } for (int i = pos; i < size; ++i) { if (RemotingAddressParser_Fields.AND == url[i]) { value = url.Substring(pos + 1, i - (pos + 1)); pos = i; if (i == size - 1) { // should not end with AND throw new ArgumentException("Illegal format address string [" + url + "], should not end with AND[&]! "); } break; } // end without more AND if (i == size - 1) { value = url.Substring(pos + 1, i + 1 - (pos + 1)); pos = size; } } properties.put(key, value); } } parsedUrl = new Url(url, ip, port, properties); initUrlArgs(parsedUrl); Url.parsedUrls.AddOrUpdate(url, new SoftReference(parsedUrl), (key, oldValue) => new SoftReference(parsedUrl)); return(parsedUrl); }