Every day we do more and more on the internet. We send messages, shop online, handle financial and sensitive data, and much more. We might not be thinking about what happens between our computer and the website, or, if we’re using an app, how our data are being transferred to the destination. You want this traffic to be as secure as possible.

First and foremost, use common sense when you’re on the internet. Only distribute your sensitive data on sites you can trust and make sure the site or connection is using TLS (or often referred to as SSL) certificates/encryption. If you want to learn more about certificates and how they work, check out this explanation. Citrix has also several resources you should read, including this Citrix networking/TLS best practices article and this blog post.

More and more sites are being encrypted every day. According to Mozilla the web went from 67 percent encrypted page loads to 77 percent in 2018 and this continues to rise. In early 2018, Google Chrome started marking non-SSL sites (HTTP) as unsafe. Also sites without any form of encryption are assigned a lower rank in search engine results. We’re moving from HTTP to HTTPS as default.

Certificates Everywhere

There are many types of TLS certificates. Some certificates cost a lot of money and some are free. Is a free certificate just as good as one you pay for? It depends on the company or website and what kind of data you’re securing. For example, if I’m hosting a website for a bank or an insurance company, I need to make sure that everything checks out, is insured, and that people trust my site. This process of verification, trust, and insurance costs money. However, if I just have a simple website or a blog like my own and I want everything to be encrypted, a cheap or free certificate will suffice.

Let’s Encrypt offers the means to automatically create and utilize a free TLS certificate. There are more than 150 million websites that use a certificate from Let’s Encrypt.

The approach from Let’s Encrypt is a bit different than you might be used to. Like with other standard certificates, you need to create a certificate request and transfer it to the certificate issuer. After a verification you will receive a certificate that you then need to implement. The validity of these certificates is typically around one to three years. Most of the time, this is a manual action that requires your attention.

A Let’s Encrypt certificate can only be requested via the ACME protocol — an automated process. This automated process handles the request, proof of ownership, and certificate transfer. The lifespan of one Let’s Encrypt certificate is limited to 90 days. Then you must repeat this process. Because of this level of automation, you can easily run everything again (typically after 60 days) to replace/renew your certificate.

How Do Let’s Encrypt Certificates Work?

Like with all TLS certificates, at some point in the process you need to prove ownership of the domain you are requesting certificates for. Let’s Encrypt provides you with several automated options to prove ownership. In this blog I’ll explain two:

DNS: Prove ownership by provisioning a DNS (TXT) record under your domain

Prove ownership by provisioning a DNS (TXT) record under your domain HTTP: Prove ownership by provisioning a HTTP resource under a well-known URI somewhere on your webserver

Basically, both HTTP and DNS validation use the same steps:

Request of a certificate, for example “domain.com”. Within the request, you also need to provide some data, like your email address. In return, you’ll receive a unique order ID and data on how to prove ownership. At this point, you need to choose if you want to use the DNS or HTTP method. After you make a choice on how to proceed with the challenge validation, you have to make sure it’s configured correctly. For DNS, create a TXT record, for example “_acme-challenge.domain.com”=”ABCDEF.12345”. For HTTP, create a resource that contains the data “ABCDEF.12345” and is available at the following URI: “http://domain.com/.well-known/acme-challenge/ABCDEF”. When everything is in place, notify Let’s Encrypt so they can perform the challenge validation. Let’s Encrypt will check the TXT record or the HTTP resource and verify if it will return the correct data. If all goes well, this action will result in a certificate for your validated domain “domain.com”. If not, you will get an error message. The last step is clean up on your end. The TXT record or HTTP resource can be removed because this is no longer required. The next time you repeat these steps, new details will be specified.

Note: In 2018 Let’s Encrypt introduced the v2 api (backend system) with the new v2-api. A Wildcard (*.) certificate, which can also be requested next to the single and SAN certificates (multiple DNS records in one certificate). These last two could already be created with the v1-api. The catch with wildcard certificates is that only the DNS challenge can be used.

Now on the fun stuff!

How to Use My “GenLeCertForNS” Script

