using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace FastGithub.Scanner.DomainAddressProviders { /// /// ipaddress.com的域名与ip关系提供者 /// [Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))] sealed class IPAddressComProvider : IDomainAddressProvider { private readonly IOptionsMonitor options; private readonly IHttpClientFactory httpClientFactory; private readonly ILogger logger; private readonly Uri lookupUri = new("https://www.ipaddress.com/ip-lookup"); /// /// 获取排序 /// public int Order => default; /// /// ipaddress.com的域名与ip关系提供者 /// /// /// public IPAddressComProvider( IOptionsMonitor options, IHttpClientFactory httpClientFactory, ILogger logger) { this.options = options; this.httpClientFactory = httpClientFactory; this.logger = logger; } /// /// 创建域名与ip的关系 /// /// public async Task> CreateDomainAddressesAsync() { var setting = this.options.CurrentValue.DominAddressProviders.IPAddressComProvider; if (setting.Enable == false) { return Enumerable.Empty(); } var httpClient = this.httpClientFactory.CreateClient(nameof(FastGithub)); var result = new HashSet(); foreach (var domain in setting.Domains) { try { var addresses = await this.LookupAsync(httpClient, domain); foreach (var address in addresses) { result.Add(new DomainAddress(domain, address)); } } catch (Exception) { this.logger.LogWarning($"ipaddress.com无法解析{domain}"); } } return result; } /// /// 反查ip /// /// /// /// private async Task> LookupAsync(HttpClient httpClient, string domain) { var keyValue = new KeyValuePair("host", domain); var content = new FormUrlEncodedContent(Enumerable.Repeat(keyValue, 1)); using var request = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = lookupUri, Content = content }; using var response = await httpClient.SendAsync(request); var html = await response.Content.ReadAsStringAsync(); var match = Regex.Match(html, @"(?<=

IP Lookup : )\d+\.\d+\.\d+\.\d+", RegexOptions.IgnoreCase); if (match.Success && IPAddress.TryParse(match.Value, out var address)) { return new List { address }; } var prefix = Regex.Escape("type=\"radio\" value=\""); var matches = Regex.Matches(html, @$"(?<={prefix})\d+\.\d+\.\d+\.\d+", RegexOptions.IgnoreCase); var addressList = new List(); foreach (Match item in matches) { if (IPAddress.TryParse(item.Value, out address)) { addressList.Add(address); } } return addressList; } } }