Hey everyone,
A recent announcement from Let's Encrypt about issuing their first certificate for an IP address sent me down a bit of a rabbit hole. For some reason, I had always assumed that TLS/SSL certificates had to be tied to a domain name. It turns out I was wrong, and it led to a fun learning experience.
After a bit of research, I learned that you can indeed create a certificate for an IP address by using a Subject Alternative Name (SAN) extension. The process involves creating a simple configuration file that specifies the IP address as an alternative name and then using the standard openssl
command-line tool to generate the certificate.
A basic configuration might look something like this:
# example san.cnf
[req]
default_bits = 2048
prompt = no
x509_extensions = v3_req
distinguished_name = dn
req_extensions = v3_req
[dn]
countryName = XX
stateOrProvinceName = N/A
localityName = N/A
organizationName = Self-signed certificate
commonName = 192.168.1.1
[v3_req]
subjectAltName = @alts
[alts]
IP.1 = 192.168.1.1
You then feed this into openssl
to generate your key and certificate files. It's straightforward, but also a bit manual.
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout self-signed-key.pem -out self-signed-cert.pem \
-config san.cnf
Of course, I couldn't just stop there. This seemed like a perfect opportunity to build a more robust tool and really dig into Python's cryptography
library. So, I created san.py
, a command-line utility to make this process much easier.
My script automates the entire process and adds several features:
The core of the script uses the cryptography
library to build the certificate programmatically, which was a great way to learn how x509 certificates are constructed.
# Build SAN extension
if is_ipv4(args.target) or is_ipv6(args.target):
san = x509.SubjectAlternativeName(
[x509.IPAddress(ipaddress.ip_address(args.target))]
)
else:
san = x509.SubjectAlternativeName([x509.DNSName(args.target)])
certificate = build_certificate(private_key, san, args.days, args.target)
You can find the full script and usage instructions on my GitHub Gist: https://gist.github.com/TheCrazyGM/7a90b038be0da792d8f27f3abd3b2145
You might be wondering why you'd want to self-sign a certificate for an IP address. It's actually quite useful for internal and non-public services:
This was a fun project that started with a simple "I didn't know you could do that!" moment. It's a great reminder that there's always something new to learn.
As always,
Michael Garcia a.k.a. TheCrazyGM
I love how you build tools on the fly as you learn and integrate new understanding, very cool. I like the potential applications of this, especially encrypted communication on an internal network. Thanks for sharing your adventure! 😁 🙏 💚 ✨ 🤙