2020-03-13 15:10:26 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using NBitcoin;
|
2019-03-18 00:03:02 +09:00
|
|
|
|
using System.Net;
|
2020-01-06 13:57:32 +01:00
|
|
|
|
using System.Net.Http;
|
2019-03-18 00:03:02 +09:00
|
|
|
|
using System.Net.Sockets;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using BTCPayServer.Configuration;
|
2020-01-06 13:57:32 +01:00
|
|
|
|
using com.LandonKey.SocksWebProxy;
|
|
|
|
|
using com.LandonKey.SocksWebProxy.Proxy;
|
2020-03-13 16:52:50 +01:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using NBitcoin.Logging;
|
2019-04-05 16:19:04 +09:00
|
|
|
|
using NBitcoin.Protocol.Connectors;
|
|
|
|
|
using NBitcoin.Protocol;
|
2019-03-18 00:03:02 +09:00
|
|
|
|
|
|
|
|
|
namespace BTCPayServer.Services
|
|
|
|
|
{
|
|
|
|
|
public class SocketFactory
|
|
|
|
|
{
|
|
|
|
|
private readonly BTCPayServerOptions _options;
|
2020-03-13 15:10:26 +01:00
|
|
|
|
public readonly Task<HttpClient> SocksClient;
|
|
|
|
|
|
2019-03-18 00:03:02 +09:00
|
|
|
|
public SocketFactory(BTCPayServerOptions options)
|
|
|
|
|
{
|
|
|
|
|
_options = options;
|
2020-01-06 13:57:32 +01:00
|
|
|
|
SocksClient = CreateHttpClientUsingSocks();
|
2019-03-18 00:03:02 +09:00
|
|
|
|
}
|
2020-03-13 15:10:26 +01:00
|
|
|
|
|
2019-03-31 13:16:05 +09:00
|
|
|
|
public async Task<Socket> ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
|
2019-03-18 00:03:02 +09:00
|
|
|
|
{
|
2019-04-05 16:19:04 +09:00
|
|
|
|
DefaultEndpointConnector connector = new DefaultEndpointConnector();
|
|
|
|
|
NodeConnectionParameters connectionParameters = new NodeConnectionParameters();
|
|
|
|
|
if (_options.SocksEndpoint != null)
|
2019-03-18 00:03:02 +09:00
|
|
|
|
{
|
2019-04-05 16:19:04 +09:00
|
|
|
|
connectionParameters.TemplateBehaviors.Add(new NBitcoin.Protocol.Behaviors.SocksSettingsBehavior()
|
2019-03-18 00:03:02 +09:00
|
|
|
|
{
|
2019-04-05 16:19:04 +09:00
|
|
|
|
SocksEndpoint = _options.SocksEndpoint
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-03-13 15:10:26 +01:00
|
|
|
|
|
2019-04-05 16:19:04 +09:00
|
|
|
|
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await connector.ConnectSocket(socket, endPoint, connectionParameters, cancellationToken);
|
2019-03-18 00:03:02 +09:00
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
2019-04-05 16:19:04 +09:00
|
|
|
|
SafeCloseSocket(socket);
|
2019-03-18 00:03:02 +09:00
|
|
|
|
}
|
2020-03-13 15:10:26 +01:00
|
|
|
|
|
2019-03-18 00:03:02 +09:00
|
|
|
|
return socket;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-05 16:19:04 +09:00
|
|
|
|
internal static void SafeCloseSocket(System.Net.Sockets.Socket socket)
|
2019-03-18 00:03:02 +09:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2019-04-05 16:19:04 +09:00
|
|
|
|
socket.Shutdown(SocketShutdown.Both);
|
2019-03-18 00:03:02 +09:00
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
}
|
2020-03-13 15:10:26 +01:00
|
|
|
|
|
2019-04-05 16:19:04 +09:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
socket.Dispose();
|
|
|
|
|
}
|
|
|
|
|
catch
|
2019-03-18 00:03:02 +09:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-06 13:57:32 +01:00
|
|
|
|
|
2020-03-13 15:10:26 +01:00
|
|
|
|
private Task<HttpClient> CreateHttpClientUsingSocks()
|
2020-01-06 13:57:32 +01:00
|
|
|
|
{
|
2020-03-13 15:10:26 +01:00
|
|
|
|
return Task.Run(() =>
|
2020-01-06 13:57:32 +01:00
|
|
|
|
{
|
2020-03-13 16:52:50 +01:00
|
|
|
|
try
|
2020-01-06 13:57:32 +01:00
|
|
|
|
{
|
2020-03-13 16:52:50 +01:00
|
|
|
|
var proxyConfig = new ProxyConfig() {Version = ProxyConfig.SocksVersion.Five};
|
|
|
|
|
switch (_options.SocksEndpoint)
|
|
|
|
|
{
|
|
|
|
|
case null:
|
|
|
|
|
return null;
|
|
|
|
|
case IPEndPoint ipEndPoint:
|
|
|
|
|
proxyConfig.SocksPort = ipEndPoint.Port;
|
|
|
|
|
proxyConfig.SocksAddress = ipEndPoint.Address;
|
|
|
|
|
break;
|
|
|
|
|
case DnsEndPoint dnsEndPoint:
|
|
|
|
|
|
2020-03-13 15:10:26 +01:00
|
|
|
|
proxyConfig.SocksPort = dnsEndPoint.Port;
|
|
|
|
|
var ip = Dns.GetHostEntry(dnsEndPoint.Host).AddressList
|
|
|
|
|
.SingleOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork);
|
|
|
|
|
if (ip == null)
|
|
|
|
|
{
|
2020-03-13 16:52:50 +01:00
|
|
|
|
Logs.Utils.LogWarning( $"Could not find ip for {dnsEndPoint.Host}");
|
2020-03-13 15:10:26 +01:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proxyConfig.SocksAddress = ip;
|
|
|
|
|
break;
|
2020-03-13 16:52:50 +01:00
|
|
|
|
|
|
|
|
|
default:
|
2020-03-13 15:10:26 +01:00
|
|
|
|
return null;
|
2020-03-13 16:52:50 +01:00
|
|
|
|
}
|
|
|
|
|
Logs.Utils.LogWarning( $"Created socks proxied http client!");
|
|
|
|
|
return new HttpClient(new HttpClientHandler
|
|
|
|
|
{
|
|
|
|
|
Proxy = new SocksWebProxy(proxyConfig), UseProxy = true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logs.Utils.LogError(e, "Could not create Tor client");
|
|
|
|
|
return null;
|
2020-03-13 15:10:26 +01:00
|
|
|
|
}
|
2020-01-06 13:57:32 +01:00
|
|
|
|
});
|
|
|
|
|
}
|
2019-03-18 00:03:02 +09:00
|
|
|
|
}
|
|
|
|
|
}
|