FastGithub/FastGithub.Scanner/DomainAddressProviders/IPAddressComProvider.cs
2021-06-18 22:37:53 +08:00

119 lines
4.3 KiB
C#

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;
using System.Threading.Tasks;
namespace FastGithub.Scanner.DomainAddressProviders
{
/// <summary>
/// ipaddress.com的域名与ip关系提供者
/// </summary>
[Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))]
sealed class IPAddressComProvider : IDomainAddressProvider
{
private readonly IOptionsMonitor<GithubOptions> options;
private readonly IHttpClientFactory httpClientFactory;
private readonly ILogger<IPAddressComProvider> logger;
private readonly Uri lookupUri = new("https://www.ipaddress.com/ip-lookup");
/// <summary>
/// 获取排序
/// </summary>
public int Order => default;
/// <summary>
/// ipaddress.com的域名与ip关系提供者
/// </summary>
/// <param name="options"></param>
/// <param name="logger"></param>
public IPAddressComProvider(
IOptionsMonitor<GithubOptions> options,
IHttpClientFactory httpClientFactory,
ILogger<IPAddressComProvider> logger)
{
this.options = options;
this.httpClientFactory = httpClientFactory;
this.logger = logger;
}
/// <summary>
/// 创建域名与ip的关系
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync(CancellationToken cancellationToken)
{
var setting = this.options.CurrentValue.DominAddressProviders.IPAddressComProvider;
if (setting.Enable == false)
{
return Enumerable.Empty<DomainAddress>();
}
var httpClient = this.httpClientFactory.CreateClient(nameof(FastGithub));
var result = new HashSet<DomainAddress>();
foreach (var domain in setting.Domains)
{
try
{
var addresses = await this.LookupAsync(httpClient, domain, cancellationToken);
foreach (var address in addresses)
{
result.Add(new DomainAddress(domain, address));
}
}
catch (Exception)
{
cancellationToken.ThrowIfCancellationRequested();
this.logger.LogWarning($"ipaddress.com无法解析{domain}");
}
}
return result;
}
/// <summary>
/// 反查ip
/// </summary>
/// <param name="httpClient"></param>
/// <param name="domain"></param>
/// <returns></returns>
private async Task<List<IPAddress>> LookupAsync(HttpClient httpClient, string domain, CancellationToken cancellationToken)
{
var keyValue = new KeyValuePair<string?, string?>("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, cancellationToken);
var html = await response.Content.ReadAsStringAsync(cancellationToken);
var match = Regex.Match(html, @"(?<=<h1>IP Lookup : )\d+\.\d+\.\d+\.\d+", RegexOptions.IgnoreCase);
if (match.Success && IPAddress.TryParse(match.Value, out var address))
{
return new List<IPAddress> { address };
}
var prefix = Regex.Escape("type=\"radio\" value=\"");
var matches = Regex.Matches(html, @$"(?<={prefix})\d+\.\d+\.\d+\.\d+", RegexOptions.IgnoreCase);
var addressList = new List<IPAddress>();
foreach (Match item in matches)
{
if (IPAddress.TryParse(item.Value, out address))
{
addressList.Add(address);
}
}
return addressList;
}
}
}