When I first came in contact with Let’s Encrypt, there weren’t as many tools available as there are today. I needed to create a Linux virtual machine and use it to get the certificates. I needed to transfer it (manually) to my Citrix ADC. After a while I found a PowerShell module that removed the need for the Linux virtual machine, so I started with the very first lines of code for my script.

If only I could use PowerShell to configure the ADC’s responder, load-balancing, and content switching functionality to mimic a webserver to utilize the HTTP challenge validation. And thanks to the NITRO functionality I could use REST! This combination resulted in the “GenLeCertForNS” script as it is today.

Just specify all the required parameters, run the script, and voila, the Citrix ADC has a new certificate! It’s simple as that.

Please note that due to requests of many of you in the community, I have rewritten a large portion of my script to support the v2-api. Only the DNS challenge validation is a valid option to use with wildcard certificates. Although the script allows you to request a wildcard certificate, it will require you to manually configure the TXT record(s) to continue. Unfortunately, there is no standard in configuring DNS records. Each provider uses its own system, and not all have a public API. Maybe this will change in the future, but, for now, this is it.

Also, with the v2 API comes a requirement for .NET 4.7.1 and PowerShell v5.1. If you don’t have it and still want a Let’s Encrypt certificate, you can use an older version of the script that uses the v1 API. You can only generate single/SAN and no wildcard certificates.

If you want to fully automate the process, request a single or SAN certificate and it will automatically use the HTTM challenge validation method.

To generate a production certificate for hostname “domain.com” with alternate names: “sts.domain.com, www.domain.com, vpn.domain.com”, use the email address “hostmaster@domain.com”. At the end store the certificates (pfx with password “P@ssword”) in “C:\Certificates” and upload them to the Citrix ADC and replace the current certificate “san_domain_com”. The Content Switch “cs_domain.com_http” will be used to validate the certificates.

.\GenLeCertForNS.ps1 -CN "domain.com" -EmailAddress "hostmaster@domain.com" -SAN "sts.domain.com","www.domain.com","vpn.domain.com" -PfxPassword "P@ssw0rd" -CertDir "C:\Certificates" -NSManagementURL "http://192.168.100.1" -NSCsVipName "cs_domain.com_http" -NSPassword "P@ssw0rd" -NSUserName "nsroot" -NSCertNameToUpdate "san_domain_com" -Production -Verbose

For another example for generating a (Production) wildcard certificate for hostname “domain.com” with alternate names: “*.domain.com, *.test.domain.com, start by using the email address “hostmaster@domain.com”. At the end store the certificates in “C:\Certificates” and upload them to the Citrix ADC.

.\GenLeCertForNS.ps1 -CN "domain.com" -EmailAddress "hostmaster@domain.com" -SAN "*.domain.com","*.test.domain.com" -PfxPassword "P@ssw0rd" -CertDir "C:\Certificates" -NSManagementURL "http://192.168.100.1" -NSPassword "P@ssw0rd" -NSUserName "nsroot" -NSCertNameToUpdate "san_domain_com" -Production -Verbose

The table below contains all the parameters you can use with the script. The help command will also return all the parameters and options.

* Use the -NSCredential parameter OR -NSUsername & -NSPassword

** Not required when requesting a wildcard certificate

*** Use the -Production switch after you’ve done a successful run of the script. This is to make sure you don’t hit the limits of the production servers.

Where to Find “GenLeCertForNS”

You can find the “GenLeCertForNS” script on GitHub. Do with it as you please! If you want to make modifications or improvements, please let me know! I’m constantly trying to improve it, so any feedback will be welcome!

GenLeCertForNS v2 api

GenLeCertForNS v1 api (older version that only supports the v1 api, or if you have ADC v10.x or lower)

How the Script Works (Under the Hood)

In the last part of this post, I’ll explain in more depth how my script works and how it utilizes Citrix ADC’s responder, load-balancing, and content-switching features (the fun stuff!).

The same steps I covered before on how the challenge validation process works can be applied here.

Request a certificate (for example “domain.com”). Within this request I also need to provide some data like my email address.

