mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-16 01:03:01 +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.Linq;
|
||||
using System.Net.Security;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using MQTTnet.Serializer;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
@@ -76,6 +79,29 @@ namespace MQTTnet.Client
|
||||
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)
|
||||
{
|
||||
_webSocketOptions = new MqttClientWebSocketOptions
|
||||
@@ -86,11 +112,54 @@ namespace MQTTnet.Client
|
||||
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(
|
||||
bool allowUntrustedCertificates = false,
|
||||
bool allowUntrustedCertificates,
|
||||
bool ignoreCertificateChainErrors = 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
|
||||
{
|
||||
@@ -98,21 +167,14 @@ namespace MQTTnet.Client
|
||||
AllowUntrustedCertificates = allowUntrustedCertificates,
|
||||
IgnoreCertificateChainErrors = ignoreCertificateChainErrors,
|
||||
IgnoreCertificateRevocationErrors = ignoreCertificateRevocationErrors,
|
||||
Certificates = certificates?.ToList()
|
||||
Certificates = certificates?.ToList(),
|
||||
SslProtocol = sslProtocol,
|
||||
CertificateValidationCallback = certificateValidationCallback
|
||||
};
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithTls()
|
||||
{
|
||||
_tlsOptions = new MqttClientTlsOptions
|
||||
{
|
||||
UseTls = true
|
||||
};
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public IMqttClientOptions Build()
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Authentication;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
@@ -17,6 +18,8 @@ namespace MQTTnet.Client
|
||||
|
||||
public List<byte[]> Certificates { get; set; }
|
||||
|
||||
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12;
|
||||
|
||||
public Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> CertificateValidationCallback { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ namespace MQTTnet.Client
|
||||
|
||||
public CookieContainer CookieContainer { get; set; }
|
||||
|
||||
#if NET452 || NET461
|
||||
public MqttClientWebSocketProxyOptions MqttClientWebSocketProxy { get; set; } = new MqttClientWebSocketProxyOptions();
|
||||
#endif
|
||||
|
||||
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -6,6 +6,10 @@ using System.Threading.Tasks;
|
||||
using MQTTnet.Channel;
|
||||
using MQTTnet.Client;
|
||||
|
||||
#if NET452 || NET461
|
||||
using System.Net;
|
||||
#endif
|
||||
|
||||
namespace MQTTnet.Implementations
|
||||
{
|
||||
public class MqttWebSocketChannel : IMqttChannel
|
||||
@@ -14,7 +18,7 @@ namespace MQTTnet.Implementations
|
||||
private readonly MqttClientWebSocketOptions _options;
|
||||
|
||||
private WebSocket _webSocket;
|
||||
|
||||
|
||||
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
@@ -45,6 +49,26 @@ namespace MQTTnet.Implementations
|
||||
|
||||
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)
|
||||
{
|
||||
foreach (var requestHeader in _options.RequestHeaders)
|
||||
|
||||
Reference in New Issue
Block a user