# Client SSL Authentication on BIG-IP as in-depth as it can go

**URL:** <https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005>\
**Category:** F5 Technical Articles\
**Tags:** big-ip, ssl, tls, authentication, security\
**Created:** [February 14, 2020, 8:56am UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005 "2020-02-14T08:56:48Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rodrigo\_Albuque](https://avatars.discourse-cdn.com/v4/letter/r/8491ac/32.png) [@Rodrigo\_Albuque](https://community.f5.com/u/Rodrigo_Albuque)\
**Post date:** [February 14, 2020, 8:56am UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/1 "2020-02-14T08:56:48Z")

</div>

## Quick Intro

In this article, I’m going to explain how SSL client certificate authentication works on BIG-IP and explain what actually happens during client authentication as in-depth as I can, showing the TLS headers on Wireshark.

This article is about the client side of BIG-IP (Client SL profile) authenticating a client connecting to BIG-IP.

## The Topology

For reference so we can follow Wireshark output:

 ![image_281020.jpg](https://d20hrnpixdzcsd.cloudfront.net/original/1X/171e3e0d56ecc59c907a630b24a02052e5a6cd4e.jpeg)

## How to Configure Client Certificate Authentication on Client SSL profile

Essentially, what we’re doing here is making BIG-IP verify client’s credentials before allowing the TLS handshake to proceed.

However, such credentials are in the form of a client certificate.

The way to do this is to configure BIG-IP by:

- Adding a CA file to **Trusted Certificate Authorities** ( **ca-file** in **tmsh** ) to validate client certificate
- Optionally adding same CA that signed client certificate to **Advertised Certificate Authorities**
- Enforcing Client Certificate validation by setting **Client Certificate** option on BIG-IP to **require**
- Optionally setting the **Frequency** of such checks if we don’t want to stick to the defaults.

I’ll go through each option now.

## Adding CA file to Trusted Certificate Authorities

![image_281020.gif](https://d20hrnpixdzcsd.cloudfront.net/original/2X/7/74d9be1133bf17607d3b570bb4119313fe3d8a51.gif)

We should add to **Trusted Certificate Authorities** a single certificate file (\*.crt) with one CA or concatenated file with 2 or more CAs with the purpose of validating client certificate, i.e. confirming client’s identity.

Upon receiving client certificate, BIG-IP will go through this list of CAs and confirm client’s identity.

It also has another purpose which is to authenticate BIG-IP to client but it’s out of the scope of this article.

## Optionally add CA file to Advertised Certificate Authorities

**Trusted Certificate Authorities** &nbsp;explicitly tells BIG-IP the CA or chain of CAs it will use to validate client certificate whereas&nbsp; **Advertised Certificate Authorities** tells client in advance what kind of CA BIG-IP trusts so that client can make the decision about which certificate to send to BIG-IP:

![image_281020.gif](https://d20hrnpixdzcsd.cloudfront.net/original/3X/9/a/9a8371f4a5c560b27ca71d5177b3cf3d64b185d9.gif)

### Why would we use Advertised Certificate Authorities?

Let’s imagine a situation where Client’s application has more than one Client Certificate configured.

How is it going to figure out which certificate to send to BIG-IP? That’s where Advertised Certificate Authorities comes to rescue us!

When we add our CA bundle to **Advertised Certificate Authorities** , we’re telling BIG-IP to add it to a header field named **Distinguished Names** within **Certificate Request** message.

I dedicated the **Appendix** section to show you more in-depth how changing **Advertised Certificate Authority** affects **Certificate Request** header.

## Configuring BIG-IP to enforce Client Certificate validation

To enable client certificate authentication on BIG-IP we change Local Traffic&nbsp;››&nbsp;Profiles : SSL : Client&nbsp;›› **Client Certificate** to request:

![image_281020.gif](https://d20hrnpixdzcsd.cloudfront.net/original/2X/7/7f66a98908386390330f36c393025a7d006490b1.gif)

The default is set to **ignore** where client certificate authentication is disabled.

If we truly want to enable client certificate validation we need to select **require**.

The reason why is because **request** makes BIG-IP request a client certificate from the client but BIG-IP will not perform the validation to confirm if the certificate sent is valid in this mode.

The following subsections explain each option.

### Ignore

Client Certificate Authentication is disabled (the default).

BIG-IP never sends **Certificate Request** to client and therefore client does not need to send its certificate to BIG-IP.

In this case, TLS handshake proceeds successfully without any client authentication:

**pcap** :&nbsp;[ssl-sample-peer-cert-mode-ignore.pcap](https://dc2-public.s3.amazonaws.com/ssl-sample-peer-cert-mode-ignore.pcap)

**Wireshark filter used** :&nbsp;frame.number == 5 or frame.number == 6

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/3X/b/5/b529291cbf91f8c74a48e1433e38bccfff7a2a47.png)

### Request

BIG-IP requests Client Certificate by sending **Certificate Request** message but does not check whether client certificate is valid which is not really client authentication, is it?

This means that **ca-file** &nbsp;(Trusted Certificate Authorities in the GUI) will not be used to validate client certificate and we will consider any certificate sent to us to be valid.

For example, in&nbsp;[ssl-sample-peer-cert-mode-request-with-no-client-cert-sent.pcap](https://dc2-public.s3.amazonaws.com/ssl-sample-peer-cert-mode-request-with-no-client-cert-sent.pcap)&nbsp;we now see that BIG-IP sends a&nbsp; **Certificate Request** &nbsp;message and client responds with a&nbsp; **Certificate** &nbsp;message this time:

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/3X/7/a/7a5093d31018512493188ac4f8ad4975455036aa.png)

Because I didn’t add any client certificate to my browser, it sent a blank certificate to BIG-IP.

Again, BIG-IP did not perform any validation whatsoever, so TLS handshake proceeded successfully.

We can then conclude that this setting only makes BIG-IP request client certificate and that’s it.

### Require

It behaves just like **Request** but BIG-IP also performs client certificate validation, i.e. BIG-IP will use CA we hopefully added to **ca-file** (Trusted Certificate Authorities in the GUI) to confirm if client certificate is valid. This means that if we don’t add a CA to Trusted Certificate Authorities ( **ca-file** in tmsh) then validation will fail.

## Setting the Frequency of Client Certificate Requests

This setting specifies the frequency BIG-IP authenticates client by enabling/disabling TLS session resumption.

It has only 2 options:

![image_281020.gif](https://d20hrnpixdzcsd.cloudfront.net/original/3X/4/f/4fc3633d31b0bc90855a4149fd65e66af7017a05.gif)

### once

BIG-IP requests client certificate during first handshake and no longer re-authenticates client as long as TLS session is reused and valid.

The way BIG-IP does it is by using [Session Resumption/Reuse](https://devcentral.f5.com/s/articles/TLS-Stateful-vs-Stateless-Session-Resumption).

During first TLS handshake from client, BIG-IP sends a **Session ID** to Client within **Server Hello** header and in subsequent TLS connections, assuming **session ID** is still in BIG-IP’s cache and client re-sends it back to BIG-IP, then session will be resumed every time client tries to establish a TLS session (respecting cache timeout).

First time client sends **Client Hello** with blank **session ID** as it’s cache is empty and then it is assigned a **Session ID** by BIG-IP ( **409f…** ):

**pcap** :&nbsp;[ssl-sample-clientcert-auth-once-enabled.pcap](https://dc2-public.s3.amazonaws.com/ssl-sample-clientcert-auth-once-enabled.pcap)

**Wireshark filter used:** &nbsp; **filter** :&nbsp;!ip.addr == 172.16.199.254 and frame.number \> 1 and frame.number \< 7

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/3X/0/5/054aecb90b4d5060bc41556ebc8587ad18819a38.png)

**Certificate Request** &nbsp;confirms BIG-IP is trying to authenticate client.

Notice **Session ID** BIG-IP sent to client is **409f7…**

Then when Client tries to go through another TLS handshake and sends above session ID in **Client Hello** (packet #70 below).

BIG-IP then confirms session is being resumed by sending same&nbsp; **session ID** &nbsp;in **Server Hello** back to client:

Wireshark filter used:&nbsp;!ip.addr == 172.16.199.254 and frame.number \> 66 and frame.number \< 73

 ![image_281020.jpg](https://d20hrnpixdzcsd.cloudfront.net/original/3X/f/0/f0e30727ace0b4b002aafb4f7d5e2756f73d8539.jpeg)

This resumed TLS handshake just means we will not go through full handshake and will no longer need to exchange keys, select ciphers or re-authenticate client as we’re reusing those already negotiated in the full TLS handshake where we first received **Session ID 409f…**

### always

BIG-IP requests client certificate, i.e. re-authenticates client at every handshake.

On BIG-IP, this is accomplished by disabling session reuse which makes BIG-IP not to send&nbsp; **Session ID** &nbsp;back to Client in the beginning and forcing a full TLS handshake every time.

**pcap** :&nbsp;[ssl-sample-clientcert-auth-always-enabled.pcap](https://dc2-public.s3.amazonaws.com/ssl-sample-clientcert-auth-always-enabled.pcap)

**Wireshark filter used** : !ip.addr == 172.16.199.254 and ((frame.number \> 1 and frame.number \< 7) or (frame.number \> 74 and frame.number \< 80))

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/2X/6/6d6433dee694394fc6789d984dd426714cab8ede.png)

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/2X/6/6d6433dee694394fc6789d984dd426714cab8ede.png)

## Appendix: Understanding how Advertised Certificate Authority field affects Certificate Request header

For this test, I’ve got the following:

- **myCAbundle.cr** t: concatenation of **root\_ca.crt** and **ltm2.crt** (signed by **root\_ca.crt** )
- **client\_cert.crt** : added to Firefox and signed by **ltm2.crt**

I’ve also added **myCAbundle.crt** to **Trusted Certificate Authorities** so BIG-IP is able to verify that **client\_cert.crt** is valid.

For each test, I will use change **Advertised Certificate Authorities** so we can see what happens.

We’ll go through 3 tests here:

- Setting Advertised Certificate Authority to None
- Setting Advertised Certificate Authority to a certificate that didn’t sign client cert
- Setting Advertised Certificate Authority to a bundle that signed client cert

### Setting Advertised Certificate Authority to None

 ![image_281020.jpg](https://d20hrnpixdzcsd.cloudfront.net/original/2X/a/ab90f9b473369a0fb744a99d6b00f757944ce70f.jpeg)

Note that even though no CA was advertised in **Certificate Request** message, BIG-IP still advertises **Certificate types** &nbsp;and&nbsp; **Signature Hash Algorithms** &nbsp;so that client knows in advance what kind of certificate (RSA, DSS or ECDSA) and hash algorithms BIG-IP supports in advance.

If client certificate had not been signed using any of the certificate types and hashing algorithms listed then handshake would have failed.

However, in this case validation is successful as we can see on **frame #8** that client certificate is RSA type and hashed with SHA1:

**pcap** : [ssl-sample-advcert-none.pcap](https://dc2-public.s3.amazonaws.com/ssl-sample-advcert-none.pcap)

**filter used** : !ip.addr == 172.16.199.254 and frame.number \> 1 and frame.number \< 16

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/1X/dac6246bf2a9b26928577ffce3a9b3a2553fcce8.png)

It’s worth noting that Distinguished Names is NOT populated and has length of zero because we didn’t attach a bundle to **Advertised Certificate Authorities**. In this case, it worked fine because my client browser had only one certificate attached, so it shouldn’t cause a problem anyway.

### Setting Advertised Certificate Authority to a certificate that didn’t sign client cert

**pcap** : [ssl-sample-advcert-default-firefox.pcap](https://dc2-public.s3.amazonaws.com/ssl-sample-advcert-default-firefox.pcap)

**Wireshark filter used** : None

I’ve set Advertised Certificate Authority to **default.crt** as this is NOT the CA that signed client’s certificate:

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/2X/4/429def5cfc4000c0681ffc45b6ef70683ead2732.png)

The difference here when compared to **None** is that now we can see that **Distinguished Names** is now populated with the certificate I added ( **default.crt** ):

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/3X/1/e/1e66256a3c60e7a6f02d89ce7d370c4c7b06848c.png)

However, even though I added the correct certificate to my Firefox browser, it sent a blank certificate instead. Why?

That’s because BIG-IP signalled in **Distinguished Names** that **default.crt** is the CA that signed the certificate BIG-IP is looking for and as Firefox doesn’t have any certificate signed by **default.crt** , it just sent a blank certificate back to BIG-IP.

Also, because BIG-IP is now performing proper validation, i.e. comparing whatever client certificate is sent to it with the CA list added to **Trusted Certificate Authorities** , it knows a blank certificate is not valid and terminates the TLS handshake with a **Fatal Alert**.

### Setting Advertised Certificate Authority to a bundle that signed client cert

**pcap** : &nbsp;[ssl-sample-advcert-ltm2chainedwithrootca.pcap](https://dc2-public.s3.amazonaws.com/ssl-sample-advcert-ltm2chainedwithrootca.pcap)

**filter used** : !ip.addr == 172.16.199.254 and frame.number \> 1

Now I’ve set Advertised Certificate Authority to the correct bundle that signed my client certificate:

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/3X/5/4/54f2add4f4b2bf897ca7d4eae8a7aed510e65b0d.png)

And indeed handshake succeeds because:

- BIG-IP advertises myCAbundle.crt in **Certificate Request \>\> Distinguished Names** header, as per **Advertised Certificate Authority** configuration
- By reading **Distinguished Names** field, Client correctly sends the correct client certificate back to BIG-IP
- BIG-IP correctly validates client certificate using myCAbundle configured on **Trusted Certificate Authorities**

 ![image_281020.png](https://d20hrnpixdzcsd.cloudfront.net/original/2X/7/7d5661a31e53bcc79d5ac06bb9d4816df2f8510e.png)

Hope this article provides some clarification about these mysterious TLS headers.

---

<div class="post-metadata">

**Author:** ![Dan\_Bowman](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Dan\_Bowman](https://community.f5.com/u/Dan_Bowman)\
**Post date:** [February 14, 2020, 9:46am UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/2 "2020-02-14T09:46:42Z")

</div>

Excellent article many thanks - I’ve successfully implemented this in the past but very interesting to see the low detail and associated headers.

---

<div class="post-metadata">

**Author:** ![Rodrigo\_Albuque](https://avatars.discourse-cdn.com/v4/letter/r/8491ac/32.png) [@Rodrigo\_Albuque](https://community.f5.com/u/Rodrigo_Albuque)\
**Post date:** [February 14, 2020, 11:36am UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/3 "2020-02-14T11:36:30Z")

</div>

Thanks Dan, yeah, the idea was more to show the low-level details with headers and stuff as I know this is not something new.

---

<div class="post-metadata">

**Author:** ![Rahul\_Kaul](https://avatars.discourse-cdn.com/v4/letter/r/ea5d25/32.png) [@Rahul\_Kaul](https://community.f5.com/u/Rahul_Kaul)\
**Post date:** [February 16, 2020, 6:01am UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/4 "2020-02-16T06:01:10Z")

</div>

Thanks for the writing the article in such a great detail. Appreciating efforts taken by you to make easily understand the concept.

---

<div class="post-metadata">

**Author:** ![Mayur\_Sutare](https://d1p9zq3aats0t8.cloudfront.net/user_avatar/community.f5.com/mayur_sutare/32/5035_2.png) [@Mayur\_Sutare](https://community.f5.com/u/Mayur_Sutare)\
**Post date:** [February 17, 2020, 4:14am UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/5 "2020-02-17T04:14:47Z")

</div>

Many thanks for sharing this article. very easy to understand it.

---

<div class="post-metadata">

**Author:** ![action](https://avatars.discourse-cdn.com/v4/letter/a/8e8cbc/32.png) [@action](https://community.f5.com/u/action)\
**Post date:** [February 19, 2020, 6:18pm UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/6 "2020-02-19T18:18:25Z")

</div>

Nice article, we use client certificate authentication with APM - but this helps with understand some of the associated LTM pieces.

---

<div class="post-metadata">

**Author:** ![consul\_2019](https://avatars.discourse-cdn.com/v4/letter/c/b487fb/32.png) [@consul\_2019](https://community.f5.com/u/consul_2019)\
**Post date:** [February 24, 2020, 5:12pm UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/7 "2020-02-24T17:12:20Z")

</div>

Very nice/detailed explanation. I did do a lot of troubleshooting on client cert auth before, and was unfamiliar with how exactly Advertised CA field worked. Thanks for detailed explanation.

---

<div class="post-metadata">

**Author:** ![Ramkei](https://avatars.discourse-cdn.com/v4/letter/r/4da419/32.png) [@Ramkei](https://community.f5.com/u/Ramkei)\
**Post date:** [July 19, 2020, 7:52pm UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/8 "2020-07-19T19:52:58Z")

</div>

Many Thanks for ​explaining client mutual auth. How do we validate specific client cert from multiple client certs signed by same CA(s). Example, UAT, Preproduction and production client certs are signed by same CAs. Your help is much appreciated.

---

<div class="post-metadata">

**Author:** ![Danielseyoum](https://avatars.discourse-cdn.com/v4/letter/d/7ab992/32.png) [@Danielseyoum](https://community.f5.com/u/Danielseyoum)\
**Post date:** [September 16, 2021, 8:01pm UTC](https://community.f5.com/t/client-ssl-authentication-on-big-ip-as-in-depth-as-it-can-go/66005/9 "2021-09-16T20:01:00Z")

</div>

Thanks. Very easy to follow and understand.