In return I will receive a unique order ID and data on how to prove ownership. At this point I need to choose if I want to use the DNS or HTTP challenge validation. Because I specified in this example a “single” record and no wildcard, the HTTP challenge validation is enough.

Note: Before the script continues, it will perform some ADC changes to make sure everything is in place and the challenge validation can continue.

A connection via REST/Nitro is being made to the ADC.

First, we need to create an LB (Load-Balance) VIP (A) , this will be a Non-Addressable LB-VIP.

, this will be a Non-Addressable LB-VIP. For the LB-VIP to receive the UP status, we need to bind a LB Service. The script will create a LB Service (B) with health check turned off and bind it to the LB-VIP (A) .

with health check turned off and bind it to the LB-VIP . Next a Responder Action (C) will be created. The action will contain the result Let’s Encrypt expects “HTTP/1.0 200 OK\r

\r

XXXX”

will be created. The action will contain the result Let’s Encrypt expects “HTTP/1.0 200 OK\r

\r

XXXX” A Responder Policy (D) is required to trigger execute the action created earlier when a specific URL is being triggered. The Policy expression will contain the following expression: “HTTP.REQ.URL.CONTAINS(“.well-known/acme-challenge/XXXX”)”.

is required to trigger execute the action created earlier when a specific URL is being triggered. The Policy expression will contain the following expression: “HTTP.REQ.URL.CONTAINS(“.well-known/acme-challenge/XXXX”)”. The Responder Policy will be bound to the LB-VIP (A) .

. Next a CS (Content Switch) Action (E) is created with the LB-VIP as target — the one created in the beginning (A) .

is created with the LB-VIP as target — the one created in the beginning . A CS Policy (F) is created with the expression “HTTP.REQ.URL.CONTAINS(“well-known/acme-challenge/”)” and Action set to the CS Action (E) . This will ensure that all Let’s Encrypt attempts that match the policy expression will be redirected to the LB-VIP (A) via the CS Action (E) .

is created with the expression “HTTP.REQ.URL.CONTAINS(“well-known/acme-challenge/”)” and Action set to the CS Action . This will ensure that all Let’s Encrypt attempts that match the policy expression will be redirected to the LB-VIP via the CS Action . The CS VIP (F) is an pre-existing VIP we’ll use to bind the CS Policy to.

The following changes are made to the configuration to get everything ready:

Extract the required (HTTP) challenge validation from the received data for record “domain.com”.

Change the Responder Action that it responds with the data specified: “HTTP/1.0 200 OK\r

\r

ABCDEF.12345”

Change the Responder policy expression to the specified data: “HTTP.REQ.URL.CONTAINS(“.well-known/acme-challenge/ABCDEF”)”.

When everything is in place the script will notify Let’s Encrypt that they can perform the challenge validation.

Let’s Encrypt will try to retrieve the data from the provided URI “http://domain.com/.well-known/acme-challenge/ABCDEF”.

Note: If you specified more than one host record, steps 3, 4 and 5 will be repeated until all records have been checked.

If all goes well this action will result in a certificate for the domain “domain.com”.

Now we need to clean up all the changes we made to the Citrix ADC.

Remove the CS Policy binding

Remove CS Policy

Remove CS Action

Remove LB-VIP

Remove LB-Service

Remove Responder Policy

Remove Responder Action

The final step is to upload the certificate to the Citrix ADC.

The script will upload the certificate (pfx) as a BASE64 object via REST.

It’ll then convert the pfx to an encrypted pem file.

Then the certificate will be added or updated, depending on the choices you made.

And finally, the intermediate will be linked to the certificate.

And that’s it!

If you have suggestions or questions, please let me know. You can reach me on Twitter @johnbillekens or via my blog.

Citrix Tech Bytes – Created by Citrix Experts, made for Citrix Technologists! Learn from passionate Citrix Experts and gain technical insights into the latest Citrix Technologies.

Click here for more Tech Bytes and subscribe.

Want specific Tech Bytes? Let us know! tech-content-feedback@citrix.com.