http server change remote endpoint handling

master
UbitUmarov 2020-04-11 19:57:34 +01:00
parent 7ce9f890b1
commit f95925e0fd
6 changed files with 77 additions and 45 deletions

View File

@ -147,9 +147,8 @@ namespace OpenSim.Framework.Servers.HttpServer
public IPEndPoint RemoteIPEndPoint public IPEndPoint RemoteIPEndPoint
{ {
get { return _remoteIPEndPoint; } get { return _request.RemoteIPEndPoint; }
} }
private IPEndPoint _remoteIPEndPoint;
public Uri Url public Uri Url
{ {
@ -206,29 +205,6 @@ namespace OpenSim.Framework.Servers.HttpServer
if (null != req.Headers["user-agent"]) if (null != req.Headers["user-agent"])
_userAgent = 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(); // Form = new Hashtable();
// foreach (HttpInputItem item in req.Form) // foreach (HttpInputItem item in req.Form)
// { // {

View File

@ -89,6 +89,8 @@ namespace OSHttpServer
/// </summary> /// </summary>
public event EventHandler Started; public event EventHandler Started;
public IPEndPoint LocalRemoteEndPoint {get; set;}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HttpClientContext"/> class. /// Initializes a new instance of the <see cref="HttpClientContext"/> class.
/// </summary> /// </summary>
@ -105,8 +107,7 @@ namespace OSHttpServer
if (!stream.CanWrite || !stream.CanRead) if (!stream.CanWrite || !stream.CanRead)
throw new ArgumentException("Stream must be writable and readable."); throw new ArgumentException("Stream must be writable and readable.");
RemoteAddress = remoteEndPoint.Address.ToString(); LocalRemoteEndPoint = remoteEndPoint;
RemotePort = remoteEndPoint.Port.ToString();
_log = NullLogWriter.Instance; _log = NullLogWriter.Instance;
m_parser = parserFactory.CreateParser(_log); m_parser = parserFactory.CreateParser(_log);
m_parser.RequestCompleted += OnRequestCompleted; m_parser.RequestCompleted += OnRequestCompleted;
@ -185,8 +186,8 @@ namespace OSHttpServer
m_currentRequest.Method = e.HttpMethod; m_currentRequest.Method = e.HttpMethod;
m_currentRequest.HttpVersion = e.HttpVersion; m_currentRequest.HttpVersion = e.HttpVersion;
m_currentRequest.UriPath = e.UriPath; m_currentRequest.UriPath = e.UriPath;
m_currentRequest.AddHeader("remote_addr", RemoteAddress); m_currentRequest.AddHeader("remote_addr", LocalRemoteEndPoint.Address.ToString());
m_currentRequest.AddHeader("remote_port", RemotePort); m_currentRequest.AddHeader("remote_port", LocalRemoteEndPoint.Port.ToString());
FirstRequestLineReceived = true; FirstRequestLineReceived = true;
TriggerKeepalive = false; TriggerKeepalive = false;
@ -290,16 +291,6 @@ namespace OSHttpServer
set { m_stream = value; } set { m_stream = value; }
} }
/// <summary>
/// Gets or sets IP address that the client connected from.
/// </summary>
internal string RemoteAddress { get; set; }
/// <summary>
/// Gets or sets port that the client connected from.
/// </summary>
internal string RemotePort { get; set; }
/// <summary> /// <summary>
/// Disconnect from client /// Disconnect from client
/// </summary> /// </summary>

View File

@ -54,8 +54,7 @@ namespace OSHttpServer
context.Stream = stream; context.Stream = stream;
context.IsSecured = isSecured; context.IsSecured = isSecured;
context.RemotePort = endPoint.Port.ToString(); context.LocalRemoteEndPoint = endPoint;
context.RemoteAddress = endPoint.Address.ToString();
ContextTimeoutManager.StartMonitoringContext(context); ContextTimeoutManager.StartMonitoringContext(context);
m_activeContexts[context.contextID] = context; m_activeContexts[context.contextID] = context;
context.Start(); context.Start();

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Net;
using System.Text; using System.Text;
using System.Web; using System.Web;
using OSHttpServer.Exceptions; using OSHttpServer.Exceptions;
@ -31,6 +32,7 @@ namespace OSHttpServer
private Uri m_uri = null; private Uri m_uri = null;
private string m_uriPath; private string m_uriPath;
public readonly IHttpClientContext m_context; public readonly IHttpClientContext m_context;
IPEndPoint m_remoteIPEndPoint = null;
public HttpRequest(IHttpClientContext pContext) public HttpRequest(IHttpClientContext pContext)
{ {
@ -268,6 +270,33 @@ namespace OSHttpServer
{ {
Cookies = cookies; 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;
}
}
/* /*
/// <summary> /// <summary>
/// Create a response object. /// Create a response object.
@ -306,8 +335,7 @@ namespace OSHttpServer
AcceptTypes[i] = AcceptTypes[i].Trim(); AcceptTypes[i] = AcceptTypes[i].Trim();
break; break;
case "content-length": case "content-length":
int t; if (!int.TryParse(value, out int t))
if (!int.TryParse(value, out t))
throw new BadRequestException("Invalid content length."); throw new BadRequestException("Invalid content length.");
ContentLength = t; ContentLength = t;
break; //todo: maybe throw an exception break; //todo: maybe throw an exception
@ -323,11 +351,44 @@ namespace OSHttpServer
} }
break; break;
case "remote_addr": case "remote_addr":
// to prevent hacking (since it's added by IHttpClientContext before parsing).
if (m_headers[name] == null) if (m_headers[name] == null)
m_headers.Add(name, value); m_headers.Add(name, value);
break; 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": case "connection":
if (string.Compare(value, "close", true) == 0) if (string.Compare(value, "close", true) == 0)
Connection = ConnectionType.Close; Connection = ConnectionType.Close;

View File

@ -16,6 +16,8 @@ namespace OSHttpServer
/// </summary> /// </summary>
string SSLCommonName { get; } string SSLCommonName { get; }
IPEndPoint LocalRemoteEndPoint {get; set;}
/// <summary> /// <summary>
/// Using SSL or other encryption method. /// Using SSL or other encryption method.
/// </summary> /// </summary>

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Net;
using OSHttpServer.Exceptions; using OSHttpServer.Exceptions;
namespace OSHttpServer namespace OSHttpServer
@ -8,7 +9,7 @@ namespace OSHttpServer
/// <summary> /// <summary>
/// Contains server side HTTP request information. /// Contains server side HTTP request information.
/// </summary> /// </summary>
public interface IHttpRequest : ICloneable public interface IHttpRequest
{ {
/// <summary> /// <summary>
/// Gets kind of types accepted by the client. /// Gets kind of types accepted by the client.
@ -134,5 +135,7 @@ namespace OSHttpServer
/// </summary> /// </summary>
/// <param name="cookies">The cookies.</param> /// <param name="cookies">The cookies.</param>
void SetCookies(RequestCookies cookies); void SetCookies(RequestCookies cookies);
IPEndPoint RemoteIPEndPoint { get; }
} }
} }