Generating Self-Signed SSL Certificates for Public IP Addresses: A Developer’s Guide


4 views

When building demo environments or internal tools on cloud VMs, developers often need SSL encryption for public IP addresses before DNS records are configured. Standard SSL certificates require domain validation, but the following techniques let you secure IP addresses directly.

Create a custom OpenSSL config file (ip_ssl.cnf) with these critical sections:

[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
C = US
ST = California
L = San Francisco
O = YourCompany
CN = 203.0.113.45

[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
IP.1 = 203.0.113.45

Execute these commands sequentially:

# Generate private key (3072-bit for better security)
openssl genrsa -out ip.key 3072

# Create CSR using our custom config
openssl req -new -key ip.key -out ip.csr -config ip_ssl.cnf

# Generate certificate valid for 365 days
openssl x509 -req -days 365 -in ip.csr -signkey ip.key -out ip.crt -extfile ip_ssl.cnf -extensions v3_req

For Nginx:

server {
    listen 443 ssl;
    server_name 203.0.113.45;
    
    ssl_certificate /path/to/ip.crt;
    ssl_certificate_key /path/to/ip.key;
    
    # Recommended SSL settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
}

For Apache:

<VirtualHost 203.0.113.45:443>
    SSLEngine on
    SSLCertificateFile /path/to/ip.crt
    SSLCertificateKeyFile /path/to/ip.key
    
    # Enable HTTP/2 for better performance
    Protocols h2 http/1.1
</VirtualHost>

While self-signed certificates provide encryption, browsers will still show warnings. For temporary demos, you can:

  • Install the certificate in the client's trusted root store
  • Use chrome://flags/#allow-insecure-localhost for Chrome testing
  • Create a test CA and sign your certificate for wider internal trust

For production needs, consider these approaches:

Solution Pros Cons
Let's Encrypt DNS-01 Free, trusted certificates Requires domain control
Internal PKI Full control Maintenance overhead
Reverse Proxy Decouples SSL termination Additional infrastructure

When deploying applications on cloud servers or internal networks, developers often need to secure connections to IP addresses directly. Unlike domain-based certificates, IP address certificates present unique challenges in both generation and browser acceptance.

Most tutorials focus on domain validation because:

  • Browsers expect Subject Alternative Names (SANs) to contain DNS names
  • Certificate Authorities rarely issue IP-based certificates
  • Security policies flag IP-only certificates as suspicious

Create a configuration file ip_ssl.cnf:

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = Server Certificate

[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
IP.1 = 192.168.1.100   # Replace with your public IP

Execute these OpenSSL commands:

# Generate private key
openssl genrsa -out ip.key 2048

# Generate CSR
openssl req -new -key ip.key -out ip.csr -config ip_ssl.cnf

# Generate self-signed certificate
openssl x509 -req -days 365 -in ip.csr -signkey ip.key -out ip.crt -extensions v3_req -extfile ip_ssl.cnf

For Node.js HTTPS server:

const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('ip.key'),
  cert: fs.readFileSync('ip.crt')
};

https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Secure connection established\n');
}).listen(443);

For Nginx configuration:

server {
    listen 443 ssl;
    server_name 192.168.1.100; # Your IP
    
    ssl_certificate /path/to/ip.crt;
    ssl_certificate_key /path/to/ip.key;
    
    # ... rest of your config
}

To prevent browser warnings:

  • Import the certificate into your OS/browser trust store
  • For Chrome, navigate to chrome://flags/#allow-insecure-localhost
  • Consider using a private CA for internal networks

For public-facing services:

  • Use Let's Encrypt DNS challenges
  • Configure a domain with A record pointing to your IP
  • Consider cloud provider's certificate services (AWS ACM, Azure App Service Certificates)