diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs index ee6191b4c2..284fee63d3 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs @@ -147,9 +147,8 @@ namespace OpenSim.Framework.Servers.HttpServer public IPEndPoint RemoteIPEndPoint { - get { return _remoteIPEndPoint; } + get { return _request.RemoteIPEndPoint; } } - private IPEndPoint _remoteIPEndPoint; public Uri Url { @@ -206,29 +205,6 @@ namespace OpenSim.Framework.Servers.HttpServer if (null != req.Headers["user-agent"]) _userAgent = req.Headers["user-agent"]; - if (null != req.Headers["remote_addr"]) - { - try - { - IPAddress addr = IPAddress.Parse(req.Headers["remote_addr"]); - // sometimes req.Headers["remote_port"] returns a comma separated list, so use - // the first one in the list and log it - string[] strPorts = req.Headers["remote_port"].Split(new char[] { ',' }); - if (strPorts.Length > 1) - { - _log.ErrorFormat("[OSHttpRequest]: format exception on addr/port {0}:{1}, ignoring", - req.Headers["remote_addr"], req.Headers["remote_port"]); - } - int port = Int32.Parse(strPorts[0]); - _remoteIPEndPoint = new IPEndPoint(addr, port); - } - catch (FormatException) - { - _log.ErrorFormat("[OSHttpRequest]: format exception on addr/port {0}:{1}, ignoring", - req.Headers["remote_addr"], req.Headers["remote_port"]); - } - } - // Form = new Hashtable(); // foreach (HttpInputItem item in req.Form) // { diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs index f6eb85da5d..338faaf1a3 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs @@ -89,6 +89,8 @@ namespace OSHttpServer /// public event EventHandler Started; + public IPEndPoint LocalRemoteEndPoint {get; set;} + /// /// Initializes a new instance of the class. /// @@ -105,8 +107,7 @@ namespace OSHttpServer if (!stream.CanWrite || !stream.CanRead) throw new ArgumentException("Stream must be writable and readable."); - RemoteAddress = remoteEndPoint.Address.ToString(); - RemotePort = remoteEndPoint.Port.ToString(); + LocalRemoteEndPoint = remoteEndPoint; _log = NullLogWriter.Instance; m_parser = parserFactory.CreateParser(_log); m_parser.RequestCompleted += OnRequestCompleted; @@ -185,8 +186,8 @@ namespace OSHttpServer m_currentRequest.Method = e.HttpMethod; m_currentRequest.HttpVersion = e.HttpVersion; m_currentRequest.UriPath = e.UriPath; - m_currentRequest.AddHeader("remote_addr", RemoteAddress); - m_currentRequest.AddHeader("remote_port", RemotePort); + m_currentRequest.AddHeader("remote_addr", LocalRemoteEndPoint.Address.ToString()); + m_currentRequest.AddHeader("remote_port", LocalRemoteEndPoint.Port.ToString()); FirstRequestLineReceived = true; TriggerKeepalive = false; @@ -290,16 +291,6 @@ namespace OSHttpServer set { m_stream = value; } } - /// - /// Gets or sets IP address that the client connected from. - /// - internal string RemoteAddress { get; set; } - - /// - /// Gets or sets port that the client connected from. - /// - internal string RemotePort { get; set; } - /// /// Disconnect from client /// diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpContextFactory.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpContextFactory.cs index 8c5fb2c328..6937aa8e3e 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpContextFactory.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpContextFactory.cs @@ -54,8 +54,7 @@ namespace OSHttpServer context.Stream = stream; context.IsSecured = isSecured; - context.RemotePort = endPoint.Port.ToString(); - context.RemoteAddress = endPoint.Address.ToString(); + context.LocalRemoteEndPoint = endPoint; ContextTimeoutManager.StartMonitoringContext(context); m_activeContexts[context.contextID] = context; context.Start(); diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequest.cs index 96f55d2ca6..9a25402048 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Specialized; using System.IO; +using System.Net; using System.Text; using System.Web; using OSHttpServer.Exceptions; @@ -31,6 +32,7 @@ namespace OSHttpServer private Uri m_uri = null; private string m_uriPath; public readonly IHttpClientContext m_context; + IPEndPoint m_remoteIPEndPoint = null; public HttpRequest(IHttpClientContext pContext) { @@ -268,6 +270,33 @@ namespace OSHttpServer { Cookies = cookies; } + + public IPEndPoint RemoteIPEndPoint + { + get + { + if(m_remoteIPEndPoint == null) + { + string addr = m_headers["x-forwarded-for"]; + if(!string.IsNullOrEmpty(addr)) + { + int port = m_context.LocalRemoteEndPoint.Port; + try + { + m_remoteIPEndPoint = new IPEndPoint(IPAddress.Parse(addr), port); + } + catch + { + m_remoteIPEndPoint = null; + } + } + } + if (m_remoteIPEndPoint == null) + m_remoteIPEndPoint = m_context.LocalRemoteEndPoint; + + return m_remoteIPEndPoint; + } + } /* /// /// Create a response object. @@ -306,8 +335,7 @@ namespace OSHttpServer AcceptTypes[i] = AcceptTypes[i].Trim(); break; case "content-length": - int t; - if (!int.TryParse(value, out t)) + if (!int.TryParse(value, out int t)) throw new BadRequestException("Invalid content length."); ContentLength = t; break; //todo: maybe throw an exception @@ -323,11 +351,44 @@ namespace OSHttpServer } break; case "remote_addr": - // to prevent hacking (since it's added by IHttpClientContext before parsing). if (m_headers[name] == null) m_headers.Add(name, value); break; + case "forwarded": + string[] parts = value.Split(new char[]{';'}); + string addr = string.Empty; + for(int i = 0; i < parts.Length; ++i) + { + string s = parts[i].TrimStart(); + if(s.Length < 10) + continue; + if(s.StartsWith("for", StringComparison.InvariantCultureIgnoreCase)) + { + int indx = s.IndexOf("=", 3); + if(indx < 0 || indx >= s.Length - 1) + continue; + s = s.Substring(indx); + addr = s.Trim(); + } + } + if(addr.Length > 7) + { + m_headers.Add("x-forwarded-for", addr); + } + break; + case "x-forwarded-for": + if (value.Length > 7) + { + string[] xparts = value.Split(new char[]{','}); + if(xparts.Length > 0) + { + string xs = xparts[0].Trim(); + if(xs.Length > 7) + m_headers.Add("x-forwarded-for", xs); + } + } + break; case "connection": if (string.Compare(value, "close", true) == 0) Connection = ConnectionType.Close; diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpClientContext.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpClientContext.cs index 2dc11e19d4..99ae8d7dba 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpClientContext.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpClientContext.cs @@ -16,6 +16,8 @@ namespace OSHttpServer /// string SSLCommonName { get; } + IPEndPoint LocalRemoteEndPoint {get; set;} + /// /// Using SSL or other encryption method. /// diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpRequest.cs index 36525828c0..5d43aa55b7 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpRequest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Specialized; using System.IO; +using System.Net; using OSHttpServer.Exceptions; namespace OSHttpServer @@ -8,7 +9,7 @@ namespace OSHttpServer /// /// Contains server side HTTP request information. /// - public interface IHttpRequest : ICloneable + public interface IHttpRequest { /// /// Gets kind of types accepted by the client. @@ -134,5 +135,7 @@ namespace OSHttpServer /// /// The cookies. void SetCookies(RequestCookies cookies); + + IPEndPoint RemoteIPEndPoint { get; } } } \ No newline at end of file