mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-19 19:13:11 +08:00
Merge pull request #364 from PitySOFT/webproxy
Add proxy settings for WebSocket connections for .NET 451 and 461 and add option to specify the SSLProtocol and CertificateValidationCallback in TLS options, SSLProtocol default is TLS1.2
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using MQTTnet.Serializer;
|
using MQTTnet.Serializer;
|
||||||
|
|
||||||
namespace MQTTnet.Client
|
namespace MQTTnet.Client
|
||||||
@@ -76,6 +79,29 @@ namespace MQTTnet.Client
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NET452 || NET461
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithProxy(string address, string username = null, string password = null, string domain = null, bool bypassOnLocal = false, string[] bypassList = null)
|
||||||
|
{
|
||||||
|
if (_webSocketOptions == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("A WebSocket channel must be set if MqttClientWebSocketProxy is configured.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_webSocketOptions.MqttClientWebSocketProxy = new MqttClientWebSocketProxyOptions
|
||||||
|
{
|
||||||
|
Address = address,
|
||||||
|
Username = username,
|
||||||
|
Password = password,
|
||||||
|
Domain = domain,
|
||||||
|
BypassOnLocal = bypassOnLocal,
|
||||||
|
BypassList = bypassList
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithWebSocketServer(string uri)
|
public MqttClientOptionsBuilder WithWebSocketServer(string uri)
|
||||||
{
|
{
|
||||||
_webSocketOptions = new MqttClientWebSocketOptions
|
_webSocketOptions = new MqttClientWebSocketOptions
|
||||||
@@ -86,11 +112,54 @@ namespace MQTTnet.Client
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithTls()
|
||||||
|
{
|
||||||
|
return WithTls(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithTls(Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback)
|
||||||
|
{
|
||||||
|
return WithTls(SslProtocols.None, certificateValidationCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithTls(SslProtocols sslProtocol,
|
||||||
|
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
||||||
|
{
|
||||||
|
return WithTls(new byte[][] { }, sslProtocol, certificateValidationCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithTls(byte[][] certificates,
|
||||||
|
SslProtocols sslProtocol = SslProtocols.Tls12,
|
||||||
|
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
||||||
|
{
|
||||||
|
return WithTls(false, certificates, sslProtocol, certificateValidationCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithTls(bool ignoreCertificateRevocationErrors,
|
||||||
|
byte[][] certificates = null,
|
||||||
|
SslProtocols sslProtocol = SslProtocols.Tls12,
|
||||||
|
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
||||||
|
{
|
||||||
|
return WithTls(false, ignoreCertificateRevocationErrors, certificates, sslProtocol, certificateValidationCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithTls(bool ignoreCertificateChainErrors,
|
||||||
|
bool ignoreCertificateRevocationErrors = false,
|
||||||
|
byte[][] certificates = null,
|
||||||
|
SslProtocols sslProtocol = SslProtocols.Tls12,
|
||||||
|
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
||||||
|
{
|
||||||
|
return WithTls(false, ignoreCertificateChainErrors, ignoreCertificateRevocationErrors, certificates, sslProtocol, certificateValidationCallback);
|
||||||
|
}
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithTls(
|
public MqttClientOptionsBuilder WithTls(
|
||||||
bool allowUntrustedCertificates = false,
|
bool allowUntrustedCertificates,
|
||||||
bool ignoreCertificateChainErrors = false,
|
bool ignoreCertificateChainErrors = false,
|
||||||
bool ignoreCertificateRevocationErrors = false,
|
bool ignoreCertificateRevocationErrors = false,
|
||||||
params byte[][] certificates)
|
byte[][] certificates = null,
|
||||||
|
SslProtocols sslProtocol = SslProtocols.Tls12,
|
||||||
|
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
||||||
{
|
{
|
||||||
_tlsOptions = new MqttClientTlsOptions
|
_tlsOptions = new MqttClientTlsOptions
|
||||||
{
|
{
|
||||||
@@ -98,21 +167,14 @@ namespace MQTTnet.Client
|
|||||||
AllowUntrustedCertificates = allowUntrustedCertificates,
|
AllowUntrustedCertificates = allowUntrustedCertificates,
|
||||||
IgnoreCertificateChainErrors = ignoreCertificateChainErrors,
|
IgnoreCertificateChainErrors = ignoreCertificateChainErrors,
|
||||||
IgnoreCertificateRevocationErrors = ignoreCertificateRevocationErrors,
|
IgnoreCertificateRevocationErrors = ignoreCertificateRevocationErrors,
|
||||||
Certificates = certificates?.ToList()
|
Certificates = certificates?.ToList(),
|
||||||
|
SslProtocol = sslProtocol,
|
||||||
|
CertificateValidationCallback = certificateValidationCallback
|
||||||
};
|
};
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithTls()
|
|
||||||
{
|
|
||||||
_tlsOptions = new MqttClientTlsOptions
|
|
||||||
{
|
|
||||||
UseTls = true
|
|
||||||
};
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMqttClientOptions Build()
|
public IMqttClientOptions Build()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
|
||||||
namespace MQTTnet.Client
|
namespace MQTTnet.Client
|
||||||
{
|
{
|
||||||
@@ -17,6 +18,8 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
public List<byte[]> Certificates { get; set; }
|
public List<byte[]> Certificates { get; set; }
|
||||||
|
|
||||||
|
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12;
|
||||||
|
|
||||||
public Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> CertificateValidationCallback { get; set; }
|
public Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> CertificateValidationCallback { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
public CookieContainer CookieContainer { get; set; }
|
public CookieContainer CookieContainer { get; set; }
|
||||||
|
|
||||||
|
#if NET452 || NET461
|
||||||
|
public MqttClientWebSocketProxyOptions MqttClientWebSocketProxy { get; set; } = new MqttClientWebSocketProxyOptions();
|
||||||
|
#endif
|
||||||
|
|
||||||
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#if NET452 || NET461
|
||||||
|
|
||||||
|
namespace MQTTnet.Client
|
||||||
|
{
|
||||||
|
public class MqttClientWebSocketProxyOptions
|
||||||
|
{
|
||||||
|
public string Address { get; set; }
|
||||||
|
|
||||||
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
public bool BypassOnLocal { get; set; } = true;
|
||||||
|
|
||||||
|
public string[] BypassList { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -63,7 +63,7 @@ namespace MQTTnet.Implementations
|
|||||||
if (_options.TlsOptions.UseTls)
|
if (_options.TlsOptions.UseTls)
|
||||||
{
|
{
|
||||||
sslStream = new SslStream(new NetworkStream(_socket, true), false, InternalUserCertificateValidationCallback);
|
sslStream = new SslStream(new NetworkStream(_socket, true), false, InternalUserCertificateValidationCallback);
|
||||||
await sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(), SslProtocols.Tls12, _options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
|
await sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(), _options.TlsOptions.SslProtocol, _options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateStream(sslStream);
|
CreateStream(sslStream);
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ using System.Threading.Tasks;
|
|||||||
using MQTTnet.Channel;
|
using MQTTnet.Channel;
|
||||||
using MQTTnet.Client;
|
using MQTTnet.Client;
|
||||||
|
|
||||||
|
#if NET452 || NET461
|
||||||
|
using System.Net;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace MQTTnet.Implementations
|
namespace MQTTnet.Implementations
|
||||||
{
|
{
|
||||||
public class MqttWebSocketChannel : IMqttChannel
|
public class MqttWebSocketChannel : IMqttChannel
|
||||||
@@ -14,7 +18,7 @@ namespace MQTTnet.Implementations
|
|||||||
private readonly MqttClientWebSocketOptions _options;
|
private readonly MqttClientWebSocketOptions _options;
|
||||||
|
|
||||||
private WebSocket _webSocket;
|
private WebSocket _webSocket;
|
||||||
|
|
||||||
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
||||||
{
|
{
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
@@ -45,6 +49,26 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
var clientWebSocket = new ClientWebSocket();
|
var clientWebSocket = new ClientWebSocket();
|
||||||
|
|
||||||
|
#if NET452 || NET461
|
||||||
|
// use proxy if we have an address
|
||||||
|
if (string.IsNullOrEmpty(_options.MqttClientWebSocketProxy.Address) == false)
|
||||||
|
{
|
||||||
|
var proxyUri = new Uri(_options.MqttClientWebSocketProxy.Address);
|
||||||
|
|
||||||
|
// use proxy credentials if we have them
|
||||||
|
if (string.IsNullOrEmpty(_options.MqttClientWebSocketProxy.Username) == false && string.IsNullOrEmpty(_options.MqttClientWebSocketProxy.Password) == false)
|
||||||
|
{
|
||||||
|
var credentials = new NetworkCredential(_options.MqttClientWebSocketProxy.Username, _options.MqttClientWebSocketProxy.Password, _options.MqttClientWebSocketProxy.Domain);
|
||||||
|
clientWebSocket.Options.Proxy = new WebProxy(proxyUri, _options.MqttClientWebSocketProxy.BypassOnLocal, _options.MqttClientWebSocketProxy.BypassList, credentials);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// use proxy without credentials
|
||||||
|
clientWebSocket.Options.Proxy = new WebProxy(proxyUri, _options.MqttClientWebSocketProxy.BypassOnLocal, _options.MqttClientWebSocketProxy.BypassList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (_options.RequestHeaders != null)
|
if (_options.RequestHeaders != null)
|
||||||
{
|
{
|
||||||
foreach (var requestHeader in _options.RequestHeaders)
|
foreach (var requestHeader in _options.RequestHeaders)
|
||||||
|
|||||||
Reference in New Issue
Block a user