2
0

KestrelServerExtensions.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using FastGithub.Configuration;
  2. using FastGithub.HttpServer.Certs;
  3. using FastGithub.HttpServer.TcpMiddlewares;
  4. using FastGithub.HttpServer.TlsMiddlewares;
  5. using Microsoft.AspNetCore.Connections;
  6. using Microsoft.AspNetCore.Hosting;
  7. using Microsoft.AspNetCore.Server.Kestrel.Core;
  8. using Microsoft.AspNetCore.Server.Kestrel.Https;
  9. using Microsoft.Extensions.DependencyInjection;
  10. using Microsoft.Extensions.Logging;
  11. using Microsoft.Extensions.Options;
  12. using System;
  13. using System.Net.Security;
  14. using System.Security.Cryptography.X509Certificates;
  15. using System.Threading.Tasks;
  16. namespace FastGithub
  17. {
  18. /// <summary>
  19. /// Kestrel扩展
  20. /// </summary>
  21. public static class KestrelServerExtensions
  22. {
  23. /// <summary>
  24. /// 无限制
  25. /// </summary>
  26. /// <param name="kestrel"></param>
  27. public static void NoLimit(this KestrelServerOptions kestrel)
  28. {
  29. kestrel.Limits.MaxRequestBodySize = null;
  30. kestrel.Limits.MinResponseDataRate = null;
  31. kestrel.Limits.MinRequestBodyDataRate = null;
  32. }
  33. /// <summary>
  34. /// 监听http代理
  35. /// </summary>
  36. /// <param name="kestrel"></param>
  37. public static void ListenHttpProxy(this KestrelServerOptions kestrel)
  38. {
  39. var options = kestrel.ApplicationServices.GetRequiredService<IOptions<FastGithubOptions>>().Value;
  40. var httpProxyPort = options.HttpProxyPort;
  41. if (GlobalListener.CanListenTcp(httpProxyPort) == false)
  42. {
  43. throw new FastGithubException($"tcp端口{httpProxyPort}已经被其它进程占用,请在配置文件更换{nameof(FastGithubOptions.HttpProxyPort)}为其它端口");
  44. }
  45. kestrel.ListenLocalhost(httpProxyPort, listen =>
  46. {
  47. var proxyMiddleware = kestrel.ApplicationServices.GetRequiredService<HttpProxyMiddleware>();
  48. var tunnelMiddleware = kestrel.ApplicationServices.GetRequiredService<TunnelMiddleware>();
  49. listen.Use(next => context => proxyMiddleware.InvokeAsync(next, context));
  50. listen.UseTls();
  51. listen.Use(next => context => tunnelMiddleware.InvokeAsync(next, context));
  52. });
  53. kestrel.GetLogger().LogInformation($"已监听http://localhost:{httpProxyPort},http代理服务启动完成");
  54. }
  55. /// <summary>
  56. /// 监听ssh协议代理
  57. /// </summary>
  58. /// <param name="kestrel"></param>
  59. public static void ListenSshReverseProxy(this KestrelServerOptions kestrel)
  60. {
  61. var sshPort = GlobalListener.SshPort;
  62. kestrel.ListenLocalhost(sshPort, listen =>
  63. {
  64. listen.UseFlowAnalyze();
  65. listen.UseConnectionHandler<GithubSshReverseProxyHandler>();
  66. });
  67. kestrel.GetLogger().LogInformation($"已监听ssh://localhost:{sshPort},github的ssh反向代理服务启动完成");
  68. }
  69. /// <summary>
  70. /// 监听git协议代理代理
  71. /// </summary>
  72. /// <param name="kestrel"></param>
  73. public static void ListenGitReverseProxy(this KestrelServerOptions kestrel)
  74. {
  75. var gitPort = GlobalListener.GitPort;
  76. kestrel.ListenLocalhost(gitPort, listen =>
  77. {
  78. listen.UseFlowAnalyze();
  79. listen.UseConnectionHandler<GithubGitReverseProxyHandler>();
  80. });
  81. kestrel.GetLogger().LogInformation($"已监听git://localhost:{gitPort},github的git反向代理服务启动完成");
  82. }
  83. /// <summary>
  84. /// 监听http反向代理
  85. /// </summary>
  86. /// <param name="kestrel"></param>
  87. public static void ListenHttpReverseProxy(this KestrelServerOptions kestrel)
  88. {
  89. var httpPort = GlobalListener.HttpPort;
  90. kestrel.ListenLocalhost(httpPort);
  91. if (OperatingSystem.IsWindows())
  92. {
  93. kestrel.GetLogger().LogInformation($"已监听http://localhost:{httpPort},http反向代理服务启动完成");
  94. }
  95. }
  96. /// <summary>
  97. /// 监听https反向代理
  98. /// </summary>
  99. /// <param name="kestrel"></param>
  100. /// <exception cref="FastGithubException"></exception>
  101. public static void ListenHttpsReverseProxy(this KestrelServerOptions kestrel)
  102. {
  103. var httpsPort = GlobalListener.HttpsPort;
  104. kestrel.ListenLocalhost(httpsPort, listen =>
  105. {
  106. if (OperatingSystem.IsWindows())
  107. {
  108. listen.UseFlowAnalyze();
  109. }
  110. listen.UseTls();
  111. });
  112. if (OperatingSystem.IsWindows())
  113. {
  114. var logger = kestrel.GetLogger();
  115. logger.LogInformation($"已监听https://localhost:{httpsPort},https反向代理服务启动完成");
  116. }
  117. }
  118. /// <summary>
  119. /// 获取日志
  120. /// </summary>
  121. /// <param name="kestrel"></param>
  122. /// <returns></returns>
  123. private static ILogger GetLogger(this KestrelServerOptions kestrel)
  124. {
  125. var loggerFactory = kestrel.ApplicationServices.GetRequiredService<ILoggerFactory>();
  126. return loggerFactory.CreateLogger($"{nameof(FastGithub)}.{nameof(HttpServer)}");
  127. }
  128. /// <summary>
  129. /// 使用Tls中间件
  130. /// </summary>
  131. /// <param name="listen"></param>
  132. /// <param name="configureOptions">https配置</param>
  133. /// <returns></returns>
  134. public static ListenOptions UseTls(this ListenOptions listen)
  135. {
  136. var certService = listen.ApplicationServices.GetRequiredService<CertService>();
  137. certService.CreateCaCertIfNotExists();
  138. certService.InstallAndTrustCaCert();
  139. return listen.UseTls(domain => certService.GetOrCreateServerCert(domain));
  140. }
  141. /// <summary>
  142. /// 使用Tls中间件
  143. /// </summary>
  144. /// <param name="listen"></param>
  145. /// <param name="configureOptions">https配置</param>
  146. /// <returns></returns>
  147. private static ListenOptions UseTls(this ListenOptions listen, Func<string, X509Certificate2> certFactory)
  148. {
  149. var invadeMiddleware = listen.ApplicationServices.GetRequiredService<TlsInvadeMiddleware>();
  150. var restoreMiddleware = listen.ApplicationServices.GetRequiredService<TlsRestoreMiddleware>();
  151. listen.Use(next => context => invadeMiddleware.InvokeAsync(next, context));
  152. listen.UseHttps(new TlsHandshakeCallbackOptions
  153. {
  154. OnConnection = context =>
  155. {
  156. var options = new SslServerAuthenticationOptions
  157. {
  158. ServerCertificate = certFactory(context.ClientHelloInfo.ServerName)
  159. };
  160. return ValueTask.FromResult(options);
  161. },
  162. });
  163. listen.Use(next => context => restoreMiddleware.InvokeAsync(next, context));
  164. return listen;
  165. }
  166. }
  167. }