2

I want to control my ESP8266 device from my secure website via 2 different ways:

  1. if ESP8266 is connected to internet, commands between website and device will sent over MQTT which as working perfectly as I want to be.
  2. if ESP8266 is disconnected from internet, commands should be handled through HTTP request to local webserver. (Given I'm connected to the same router).

So the website coded this way: if ( there is internet ) { Publish MQTT command } else { Send HTTP request }

When I tested sending HTTP requests: http://192.168.100.100/?led=on I get error message saying Mixed content is blocked given my website is secure while local webserver is not.

Then I tried setting up a secure local webserver on my ESP8266:

  • With Firefox: It's working perfectly.

  • With Chrome:

    GET https://192.168.100.100/?led=off net::ERR_CERT_AUTHORITY_INVALID
    
  • With IPhone Safari: It is not working and I have no mean to debug right now. But I'm suspecting security issues with local webserver.

As I'm targeting IPhone users, and looking for a solution to improve local webserver security or trying another approach.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServerSecure.h>

const char *dname = "esp8266";
const char* ssid = "SSID";
const char* password = "PASS";

BearSSL::ESP8266WebServerSecure server(443);
ESP8266WebServer serverHTTP(80);

int ledPin = 2; 

WiFiClient espClient; 
PubSubClient client(espClient);
WiFiManager wm;

int value;

static const char serverCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIC6jCCAlOgAwIBAgIUZIw0cBcWDPJZe8ZIDu6bDqdwwvwwDQYJKoZIhvcNAQEL
BQAwejELMAkGA1UEBhMCUk8xCjAIBgNVBAgMAUIxEjAQBgNVBAcMCUJ1Y2hhcmVz
dDEbMBkGA1UECgwST25lVHJhbnNpc3RvciBbUk9dMRYwFAYDVQQLDA1PbmVUcmFu
c2lzdG9yMRYwFAYDVQQDDA1lc3A4MjY2LmxvY2FsMB4XDTE5MDQxMzE1NTMzOFoX
DTIwMDQxMjE1NTMzOFowejELMAkGA1UEBhMCUk8xCjAIBgNVBAgMAUIxEjAQBgNV
BAcMCUJ1Y2hhcmVzdDEbMBkGA1UECgwST25lVHJhbnNpc3RvciBbUk9dMRYwFAYD
VQQLDA1PbmVUcmFuc2lzdG9yMRYwFAYDVQQDDA1lc3A4MjY2LmxvY2FsMIGfMA0G
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiZmrefwe6AwQc5BO+T/18IVyJJ007EASn
HocT7ODkL2HNgIKuQCnPimiysLh29tL1rRoE4v7qtpV4069BrMo2XqFvZkfbZo/c
qMcLJi43jSvWVUaWvk8ELlXNR/PX4627MilhC4bLD57VB7Q2AF4jrAVhBLzClqg0
RyCS1yab+wIDAQABo20wazAdBgNVHQ4EFgQUYvIljCgcnOfeRn1CILrj38c7Ke4w
HwYDVR0jBBgwFoAUYvIljCgcnOfeRn1CILrj38c7Ke4wDwYDVR0TAQH/BAUwAwEB
/zAYBgNVHREEETAPgg1lc3A4MjY2LmxvY2FsMA0GCSqGSIb3DQEBCwUAA4GBAI+L
mejdOgSCmsmhT0SQv5bt4Cw3PFdBj3EMFltoDsMkrJ/ot0PumdPj8Mukf0ShuBlL
alf/hel7pkwMbXJrQyt3+EN/u4SjjZZJT21Zbxbmo1BB/vy1fkugfY4F3JavVAQ/
F49UaclGs77AVkDYwKlRh5VWhmnfuXPN6NXkfV+z
-----END CERTIFICATE-----
)EOF";

static const char serverKey[] PROGMEM =  R"EOF(
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKJmat5/B7oDBBzk
E75P/XwhXIknTTsQBKcehxPs4OQvYc2Agq5AKc+KaLKwuHb20vWtGgTi/uq2lXjT
r0GsyjZeoW9mR9tmj9yoxwsmLjeNK9ZVRpa+TwQuVc1H89fjrbsyKWELhssPntUH
tDYAXiOsBWEEvMKWqDRHIJLXJpv7AgMBAAECgYA5Syqu3mAKdt/vlWOFw9CpB1gP
JydvC+KoVvPOysY4mqLFjm4MLaTSjIENcZ1SkxewBubkDHVktw+atgvhfqVD4xnC
ewMpuN6Rku5A6EELhUoDrgMEt6M9D/0/iPaMm3VDtLXJq5SuKTpnM+vyE4/uM2Gu
4COfL4GQ0A5KWTzGcQJBANfpU/kwdZf8/oaOvpNZPGRsryjIXXuWMzKKM+M1RqSA
UQV596MGXjo8k8YG/A99rTmVhbeTMC2/7gIyGTePe/kCQQDAjZg2Ujz7wY3gf1Fi
ZETL7DHsss74sZyWZI490yIX0TQqKpXqEIKlkV+UZTOoSZiAaUyPjokblPmTkKfu
uMyTAkBIBjfS+o1fxC+L53Y/ZRc2UOMlcaFtpq8xftTMSGtmWL+uWf93zJoGR0rs
VkwjRsNQYEaY9Gqv+ESHSvsKg7zRAkEAoOLuhpzqVZThHe5jqumKzjS5dkPlScjl
xIeaji/msa3cf0r73goTj5HLIev5YKi1or3Y+a4oA4LTkifxGTcRvwJBAJB+qUE6
y8y+4yxStsWu362tn2o4EjyPL2UGc40wtlQng2GzPZ20+xVYcLxsJXE5/Jqg8IeI
elVVC46RfjDK9G0=
-----END PRIVATE KEY-----
)EOF";

