16

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

Jaime
  • 5,770
  • 4
  • 23
  • 50
  • Not sure what you mean, but the device will be installed in any kind of network that don't belong to us. Just as you install a WiFi router at your house. – Jaime Jul 04 '18 at 16:38

2 Answers2

9

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.

poke
  • 369,085
  • 72
  • 557
  • 602
  • 1
    Thanks, it works with our existing wildcard certificate. We created the A entry in our DNS with the local address. It actually works. Now buying a different wildcard certificate just for this purpose. – Jaime Jul 04 '18 at 20:14
  • 3
    It's also how Plex did it according to this article: https://blog.filippo.io/how-plex-is-doing-https-for-all-its-users/ – DLight Dec 17 '19 at 21:33
  • 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? – franta kocourek Dec 20 '19 at 10:25
1

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)

araisch
  • 1,727
  • 4
  • 15