IPAddressComProvider.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. using Microsoft.Extensions.DependencyInjection;
  2. using Microsoft.Extensions.Logging;
  3. using Microsoft.Extensions.Options;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Http;
  9. using System.Text.RegularExpressions;
  10. using System.Threading.Tasks;
  11. namespace FastGithub.Scanner.DomainAddressProviders
  12. {
  13. /// <summary>
  14. /// ipaddress.com的域名与ip关系提供者
  15. /// </summary>
  16. [Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))]
  17. sealed class IPAddressComProvider : IDomainAddressProvider
  18. {
  19. private readonly IOptionsMonitor<GithubOptions> options;
  20. private readonly IHttpClientFactory httpClientFactory;
  21. private readonly ILogger<IPAddressComProvider> logger;
  22. private readonly Uri lookupUri = new("https://www.ipaddress.com/ip-lookup");
  23. /// <summary>
  24. /// 获取排序
  25. /// </summary>
  26. public int Order => default;
  27. /// <summary>
  28. /// ipaddress.com的域名与ip关系提供者
  29. /// </summary>
  30. /// <param name="options"></param>
  31. /// <param name="logger"></param>
  32. public IPAddressComProvider(
  33. IOptionsMonitor<GithubOptions> options,
  34. IHttpClientFactory httpClientFactory,
  35. ILogger<IPAddressComProvider> logger)
  36. {
  37. this.options = options;
  38. this.httpClientFactory = httpClientFactory;
  39. this.logger = logger;
  40. }
  41. /// <summary>
  42. /// 创建域名与ip的关系
  43. /// </summary>
  44. /// <returns></returns>
  45. public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync()
  46. {
  47. var setting = this.options.CurrentValue.DominAddressProviders.IPAddressComProvider;
  48. if (setting.Enable == false)
  49. {
  50. return Enumerable.Empty<DomainAddress>();
  51. }
  52. var httpClient = this.httpClientFactory.CreateClient(nameof(FastGithub));
  53. var result = new HashSet<DomainAddress>();
  54. foreach (var domain in setting.Domains)
  55. {
  56. try
  57. {
  58. var addresses = await this.LookupAsync(httpClient, domain);
  59. foreach (var address in addresses)
  60. {
  61. result.Add(new DomainAddress(domain, address));
  62. }
  63. }
  64. catch (Exception)
  65. {
  66. this.logger.LogWarning($"ipaddress.com无法解析{domain}");
  67. }
  68. }
  69. return result;
  70. }
  71. /// <summary>
  72. /// 反查ip
  73. /// </summary>
  74. /// <param name="httpClient"></param>
  75. /// <param name="domain"></param>
  76. /// <returns></returns>
  77. private async Task<List<IPAddress>> LookupAsync(HttpClient httpClient, string domain)
  78. {
  79. var keyValue = new KeyValuePair<string?, string?>("host", domain);
  80. var content = new FormUrlEncodedContent(Enumerable.Repeat(keyValue, 1));
  81. using var request = new HttpRequestMessage
  82. {
  83. Method = HttpMethod.Post,
  84. RequestUri = lookupUri,
  85. Content = content
  86. };
  87. using var response = await httpClient.SendAsync(request);
  88. var html = await response.Content.ReadAsStringAsync();
  89. var match = Regex.Match(html, @"(?<=<h1>IP Lookup : )\d+\.\d+\.\d+\.\d+", RegexOptions.IgnoreCase);
  90. if (match.Success && IPAddress.TryParse(match.Value, out var address))
  91. {
  92. return new List<IPAddress> { address };
  93. }
  94. var prefix = Regex.Escape("type=\"radio\" value=\"");
  95. var matches = Regex.Matches(html, @$"(?<={prefix})\d+\.\d+\.\d+\.\d+", RegexOptions.IgnoreCase);
  96. var addressList = new List<IPAddress>();
  97. foreach (Match item in matches)
  98. {
  99. if (IPAddress.TryParse(item.Value, out address))
  100. {
  101. addressList.Add(address);
  102. }
  103. }
  104. return addressList;
  105. }
  106. }
  107. }