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;
}
}
}