How can I use a ssl wildcard certificate to mutually authenticate several WCF servers via X509?

StackOverflow https://stackoverflow.com/questions/1630968

  •  06-07-2019
  •  | 
  •  

Question

I've got two WCF servers, both on the domain mydomain.com (fictional example, as are IP below !), respectively named server1 and server2.

They are both accessible through their public IP addresses (foo.1 and 2), but also from the private LAN they are on (ie 192.168.0.1 and 192.168.0.2)

I own a wildcard ssl certificate for *.mydomain.com. It's installed correctly in the relevant stores (ie Personal for encryption and Trusted Clients for Authentication)

I'd like both my servers to connect with one another on their local network addresses using my wildcard certificate for authentication purposes.

I've updated the C:\Windows\System32\drivers\etc\hosts file to make it look like this :

192.168.0.1     Server1.mydomain.com
192.186.0.2     Server2.mydomain.com

Those are not the IP addresses I get if I resolve Server1.mydomain.com (I would rather get foo.1 - 2)

I've also edited the Connection-specific DNS suffix for my IPV4 local interfaces to "mydomain.com"

My certificate is referred to like this in my Server.config files (I've stripped all the parts not related to authentication)

        <behavior name="ServerToServerBehavior" >
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust" revocationMode="Online"/>
            </clientCertificate>
            <serviceCertificate x509FindType="FindByThumbprint" findValue="13a41b3456e431131cd461de"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="myServerAsClientBehaviorConfiguration">
          <clientCredentials>
            <clientCertificate x509FindType="FindByThumbprint" findValue="13a41b3456e431131cd461de" storeLocation="LocalMachine"/>
            <serviceCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust" revocationMode="Online" trustedStoreLocation="LocalMachine"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>

This works perfectly fine on my own dev computer with locally generated X509 certificates, but in my production environment, here's what I get :

Server.Connect : Failed to connect to server Server2 : System.ServiceModel.Security.MessageSecurityException: Identity check failed for outgoing message. The expected DNS identity of the remote endpoint was 'server2.mydomain.com' but the remote endpoint provided DNS claim 'mydomain.com'. If this is a legitimate remote endpoint, you can fix the problem by explicitly specifying DNS identity 'mydomain.com' as the Identity property of EndpointAddress when creating channel proxy.

I've tried to get the server to answer Server2.mydomain.com instead of just mydomain.com, without success. Any hint on how to do this?

I've also tried the solution suggested in the error message, but this seems to have no effect at all (other users seem to have the same problem and I've yet to find a solution). Any idea on how to fix this ?

Edit : I've check with my certificate provider that I can indeed use it for X509 authentication.

Was it helpful?

Solution

I eventually understood why my Identity field was being ignored.

My endpoint was constructed like this :

DistantServer = new ServiceReferenceServerToServer.ServerToServerClient("myServerBinding", "net.tcp://server.mydomain.com/Server");

when the uri parameter is provided, the DNS identity field (defined in the app.config), is overridden as well (even if it's empty, which is the case when we use a string instead of a real URI object).

the solution is to set it programatically using the following code :

        System.ServiceModel.EndpointAddress uri = new System.ServiceModel.EndpointAddress(new Uri("net.tcp://server.mydomain.com/Server"),new System.ServiceModel.DnsEndpointIdentity("mydomain.com"),new System.ServiceModel.Channels.AddressHeader[0]);

        DistantServer = new ServiceReferenceServerToServer.ServerToServerClient("myServerBinding", uri );

OTHER TIPS

I think the DNS claim override the error is talking about would be specified on the client side, not the server, so you're not opening anything up by making that change except that your client could successfully connect to any server in your domain (if it were listening). The error you're seeing is kinda like the message security equivalent of a hostname mismatch on the cert. I've gotten message security to work with wildcard certs after a lot of screwing around, but you might have to do some custom validation work since your cert probably doesn't have the Client Authentication usage specified.

Any reason you're not using Transport security? MUCH simpler to get working unless you've got intermediate Layer7 routing...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top