From 4f80ceaf755c26d243b479b93c230b1ebd29de5d Mon Sep 17 00:00:00 2001 From: Shreyas Zare Date: Sat, 4 May 2019 12:46:20 +0530 Subject: [PATCH] DnsWebService: SendError() code refactoring done. Implemented `X-Real-IP` support when using reverse proxy on private IP address. Set IgnoreWriteExceptions option for HttpListener. --- DnsServerCore/DnsWebService.cs | 87 +++++++++++++++------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/DnsServerCore/DnsWebService.cs b/DnsServerCore/DnsWebService.cs index 75168fbb..5e2ab357 100644 --- a/DnsServerCore/DnsWebService.cs +++ b/DnsServerCore/DnsWebService.cs @@ -207,7 +207,7 @@ namespace DnsServerCore if (!path.StartsWith("/")) { - Send404(response); + SendError(response, 404); return; } @@ -436,7 +436,7 @@ namespace DnsServerCore { if (!IsSessionValid(request)) { - Send403(response, "Invalid token or session expired."); + SendError(response, 403, "Invalid token or session expired."); return; } @@ -456,14 +456,14 @@ namespace DnsServerCore { if (path.Contains("/../")) { - Send404(response); + SendError(response, 404); return; } if (path == "/blocklist.txt") { if (!IPAddress.IsLoopback(GetRequestRemoteEndPoint(request).Address)) - Send403(response, "Access Denied."); + SendError(response, 403); } if (path == "/") @@ -473,7 +473,7 @@ namespace DnsServerCore if (!File.Exists(path)) { - Send404(response); + SendError(response, 404); return; } @@ -487,12 +487,7 @@ namespace DnsServerCore _log.Write(GetRequestRemoteEndPoint(request), ex); - try - { - Send500(response, ex); - } - catch - { } + SendError(response, ex); } } @@ -501,6 +496,18 @@ namespace DnsServerCore //this is due to mono NullReferenceException issue try { + if (NetUtilities.IsPrivateIP(request.RemoteEndPoint.Address)) + { + //reverse proxy X-Real-IP header supported only when remote IP address is private + + string xRealIp = request.Headers["X-Real-IP"]; + if (!string.IsNullOrEmpty(xRealIp)) + { + //get the real IP address of the requesting client from X-Real-IP header set in nginx proxy_pass block + return new IPEndPoint(IPAddress.Parse(xRealIp), 0); + } + } + return request.RemoteEndPoint; } catch @@ -509,51 +516,29 @@ namespace DnsServerCore } } - private static void Send500(HttpListenerResponse response, Exception ex) + private static void SendError(HttpListenerResponse response, Exception ex) { - Send500(response, ex.ToString()); + SendError(response, 500, ex.ToString()); } - private static void Send500(HttpListenerResponse response, string message) + private static void SendError(HttpListenerResponse response, int statusCode, string message = null) { - byte[] buffer = Encoding.UTF8.GetBytes("

500 Internal Server Error

" + message + "

"); - - response.StatusCode = 500; - response.ContentType = "text/html"; - response.ContentLength64 = buffer.Length; - - using (Stream stream = response.OutputStream) + try { - stream.Write(buffer, 0, buffer.Length); - } - } - - private static void Send404(HttpListenerResponse response) - { - byte[] buffer = Encoding.UTF8.GetBytes("

404 Not Found

"); - - response.StatusCode = 404; - response.ContentType = "text/html"; - response.ContentLength64 = buffer.Length; - - using (Stream stream = response.OutputStream) - { - stream.Write(buffer, 0, buffer.Length); - } - } - - private static void Send403(HttpListenerResponse response, string message) - { - byte[] buffer = Encoding.UTF8.GetBytes("

403 Forbidden

" + message + "

"); - - response.StatusCode = 403; - response.ContentType = "text/html"; - response.ContentLength64 = buffer.Length; - - using (Stream stream = response.OutputStream) - { - stream.Write(buffer, 0, buffer.Length); + string statusString = statusCode + " " + DnsServer.GetStatusString((HttpStatusCode)statusCode); + byte[] buffer = Encoding.UTF8.GetBytes("" + statusString + "

" + statusString + "

" + (message == null ? "" : "

" + message + "

") + ""); + + response.StatusCode = statusCode; + response.ContentType = "text/html"; + response.ContentLength64 = buffer.Length; + + using (Stream stream = response.OutputStream) + { + stream.Write(buffer, 0, buffer.Length); + } } + catch + { } } private static void SendFile(HttpListenerResponse response, string path) @@ -4005,6 +3990,8 @@ namespace DnsServerCore _webServiceHostname = "localhost"; } + _webService.IgnoreWriteExceptions = true; + _webServiceThread = new Thread(AcceptWebRequestAsync); _webServiceThread.IsBackground = true; _webServiceThread.Start();