Forum Discussion
TLS/1.0, PCI, and a custom message for HTTP response status codes
By June 30, 2018 we would like to turn off TLS/1.0 on all our HTTPS websites, in order to be compliant with PCI requirements.
Instead of just turning TLS/1.0 off, we would like to use that time between now and June 30, 2018 to seamlessly phase the TLS/1.0 out.
To do so, our F5 still supports all TLS protocols (TLS/1.0, TLS/1.1, and TLS/1.2), but only the clients supporting TLS/1.1 and above get the actual website content. Everyone else (clients supporting TLS/1.0 only) gets a custom error page informing them about the browser upgrade requirement.
To achieve that, I'm using the HTTP status code "426 Upgrade Required". Please see:
The expected result is:
HTTP/1.1 426 Upgrade Required
Upgrade: TLS/1.1, HTTP/1.1
Connection: Upgrade
... Human-readable HTML page describing why the upgrade is required
and what to do if this text is seen ...
Unfortunately, F5 gives me the following result:
HTTP/1.1 426 Unknown Code
Upgrade: TLS/1.1, HTTP/1.1
Connection: close
... Human-readable HTML page describing why the upgrade is required
and what to do if this text is seen ...
My iRule looks like this:
Detect TLSv1.0 protocol and send HTTP 426
when HTTP_REQUEST priority 150 {
if { [SSL::cipher version] equals "TLSv1" } {
log local0. "TLS/1.0 connection detected from [IP::client_addr] for [HTTP::host]"
HTTP::respond 426 -version auto content $static::obsolete_browser_page noserver "Upgrade" "TLS/1.1, HTTP/1.1" "Content-Type" "text/html" "Cache-Control" "no-cache" "Retry-After" "60" "Connection" "Close"
event disable
return
}
}
If I use "Connection" "Upgrade" in the HTTP::respond code, as defined in the aforementioned RFC2817, F5 replaces it with Connection: Keep-Alive in the actual response which is being sent back to the client.
My questions are:
Question 1: is there a way in F5 to replace the message in HTTP response, so that it says:
HTTP/1.1 426 Upgrade Required
instead of
HTTP/1.1 426 Unknown Code
Question 2: is there a way to force F5 to send HTTP header that says:
Connection: Upgrade
instead of
Connection: close
or
Connection: Keep-Alive
- BinaryCanary_19Historic F5 Account
this is not very elegant, but:
it may be possible to use SSL::respond which allows you to inject raw payload directly into the SSL layer, if this is something you have room to experiment with.
If you go this route however, you may have to make sure that this connection cannot be used for other requests, as I am not sure what effect injecting data into the stream will have on the HTTP profile state machine. So you should consider, including Connection: close in your response, calling HTTP::disable, Dropping the SSL session with SSL::session invalidate, and closing the TCP connection with TCP::close once done.
Very well versed question, kudos for that.
I fiddled around a bit with this in my lab but came to he same conclusion as you did. Maybe you could have an Apache/NGINX server that could do this for you? Or maybe iRulesLX?
Just brainstorming...
/Patrik
- Simon_BlakelyEmployee
A client capable of TLSv1.2 should not connect as TLSv1.0 in the initial instance, so there should never be a valid reason to try to get a browser to upgrade from TLSv1.0 to TLSv1.2.
The Client Hello contains a protocol_version that specifies the lowest version that the client supports, and a client_version that contains the highest TLS version the client supports. The server then responds with the highest version it supports within those two limits. The result is that the client should always connect with the highest TLS version that the client and server can support.
Any client that connects as TLSv1.0 can only connect at TLSv1.0. Your response should be a 200 Response that informs the customer that they need to upgrade their browser.
I'll also add that RFC2817 was intended to drive a TLS protocol upgrade within an unencrypted tcp connection, similar to STARTTLS, allowing virtual hosting for encrypted connections. The adoption of Server Name Indication for SSL has provided a suitable solution to this problem, so RFC2817 is still a proposal after 17 years with no strong drivers for implementation.
- JurajCirrus
Thank you both, BinaryCanary and Patrik for your responses.
To be honest, I do not feel that comfortable to fiddle around with the payload directly on the SSL layer. Unfortunately, I'm not that skilled with iRules. If you have a working example that I could use or modify, I would definitely give it a try.
Regarding the repurposing Apache/Nginx for this, it would be a step backwards for us, because we've just recently migrated the entire website from NGINX/HAPROXY to F5.
Regarding the iRulesLX, I don't even know what it is; googling it right now :)
- JGCumulonimbus
Here's a quick and easy one for this situation based on the responses above:
when HTTP_REQUEST { switch -exact [SSL::cipher version] { "TLSv1.2" { do nothing } "TLSv1.1" { do nothing } default { HTTP::respond 403 content { Access Denied You are using a Web browser that is not secure for accessing confidential information. Please upgrade to the most recent version./font> } "Content-Type" "text/html" Connection close TCP::close return } } }
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com