My set up is:
I have a server listener app that only accepts TLS 1.0 connections.
I have a client app that uses SslStream.AuthenticateAsClient to configure a secure connection
I am using WireShark to monitor traffic between client and server
On the client machine I use the SecurityProviders\SCHANNEL\Protocols registry keys to manipulate which version of TLS I want to use. If I force the client to use TLS 1.2 I get the expected error of "The client and server cannot communicate, because they do not possess a common algorithm". However, the only packets that get captured in WireShark are the TCP 3-way handshake.
Conversely, if I explicitly specify Tls1.2 in the call to SslStream.AuthenticateAsClient I see the Client Hello and Server Hello TLS messages in WireShark. And of course, I see the same expected error message as above.
My question is, when I'm only using the Registry to manipulate TLS versions how come I do not see any TLS packets being sent through WireShark? How does Windows/.NET know that the remote server does not support TLS 1.2?
Thanks
Related
I have a C# application making a successful TCP TLS 1.0 connection with mutual authentication to another company's server. It is implemented using SslStream class. We are just one of many clients of this very large organisation.
This TCP link above must undergo TLS 1.2 + SHA2 upgrade. After doing all necessary steps on our side and successful testing with our local servers we are still failing all attempts to connect to the remote server. A lengthy investigation revealed that during TLS Handshake the server is sending to us a certificate request with only option for Signature Hash Algorithm = SHA1-RSA (see picture below). Our cerificate is SHA256. As a result, SslStream is not sending our certificate to the server at all and the server sees this as a Handshake Failure and closes down the connection.
The reason for this nuisance is that our counterparty uses very old (10.x) version of F5 firewall to terminate SSL. It only sends SHA1/RSA Signature Hash Algorithm in the certificate request although it supports the client’s SHA2 certificates.
While admitting the facts above, our counterparty is unable to upgrade F5 soon enough. They suggested to ignore the requested Signature Hash Algorithm and send our SHA256 certificate anyway. Apparently other clients connecting to them were able to do that somehow.
Unfortunately,.Net's SslStream does not provide that level of fine tuning for TLS handshake.
Hence the question: is it possible to ignore the server's request for SHA1RSA-based certificate at all? What options do I have? Are there SslStream alternatives that implement TLS 1.2? Is there an open-source third-party solution? Any suggestion would be helpful. Thanks in advance.
The issue above was eventually resolved without any special code changes: a proxy server added on our side. It took care of communication with the other party. The proxy server is able to ignore the specific SHA1/RSA Signature Hash Algorithm in the incoming certificate request.
I am developing an Xmarain.Forms app to initially work on Android along with a service it will be connecting to. The service is a WCF service and needs to use a secure transport to send messages so is set to use https.
I can correctly connect and use the service with both SoapUI and a console program built using the same client proxy library but when I try using the Xamarin App it fails. When run in the emulator the exception is a TimeoutException but when installed on an actual device the exception is WebException with message of "Error: SecureChannelFailure (The authentication or decryption has failed" with inner exception stack of:
IOException with message "The authentication or decryption has failed"
IOException with message "Error while sending TLS Alert (Fatal:InternalError)"
IOException with message "The authentication or decryption has failed.
IOException with message "Unable to read data from the transport connection: Connection reset by peer"
The full stack trace is included below as attachments. The full code is available at https://github.com/staircase27/WcfXamarinHttpBugExample along with the instructions of how to set it up and use it. The example code has connections using both http and https to show the difference and to show that one works and the other doesn't. I have also checked while testing that the devices can access the service using their web browsers so it's not a firewall or routing issue.
I have also wiresharked the connection to see where exactly the connection is failing and it's failing at the TLS v1.0 level. The app (on both devices I've tested) is sending a Client Hello and the service is responding with a TCP RST packet rather than a Server Hello. I have also performed a connection from the testing device using a web browser that succeeded and the main differences are in the types of encryption supported specifically the app only offers to use
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_DES_CBC_SHA
where as the working connections both used
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
A filtered wireshark with two connections is at https://github.com/staircase27/WcfXamarinHttpBugExample/raw/master/Mobile%20WCF%20https%20Capture%20-%20Filtered.pcapng. The first connection is from the app and fails with a tcp rst. The second is the start of the connection from the android web browser.
I have enabled all versions of TLS and all cypher suites but it hasn't changed the wireshark trace or exception in the app.
I have also checked the SChannel Event Logs as recommended by #tomasr and found the following event:
An SSL client handshake completed successfully. The negotiated cryptographic parameters are as follows. Protocol: TLS 1.0. CipherSuite: 0xc014. Exchange strength: 256
(Before enabling all version of TLS the events were:
An TLS 1.0 connection request was received from a remote client application, but none of the cipher suites supported by the client application are supported by the server. The SSL connection request has failed.
The following fatal alert was generated: 40. The internal error state is 1205.
)
Sadly as none of the suggestions in the comments worked I have had to work around this and am now using a RESTful WCF API and have implemented the client manually using HttpClient.
Due to security reasons, we wanted to disable TLS 1.0 support in our server on OS level (in followign SChannel registry):
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols
But because the SQL Server service won't start with TLS 1.0 disabled, we had to leave the TLS 1.0 enabled on OS level.
What we are trying to do now is to force the usage of TLS 1.2 on application level rather than on OS level.
Our application is Client-Server, running on .NET 4.5.
On the Client, before calling the WCF service, we set:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
That ensures that the Client will send ClientHello message with TLS1.2 protocol.
But on the Server, which is self-hosted WCF service, we do not see how to force the TLS1.2 usage. The SSL/TSL negotiation on the Server side is based on the SChannel registry and thus setting the ServicePointManager.SecurityProtocol does not make any effect.
We would like to inspect the incoming WCF call in our Server code and check what TLS protocol used for the call, and close the connection if it is anything less than TLS1.2.
Is there any way how to get the incoming WCF call SSL/TLS protocol version? Something like HttpContext.WebSocketNegotiatedProtocol?
Have you tried using a custom binding with sslStreamSecurity?
<sslStreamSecurity requireClientCertificate="false" sslProtocols="Tls12" />
I am trying to learn more about websocket and its internal implementations. But still can’nt understand few things. I tried googling for a in-depth explanation, but most of them just gives the high-level overview. Following are my doubts
1. According to what I read, web socket server (C# / C++ implementation) by default uses port 80. Although we can use any port, it’s preferred that we use port 80 as we won’t have any firewall issues. If that’s so, how are we supposed to run both the webserver and web socket server on the same port (80)?
2. Let’s assume that the web socket server is running on port 81 and webserver is running on port 80.
So when the browser issues the initial handshake HTTP request (Upgrade: websocket) , this request sent to port 81. Right? If so, this request (See below) does’nt have any relation to an HTTP protocol. But still we use HTTP protocol headers. Why?
GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com
Why dint they use the same websocket interface currently implemented in most browser to issue a direct TCP/IP connection with the given port, without any HTTP stuff?
3. Is there any packet size limit or data/buffer limit for data sent/received from client/server? If that’s the case, do we need to frame the data and handle it ourselves?
4. Does the websocket server always needs to be a separate service/process? In future will the webserver’s (IIS, apache) will include support for hosting web socket servers within its process space?
By using an HTTP compatible handshake you can integrate a WebSocket handler into your webserver or just have the webserver forward the websocket connection to a dedicated WebSocket server.
The WebSocket handshake uses an HTTP compatible handshake to allow both protocols to be handled easily on the same port and it allows existing firewall configurations to much more easily support WebSocket traffic. In addition, preventing cross-side script attacks in well understood in the context of HTTP requests and so WebSocket leverages that knowledge. Even after the connection is established, WebSocket is not a raw socket connection. It is a message based protocol and therefore requires framing. In addition, the framing is masked when sent from client (browser) to server in order to alleviate fears of a theoretical vulnerability in misbehaving proxies/caches/intermediaries.
There is no limit on message size in the protocol itself. A message can be split into multiple frames. There is a protocol limit to frame size but it's 2^64 bytes. The actual frame size limit will be smaller depending on client/server implementation. If you have multi-megabyte single messages that you want to send you might consider changing your application to use smaller messages to maximize cross-browser and cross-server support.
WebSocket handling can definitely be integrated into web servers and this was very much a scenario envisioned by the working group. For example, consider pywebsocket which is designed to run both standalone or as a mod_python module in Apache. As another example, ASP.NET 4.5 and IIS 8 will have built-in support for WebSockets.
I have a .NET 4.0 application that uses both TCP and UDP to communicate with a server.
The client connects to the server using a TCP connection first, and then they exchange some information via some UDP packets.
The UDP exchange is initiated by the server, which sends a packet to the client. The client receives the packet and responds back to the server, also over UDP.
Sometimes, the server isn't getting the reply. If I recompile the application to target the .NET 2.0 framework, the server always receives the packet.
So to summarize:
When the client is compiled against the 4.0 framework, the server fails to receive the packet pretty regularly.
When the client is compiled against the 2.0 framework, the server always receives the packet.
This behavior is consistent on XP, Vista, and Windows 7.
I know that UDP doesn't guarantee packet delivery, and unfortunately I have no control over this protocol so I can't switch to TCP.
I also know that windows will sometimes drop UDP packets if it needs to refresh the ARP cache, but why does this happen consistently with 4.0 and not 2.0?
I've looked at the 4.0 and 2.0 implementations of the Socket.Send method in Reflector, and they appear identical.