119 lines
4.3 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|