" + message + "
") + ""); + byte[] bufferHeader = Encoding.UTF8.GetBytes("HTTP/1.1 " + statusString + "\r\nDate: " + DateTime.UtcNow.ToString("r") + "\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: " + bufferContent.Length + "\r\nX-Robots-Tag: noindex, nofollow\r\nConnection: " + connection + "\r\n\r\n"); + + await outputStream.WriteAsync(bufferHeader); + await outputStream.WriteAsync(bufferContent); + await outputStream.FlushAsync(); + } + catch + { } + } + + private static async Task RedirectAsync(Stream outputStream, string protocol, string connection, string location) + { + try + { + string statusString = "302 Found"; + byte[] bufferContent = Encoding.UTF8.GetBytes("Location: " + location + "
"); + byte[] bufferHeader = Encoding.UTF8.GetBytes(protocol + " " + statusString + "\r\nDate: " + DateTime.UtcNow.ToString("r") + "\r\nLocation: " + location + "\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: " + bufferContent.Length + "\r\nX-Robots-Tag: noindex, nofollow\r\nConnection: " + connection + "\r\n\r\n"); + + await outputStream.WriteAsync(bufferHeader); + await outputStream.WriteAsync(bufferContent); + await outputStream.FlushAsync(); + } + catch + { } + } + + private static async Task SendFileAsync(Stream outputStream, string connection, string filePath) + { + using (FileStream fS = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + byte[] bufferHeader = Encoding.UTF8.GetBytes("HTTP/1.1 200 OK\r\nDate: " + DateTime.UtcNow.ToString("r") + "\r\nContent-Type: " + WebUtilities.GetContentType(filePath).MediaType + "\r\nContent-Length: " + fS.Length + "\r\nCache-Control: private, max-age=300\r\nX-Robots-Tag: noindex, nofollow\r\nConnection: " + connection + "\r\n\r\n"); + + await outputStream.WriteAsync(bufferHeader); + await fS.CopyToAsync(outputStream); + await outputStream.FlushAsync(); + } + } + + private static string GetHttpStatusString(HttpStatusCode statusCode) + { + StringBuilder sb = new StringBuilder(); + + foreach (char c in statusCode.ToString().ToCharArray()) + { + if (char.IsUpper(c) && sb.Length > 0) + sb.Append(' '); + + sb.Append(c); + } + + return sb.ToString(); + } + + #endregion + + #region public + + public Task InitializeAsync(IDnsServer dnsServer, string config) + { + _dnsServer = dnsServer; + + dynamic jsonConfig = JsonConvert.DeserializeObject(config); + + { + List" + blockPageMessage + "
") + @" + +"; + + _blockPageContent = Encoding.UTF8.GetBytes(blockPageContent); + + try + { + StopWebServer(); + + if (string.IsNullOrEmpty(_webServerTlsCertificateFilePath)) + { + StopTlsCertificateUpdateTimer(); + _webServerTlsCertificate = null; + } + else + { + LoadWebServiceTlsCertificate(); + StartTlsCertificateUpdateTimer(); + } + + StartWebServer(); + } + catch (Exception ex) + { + _dnsServer.WriteLog(ex); + } + + return Task.CompletedTask; + } + + #endregion + + #region properties + + public string Description + { get { return "Serves a block page from a built-in web server that can be displayed to the end user when a website is blocked by the DNS server.\n\nNote: You need to manually configure the custom IP addresses of this built-in web server in the blocking settings for the block page to be served."; } } + + #endregion + } +} diff --git a/Apps/BlockPageWebServerApp/BlockPageWebServerApp.csproj b/Apps/BlockPageWebServerApp/BlockPageWebServerApp.csproj new file mode 100644 index 00000000..c120f783 --- /dev/null +++ b/Apps/BlockPageWebServerApp/BlockPageWebServerApp.csproj @@ -0,0 +1,55 @@ +This website has been blocked by your network administrator.
+ + \ No newline at end of file