TcpScanMiddleware.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using Microsoft.Extensions.Caching.Memory;
  2. using Microsoft.Extensions.DependencyInjection;
  3. using Microsoft.Extensions.Logging;
  4. using Microsoft.Extensions.Options;
  5. using System;
  6. using System.Net.Sockets;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. namespace FastGithub.Scanner.ScanMiddlewares
  10. {
  11. /// <summary>
  12. /// tcp扫描中间件
  13. /// </summary>
  14. [Service(ServiceLifetime.Singleton)]
  15. sealed class TcpScanMiddleware : IMiddleware<GithubContext>
  16. {
  17. private const int PORT = 443;
  18. private readonly IOptionsMonitor<TcpScanOptions> options;
  19. private readonly IMemoryCache memoryCache;
  20. private readonly ILogger<TcpScanMiddleware> logger;
  21. /// <summary>
  22. /// tcp扫描中间件
  23. /// </summary>
  24. /// <param name="options"></param>
  25. /// <param name="logger"></param>
  26. public TcpScanMiddleware(
  27. IOptionsMonitor<TcpScanOptions> options,
  28. IMemoryCache memoryCache,
  29. ILogger<TcpScanMiddleware> logger)
  30. {
  31. this.options = options;
  32. this.memoryCache = memoryCache;
  33. this.logger = logger;
  34. }
  35. /// <summary>
  36. /// tcp扫描
  37. /// </summary>
  38. /// <param name="context"></param>
  39. /// <param name="next"></param>
  40. /// <returns></returns>
  41. public async Task InvokeAsync(GithubContext context, Func<Task> next)
  42. {
  43. var key = $"tcp://{context.Address}";
  44. if (this.memoryCache.TryGetValue<bool>(key, out var available) == false)
  45. {
  46. available = await this.TcpScanAsync(context);
  47. this.memoryCache.Set(key, available, this.options.CurrentValue.CacheExpiration);
  48. }
  49. if (available == true)
  50. {
  51. await next();
  52. }
  53. else
  54. {
  55. this.logger.LogTrace($"{context.Domain} {context.Address}的{PORT}端口未开放");
  56. }
  57. }
  58. /// <summary>
  59. /// tcp扫描
  60. /// </summary>
  61. /// <param name="context"></param>
  62. /// <returns></returns>
  63. private async Task<bool> TcpScanAsync(GithubContext context)
  64. {
  65. try
  66. {
  67. var timeout = this.options.CurrentValue.Timeout;
  68. using var timeoutTokenSource = new CancellationTokenSource(timeout);
  69. using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutTokenSource.Token, context.CancellationToken);
  70. using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  71. await socket.ConnectAsync(context.Address, PORT, linkedTokenSource.Token);
  72. return true;
  73. }
  74. catch (Exception)
  75. {
  76. context.CancellationToken.ThrowIfCancellationRequested();
  77. return false;
  78. }
  79. }
  80. }
  81. }