Using Let’s Encrypt with pfSense
I had trouble finding a guide for deploying certificates with Let’s Encrypt to pfSense instances (at least a guide without complex or questionable firewall rules going into pfSense), so here’s a guide for using Amazon Route 53 as for domain control validation—even if you don’t use Route 53 for anything else.
For this guide, the goal is deploying valid HTTPS to access the router via router.example.com for clients on the LAN. We’ll use the hostname router and the domain example.com. The domain portion can have more levels, like office.example.com or lax.office.example.com. In any case, replace example.com with whatever you’re using.
Step One: Find the WAN Addresses in pfSense
- Use Interfaces > WAN to look up the WAN IP address(es).
- Note these for use in the next step.
Step Two: Set Up AWS Route 53
- Create a new hosted zone in Route 53 for the domain being used on the pfSense router. Let’s say this is
router.example.com. (The zone in Route 53 should match the router’s fully qualified domain name. If it doesn’t, the pfSense Acme client will run into an issue cleaning up the validation records.) - Add the
Aand/orAAAArecords (as appropriate based on what the pfSense WAN interface uses) to therouter.example.comzone. - Copy the
NSrecords for the new zone in Route 53. Configure these asNSrecords for the base domain. In this case, that means addingNSrecords forroutertoexample.comDNS (which does not need to be in Route 53). - It should now be possible to visit https://router.example.com from the LAN — but with a certificate error.
Step Three: Set Up an AWS IAM Policy
- Obtain the Hosted Zone ID from Route 53 for
router.example.com. - Then, create a new AWS IAM policy, choosing “Create Your Own Policy.” This policy will allows updating the
TXTrecord that Let’s Encrypt’s uses for ACME validation.
IAM Policy Document
Replace HOSTED-ZONE-ID with the one obtained in the first step:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListingHostedDomains",
"Effect": "Allow",
"Action": [
"route53:ListHostedZones"
],
"Resource": "*"
},
{
"Sid": "AlterRouterZone",
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/HOSTED-ZONE-ID"
]
}
]
}Step Four: Configure an AWS User for API Access
- Using AWS IAM, create a user with “Programmatic access.”
- Choose the new policy just created.
- Note the “Access key ID” and the “Secret access key.” We’ll need these when we configure the certificate on pfSense.
Step Five: Configure ACME Client on pfSense
- Go to System > Package Manager > Available Packages.
- Install the “acme” package.
- Go to Services > Acme Certificates > Account Keys > + Add.
- Name the new key.
- Set Acme Server to “Let’s Encrypt Production.”
- Click “Create new account key.”
- Click “Register acme account key.”
- Click “Save.”
Step Five: Configure a Certificate on pfSense
- Go to Services > Acme Certificates > Certificates > + Add.
- Name the new certificate. Something like
router.example.comworks. - Add an entry for
router.example.comto the “Domain SAN list.” Set the Method to “DNS-Amazon Route53.” Set the “Id” to the AWS “Access key ID” and the “Key” to the AWS “Secret access key.” - Optionally, configure the “Actions list” to restart the web interface on certificate renewal.
Step Six: Set pfSense to Use the New Certificate
- Go to System > Advanced.
- Set the SSL Certificate to be the one just created.
- Save.
Step Seven: Set the pfSense Host and Domain
To protect against DNS rebinding, pfSense requires the configured Hostname and Domain to match the one used to access the administrative interface.
- Go to System > General Setup.
- Set Hostname to
router. - Set Domain to
example.com.
It should now be possible to visit https://router.example.com from the LAN — this time with full validation!