void showWebpage() {
  int ledStatus = digitalRead(ledPin);

  if (server.hasArg("led")) {
    String status = server.arg("led");
    if (status == "off") {
      digitalWrite(ledPin, HIGH);
      ledStatus = 1;
    }
    else if (status == "on") {
      digitalWrite(ledPin, LOW);
      ledStatus = 0;
    }
  }

  String content = "<!DOCTYPE html><html>";
  content += "<head><title>ESP8266 Test Server</title>";
  content += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">";
  content += "<link rel=\"shortcut icon\" href=\"data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA/4QAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAiIgEQAiAQASAAEAEgAhABAgAQASACARAAIBEQIiAQASACAQACABABIAIAEAAgARACIAABAAIAAAAAAAAAAAAAAAAAAAAAEREAERAAEAAQAAAAAQAQABAAAAABABAAERAAARAAERAQAAAQAAAQARAAABAAABABEREAAREAERCQmQAAZ2YAAGtmAACdEQAAZrsAAGbdAACZ7gAA//8AAP//AAAMdwAAf7cAAH+3AAAecQAAffYAAH32AAAOMQAA\" />";
  content += "<style>body {font-family: sans-serif;} </style>";
  content += "</head><body>";
  content += "<h1>ESP8266 HTTPS Server</h1><form action=\"/\" method=\"get\"><p><b>ledPin</b> LED Status:";

  if (ledStatus) content += " <i>Turned off</i>";
  else content += " <i>Turned on</i>";

  content += "</p>";

  if (ledStatus) content += "<input type=\"submit\" value=\"on\" name=\"led\">";
  else content += "<input type=\"submit\" value=\"off\" name=\"led\">";

  content += "</form>";
  
  content += "<p>";
  time_t now = time(NULL);
  content += ctime(&now);
  content += "</p>";
  
  content += "<p>For more information see <a href=\"https://www.onetransistor.eu/2019/04/https-server-on-esp8266-nodemcu.html\" target=\"_blank\">OneTransistor</a>.</p></body></html>";

  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.sendHeader("Access-Control-Max-Age", "10000");
  server.sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
  server.sendHeader("Access-Control-Allow-Headers", "*");
  server.send(200, "text/html", content);
}

void secureRedirect() {
  serverHTTP.sendHeader("Location", String("https://esp8266.local"), true);
  serverHTTP.send(301, "text/plain", "");
}


void setup() {
  Serial.begin(115200);  pinMode(ledPin, OUTPUT);  digitalWrite(ledPin, LOW);

    // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {    delay(1000);    Serial.println("Connecting to WiFi..");  }
  Serial.print("Connected to WiFi: ");  Serial.println(WiFi.SSID());
  Serial.print("IP: ");  Serial.println(WiFi.localIP());
  
  Serial.print("Server can be accessed at https://");
  Serial.print(WiFi.localIP());
  if (MDNS.begin(dname)) {
   Serial.print(" or at https://");
   Serial.print(dname);
   Serial.println(".local");
  }

  serverHTTP.on("/", secureRedirect);
  serverHTTP.begin();

  server.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
  server.on("/", showWebpage);
  server.begin();
  
}

void loop() {
  serverHTTP.handleClient();
  server.handleClient();
  MDNS.update();
  delay(1000);
}
11
  • Are you using self-signed certificates?
    – Majenko
    Feb 16 at 11:53
  • @Majenko Yes it is self signed
    – ASH
    Feb 16 at 11:56
  • That's probably your problem then: you don't have a valid CA. You should get a proper certificate. letsencrypt.org do them for free, but I usually use certbot to generate and install them automatically - not sure how you'd get the raw certificate files.
    – Majenko
    Feb 16 at 11:58
  • The commonly accepted method for this seems to be to either run your own CA and import that into the systems that will access your devices, or manually import and trust each certificate for your devices into the phone/computer that wants to access it. There is no simple way of using a public CA since they generally need authentication against the domain live on the server, which you can't do.
    – Majenko
    Feb 16 at 13:27
  • 2
    Well, you can't really use a public CA on internal sites, and you don't want to run your own CA or import certificates into your browsers, so that only leaves ditching SSL. Which is pointless in a closed network anyway.
    – Majenko
    Feb 16 at 20:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.