Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self-signed certificate for device with local IP

Scenario:

  • We have a device similar to a WiFi router that has UI and API exposed
  • The device will run on any LAN out of our control, just like a WiFi router runs on any house.
  • The device doesn't belong to any domain and is accessed through its IP address (i.e. 192.168.1.100) with a browser.
  • The protocol shall be HTTPS
  • The software used is .net Core/Kestrel on Windows
  • Currently we have warnings in all browsers telling that the device has an invalid certificate.
  • Constraint: The device shall be accessible by any machine (desktop/tablet) and cannot install or configure anything in the client machines.

The question is: What it the best way to remove the warning? We read that there cannot be regular certificates for private/local IPs.

Self-signed certificates seem to work for few days and then the error shows up again.

Local environment

like image 609
Jaime Avatar asked Jul 04 '18 16:07

Jaime


2 Answers

There is no way to issue SSL certificate for an IP address; you have to have an actual name which you create the certificate for. In order to get such a name, you need a DNS. Since you don’t have access to the internal DNS of that local network, you will have to use a public DNS server for this.

This assumes that devices within that network do actually have internet access. If they don’t, then you’re completely out of luck.

If there is internet access, then you can simply make a public (sub-)domain point to your local IP address. Basically, configure the DNS for a domain that you own so that there is an A entry on the domain or one of its subdomains, that points to your local IP address 192.168.1.100.

That way, you can communicate that public domain to others, and when they try to resolve the domain, they will hit the DNS which will give the local IP address. So devices within that network can then get to your device and access it. Since they are accessing it then through that domain, a certificate for that exact domain would be generally accepted.

In theory, this works pretty well. In practice this can be a bit complicated or expensive though. Server certificates expire, so you will have to include the certificate (securely!) inside your device and also provide some means to update it eventually when it would expire. Free certificates, like from letsencrypt, will expire within a few weeks, but money will be able to buy you certificates that expire less quickly.

But in the end, it will still be somewhat painful. But not because of the domain name, but rather because of the certificate – at least if you want a certificate that is automatically trusted. Otherwise, you would be back at the beginning.

like image 122
poke Avatar answered Sep 28 '22 03:09

poke


So If I understand it corretly, without internet access and without access to internal DNS, there is no way to allow clients (within local network) to access a REST api listening on "some" device within the local network over HTTPS. Right?

That is not correct. You can use a wildcard certificate, generated with e.g. openssl and communicate securely over TLS encryption. Just the signing is not trusted, so modern Browsers will show the big warning "Not secure". That is awfully wrong. It is way more secure compared to plain http, because it is not sure you're talking to the server you're expecting but you talk securely encrypted.

In plain http it will be enough to just listen the packets flying by. With https you need to pretend to be the server and issue a certificate and the right endpoints. So a much bigger effort and for most use cases in local networks a sufficient level of security.


Generate Certificate

#!/bin/bash
CONFIG="
HOME            = /var/lib/cert
[ req ]
default_bits        = 4096
default_md          = sha256
distinguished_name  = req_distinguished_name
prompt              = no
x509_extensions         = v3_req
[ req_distinguished_name ]
countryName=        YourCountryCode
stateOrProvinceName=    YourState
localityName=       YourTown
organizationName=   YourCompany
organizationalUnitName= YourUnit
commonName=     *
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = email:whatever@localhost

"

openssl genrsa -out /var/usr/cert/name.key 4096

openssl req -x509 -new -nodes -key /var/usr/cert/name.key \
            -config <(echo "$CONFIG") -days 365 \
            -out /var/usr/cert/name.crt

Apply it to your service.

For browsers it'll show this big ugly message For apps connecting to services you'll often need to set a flag, disabling signing checks like:

  • curl -k or --insecure
  • influx -ssl -unsafeSsl

(google helps for your application)

like image 43
araisch Avatar answered Sep 28 '22 02:09

araisch