Ситуация
Я изменил образец маршрутизатора WCF, чтобы удалить вещи, которые я в данный момент не использую, поддерживаю clientVia, а не прямые соединения, и поддерживаю HTTP и HTTPS.Когда я использую маршрутизатор в качестве посредника для службы с поддержкой MLS, все работает нормально.Когда я использую маршрутизатор в качестве промежуточного звена для службы с поддержкой TLS и MLS, мне не удается настроить безопасный диалог.
Я подключаюсь к маршрутизатору по протоколу HTTP и пытаюсь маршрутизировать к SSL-включен сервис с использованием HTTPS.Если я пытаюсь использовать TLS для маршрутизатора, то маршрутизатор должен работать по протоколу HTTPS ... и тогда мне нужен соответствующий сертификат, поэтому я пытаюсь настроить клиент == (HTTP) ==>Маршрутизатор == (HTTPS) ==> Сервисные отношения.
Сообщение, отправляемое для установления TLS в случае прямого соединения (которое работает), сильно отличается от сообщения, отправляемого для установления TLS при прохождении через маршрутизатор.,Похоже, что клиент диктует то, что отправляется, но разве клиент не должен просто отправлять сообщение MLS, а маршрутизатор устанавливает TLS, а затем отправляет сообщение MLS?
Далее следуют информация о коде и конфигурации, ирезультирующий трафик (прямой и через маршрутизатор), а также.Поскольку в класс RouterBindingElement не было внесено соответствующих изменений, я удалил это из приведенного ниже кода (для экономии места).
Будем весьма благодарны за любые предложения о том, как заставить работать SSL.
Код / Конфиг
Класс привязки Router *
public enum RouterTransport
{
Http = 0,
Tcp = 1,
NamedPipe = 2,
Https = 3
}
public enum MessageEncoding
{
Text,
Binary,
Mtom,
}
public class RouterBinding : Binding, IBindingRuntimePreferences
{
MessageEncoding messageEncoding;
RouterTransport transport;
HttpTransportBindingElement httpTransport;
HttpsTransportBindingElement httpsTransport;
TcpTransportBindingElement tcpTransport;
NamedPipeTransportBindingElement namedPipeTransport;
TextMessageEncodingBindingElement textEncoding;
MtomMessageEncodingBindingElement mtomEncoding;
BinaryMessageEncodingBindingElement binaryEncoding;
public RouterBinding()
: base()
{
Initialize();
}
public RouterBinding(string configurationName)
: this()
{
ApplyConfiguration(configurationName);
}
public RouterBinding(RouterTransport transport)
: this()
{
this.Transport = transport;
if (transport == RouterTransport.NamedPipe || transport == RouterTransport.Tcp)
{
this.MessageEncoding = MessageEncoding.Binary;
}
}
public RouterTransport Transport
{
get { return this.transport; }
set
{
this.transport = value;
}
}
public MessageEncoding MessageEncoding
{
get { return this.messageEncoding; }
set
{
this.messageEncoding = value;
}
}
public HostNameComparisonMode HostNameComparisonMode
{
get { return this.tcpTransport.HostNameComparisonMode; }
set
{
this.tcpTransport.HostNameComparisonMode = value;
this.namedPipeTransport.HostNameComparisonMode = value;
this.httpTransport.HostNameComparisonMode = value;
this.httpsTransport.HostNameComparisonMode = value;
}
}
public int ListenBacklog
{
get { return this.tcpTransport.ListenBacklog; }
set { this.tcpTransport.ListenBacklog = value; }
}
public long MaxBufferPoolSize
{
get { return this.tcpTransport.MaxBufferPoolSize; }
set
{
this.tcpTransport.MaxBufferPoolSize = value;
this.namedPipeTransport.MaxBufferPoolSize = value;
}
}
public int MaxBufferSize
{
get { return this.tcpTransport.MaxBufferSize; }
set
{
this.tcpTransport.MaxBufferSize = value;
this.namedPipeTransport.MaxBufferSize = value;
}
}
public int MaxConnections
{
get { return this.tcpTransport.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint; }
set
{
this.tcpTransport.MaxPendingConnections = value;
this.namedPipeTransport.MaxPendingConnections = value;
this.tcpTransport.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint = value;
this.namedPipeTransport.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint = value;
}
}
public long MaxReceivedMessageSize
{
get { return this.tcpTransport.MaxReceivedMessageSize; }
set
{
this.tcpTransport.MaxReceivedMessageSize = value;
this.namedPipeTransport.MaxReceivedMessageSize = value;
this.httpTransport.MaxReceivedMessageSize = value;
this.httpsTransport.MaxReceivedMessageSize = value;
}
}
public bool PortSharingEnabled
{
get { return this.tcpTransport.PortSharingEnabled; }
set { this.tcpTransport.PortSharingEnabled = value; }
}
public TransferMode TransferMode
{
get { return this.tcpTransport.TransferMode; }
set
{
this.tcpTransport.TransferMode = value;
this.namedPipeTransport.TransferMode = value;
this.httpTransport.TransferMode = value;
this.httpsTransport.TransferMode = value;
}
}
bool IBindingRuntimePreferences.ReceiveSynchronously
{
get { return false; }
}
public override string Scheme
{
get { return this.TransportElement.Scheme; }
}
void Initialize()
{
this.httpTransport = new HttpTransportBindingElement();
this.httpsTransport = new HttpsTransportBindingElement();
this.tcpTransport = new TcpTransportBindingElement();
this.namedPipeTransport = new NamedPipeTransportBindingElement();
this.textEncoding = new TextMessageEncodingBindingElement();
this.mtomEncoding = new MtomMessageEncodingBindingElement();
this.binaryEncoding = new BinaryMessageEncodingBindingElement();
this.httpTransport.ManualAddressing = true;
this.httpsTransport.ManualAddressing = true;
this.tcpTransport.ManualAddressing = true;
this.namedPipeTransport.ManualAddressing = true;
this.transport = RouterTransport.Http;
this.messageEncoding = MessageEncoding.Text;
}
void ApplyConfiguration(string configurationName)
{
RouterBindingCollectionElement bindingCollectionElement = RouterBindingCollectionElement.GetBindingCollectionElement();
RouterBindingElement element = bindingCollectionElement.Bindings[configurationName];
if (element == null)
{
throw new ConfigurationErrorsException(string.Format("ConfigInvalidBindingConfigurationName", configurationName, bindingCollectionElement.BindingName));
}
else
{
element.ApplyConfiguration(this);
}
}
TransportBindingElement TransportElement
{
get
{
switch (this.transport)
{
case RouterTransport.Http:
return this.httpTransport;
case RouterTransport.Https:
return this.httpsTransport;
case RouterTransport.Tcp:
return this.tcpTransport;
case RouterTransport.NamedPipe:
return this.namedPipeTransport;
}
return null;
}
}
MessageEncodingBindingElement EncodingElement
{
get
{
switch (this.messageEncoding)
{
case MessageEncoding.Text:
return this.textEncoding;
case MessageEncoding.Mtom:
return this.mtomEncoding;
case MessageEncoding.Binary:
return this.binaryEncoding;
}
return null;
}
}
public override BindingElementCollection CreateBindingElements()
{
BindingElementCollection elements = new BindingElementCollection();
elements.Add(this.EncodingElement);
elements.Add(this.TransportElement);
return elements;
}
}
public partial class RouterBindingCollectionElement : StandardBindingCollectionElement<RouterBinding, RouterBindingElement>
{
// Removed for space
}
Класс маршрутизатора
class SoapRouterExtension : IExtension<ServiceHostBase>
{
IDictionary<string, Binding> bindings = new Dictionary<string, Binding>(2);
public SoapRouterExtension()
{
this.bindings.Add("http", new RouterBinding("HttpTextSoap12RouterBinding"));
this.bindings.Add("https", new RouterBinding("HttpsTextSoap12RouterBinding"));
}
public IDictionary<string, Binding> Bindings
{
get { return this.bindings; }
}
public void Attach(ServiceHostBase owner)
{ }
public void Detach(ServiceHostBase owner)
{ }
}
sealed class SoapRouterServiceBehavior : Attribute, IServiceBehavior
{
void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{ }
void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{ }
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
SoapRouterExtension extension = new SoapRouterExtension();
serviceHostBase.Extensions.Add(extension);
}
}
[SoapRouterServiceBehavior]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple, ValidateMustUnderstand = false, AddressFilterMode = AddressFilterMode.Any)]
public sealed class SoapRouter : IRequestReplyDatagramRouter, IDisposable
{
SoapRouterExtension extension;
public SoapRouter()
{
ServiceHostBase host = OperationContext.Current.Host;
this.extension = host.Extensions.Find<SoapRouterExtension>();
}
#region SoapIntermediary Request-Reply Datagram
Message IRequestReplyDatagramRouter.ProcessMessage(Message message)
{
EndpointAddress to = new EndpointAddress(message.Headers.To.AbsoluteUri);
IRequestReplyDatagramRouter forwardingChannel = null;
try
{
ChannelFactory<IRequestReplyDatagramRouter> factory = new ChannelFactory<IRequestReplyDatagramRouter>(this.extension.Bindings[to.Uri.Scheme], to);
factory.Endpoint.Behaviors.Add(new MustUnderstandBehavior(false));
forwardingChannel = factory.CreateChannel();
Console.WriteLine("Forwarding request " + message.Headers.Action + "...");
Message response = forwardingChannel.ProcessMessage(message);
Console.WriteLine("Forwarding response " + response.Headers.Action + "...");
return response;
}
finally
{
if (forwardingChannel != null)
{
IClientChannel channel = forwardingChannel as IClientChannel;
if (channel.State == CommunicationState.Faulted)
channel.Abort();
else
channel.Close();
}
}
}
#endregion
void IDisposable.Dispose()
{
}
}
public class ServiceDriver
{
public static void Main(string[] args)
{
ServiceHost serviceHost = new ServiceHost(typeof(SoapRouter));
serviceHost.Open();
Console.ReadLine();
}
}
Сервисные привязки
Конфигурация привязки HTTPS применяется к исходящему соединению TLS.
<routerBinding>
<binding name="HttpTextSoap12RouterBinding"
transport="Http"
messageEncoding="Text"
messageVersion="Soap12WSAddressing10"
closeTimeout="01:00:00"
openTimeout="01:00:00"
receiveTimeout="01:00:00"
sendTimeout="01:00:00">
</binding>
<binding name="HttpsTextSoap12RouterBinding"
transport="Https"
messageEncoding="Text"
messageVersion="Soap12WSAddressing10"
closeTimeout="01:00:00"
openTimeout="01:00:00"
receiveTimeout="01:00:00"
sendTimeout="01:00:00">
</binding>
</routerBinding>
Трафик
Места, которые я вложилin {} были изменены, но не было внесено никаких изменений в общее значение.
Прямое подключение
CONNECT {provider.com:443} HTTP/1.1
Host: {provider.com}
Proxy-Connection: Keep-Alive
Прямое установление TLS
POST {https://provider.com/service.svc} HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Host: {provider.com}
Content-Length: 4379
Expect: 100-continue
Connection: Keep-Alive
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</a:Action>
<a:MessageID>urn:uuid:cfd9ec29-5e55-4154-8737-69f9b8b8bbb7</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1" u:Id="_1">{https://provider.com/service.svc}</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2011-03-04T14:06:27.993Z</u:Created>
<u:Expires>2011-03-04T14:11:27.993Z</u:Expires>
</u:Timestamp>
<o:BinarySecurityToken u:Id="uuid-526477b6-8ed4-4873-bba5-7997589cd63c-1" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"> {wFNcPIXogDSsEJYhXyu/H3NbS1oam7quaeDScz+MdDANBgkqhkiG9w0BAQUFADCBujEfMB0GA1UEChMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEXMBUGA1UECxMOVmVyaVNpZ24sIEluYy4xMzAxBgNVBAsTKlZlcmlTaWduIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gQ2xhc3MgMzFJMEuIDPoxyyRVZOBT9HmFHglzaWduLmNvbS9DUFMgSW5jb3JwLmJ5IFJlZi4gTElBQklMSVRZIExURC4oYyk5NyBWZXJpU2lnbjAeFw0xMDA4MjYwMDAwMDBaFw0xMTA4MjYyMzU5NTlaMIGXMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExETAPBgNVBAcUCFJpY2htb25kMSswKQYDVQQKFCJBZmZpbGlhdGVkIENvbXB1dGVyIFNlcnZpY2VzLCBJbmMuMSQwIgYDVQQLFBtIZWFsdGggTWFuYWdlbWVudCBTb2x1dGlvbnMxDzANBgNVBAMUBkFDU0hJRTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArpBNMAnbIJ5MLafu2mYd8CJ1239FQ8LJlNfGwyVDkKHE8Quzdml28hIZ8XnLvUI0T9YWymf020SbqhwWKXt9eNH6IaRBZzIaT35NyAaUa/FA9rpCO/djt0z+wOukX75ZLmYtLHpskNtFfBtS9E+k2N8QEz7V+VJhHcWCVKESWBcCAwEAAaOCAa0wggGpMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9TVlJJbnRsLWNybC52ZXJpc2lnbi5jb20vU1ZSSW50bC5jcmwwRAYDVR0gBD0wOzA5BgtghkgBhvhFAQcXAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMCgGA1UdJQQhMB8GCWCGSAGG+EIEAQYIKwYBBQUHAwEGCCsGAQUFBwMCMHEGCCsGAQUFBwEBBGUwYzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AudmVyaXNpZ24uY29tMDsGCCsGAQUFBzAChi9oaiEP2i8vU1ZSSW50bC1haWEudmVyaXNpZ24uY29tL1NWUkludGwtYWlhLmNlcjBuBggrBgEFBQcBDARiMGChXqBcMFowWDBWFglpbWFnZS9naWYwITAfMAcGBSsOAwIaBBRLa7kolgYMu9BSOJsprEsHiyEFGDAmFiRodHRwOi8vbG9nby52ZXJpc2lnbi5jb20vdnNsb2dvMS5naWYwDQYJKoZIhvcNAQEFCB03AYEAXx9ZBgH5iWAnU8eOh2tNS286TFIcnAMJRiR3lvNs+2bi8NNl4a3AUcPhcfy+ybSHiL0Qu7wbpSnZ67FIT2SDa+h3v1JYhAu9hUrkJF9UGOWe8QOVUZuhjt5Uzs+YyRcI30FPRBjvsEqrnO+5ckoKqFEJVwV3FKMyMF5/gvZZszo=}</o:BinarySecurityToken>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#_0">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>{aepZFE9EXqlXmuAf3RwcA6vXThQ=}</DigestValue>
</Reference>
<Reference URI="#_1">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>{G9/ctKlSyWbRU78aQSLZmEbgdPw=}</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>{JAGbae324PdpRWOaIzihZygSAQVm3CJfOWbP6gsc0UJAGbae324PmYyqYMsgIMuCAlSHIj4yrEfbEL2XHt/nWlBfF0FgfhyqgcsEhc5vHR4kSmS7uKEoOZg8iMSDTGgk86YN5Z+UdB9ysIwe7KpxqrPmJAGbae324PdW8E2GWzY=}</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-526477b6-8ed4-4873-bba5-7997589cd63c-1"/>
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:Entropy>
<t:BinarySecret u:Id="uuid-18de0e52-6a66-442a-8b18-41e4037b5139-1" Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce">{gjBI9ZhnJzJAGbae324P+APERNf9gqoJAGbae324PCA=}</t:BinarySecret>
</t:Entropy>
<t:KeySize>256</t:KeySize>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>
Почта клиента
POST http://localhost.:8000/services/soap12/text HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Host: localhost.:8000
Content-Length: 1146
Expect: 100-continue
Connection: Keep-Alive
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:MessageID>urn:uuid:1f5e02f6-ce41-4b66-a3a8-eb4014d5d1cb</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">{https://provider.com/service.svc}</a:To>
</s:Header>
<s:Body>
<t:RequestSecurityToken Context="uuid-ffc85f7f-3ffa-4bc7-9174-5ab16948ec78-1" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:KeySize>256</t:KeySize>
<t:BinaryExchange ValueType=" http://schemas.xmlsoap.org/ws/2005/02/trust/tlsnego" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">{FgMBAEgBAABEAwFNcPIXogDSsEJYhXyu/adf4eFAe436TWvHqqv6ZN+FSQAAFgAEAAUACgAJAGbae324PYAEwASAGMBAAAF/wEAAQA=}</t:BinaryExchange>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>
Подключение маршрутизатора
CONNECT {provider.com:443} HTTP/1.1
Host: {provider.com}
Proxy-Connection: Keep-Alive
Создание TLS маршрутизатора
POST {https://provider.com/service.svc} HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
VsDebuggerCausalityData: uIDPoxyyRVZOBT9HmFHghQdaliEAAAAAAdkPtiI0y021hKG+IPwkNqyhfujS37tMnxoFJUL1/zoACQAA
Host: {provider.com}
Content-Length: 1146
Expect: 100-continue
Connection: Keep-Alive
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:MessageID>urn:uuid:1f5e02f6-ce41-4b66-a3a8-eb4014d5d1cb</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">{https://provider.com/service.svc}</a:To>
</s:Header>
<s:Body>
<t:RequestSecurityToken Context="uuid-ffc85f7f-3ffa-4bc7-9174-5ab16948ec78-1" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:KeySize>256</t:KeySize>
<t:BinaryExchange ValueType=" http://schemas.xmlsoap.org/ws/2005/02/trust/tlsnego" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">{FgMBAEgBAABEAMIIEhzCCA/CgAwIBAgIQadf4eFAe436TWvHqqv6ZN+FSQAAFgAEAAUACgAJAGbae324PYAEwASAGMBAAAF/wEAAQA=}</t:BinaryExchange>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>
Ошибка
Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint.