Secure dooropener on ESP8266

Hi,

I build a simple door opener using an ESP8266. Really simple, it runs a webserver and when you request a page the front door is unlock by switching a relay. The link can be opened in a webbrowser but I also build an android/air application to request the link. My code is below.

Very simple but also very… unsecure :frowning:

My question is, what would be an approach to make it more secure ?
Password protection is not really an option because the purpose is to easily open the front door.

Thanks !

(ssid, password and url’s are XXX’ed ;))

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

MDNSResponder mdns;

// Replace with your network credentials
const char* ssid = "XXXXX";
const char* password = "XXXXX";

ESP8266WebServer server(80);

String webPage = "";

int gpio0_pin = 5;

void setup(void){
  
  webPage += "<p><center><a href=\"XXX\"><button style=font-size:200px;width:700px;height:500px><[]></button></a></center></p>";
  
  // preparing GPIOs
  pinMode(gpio0_pin, OUTPUT);
  //digitalWrite(gpio0_pin, HIGH);
  
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  if (mdns.begin("esp8266", WiFi.localIP())) {
    Serial.println("MDNS responder started");
  }
  
  server.on("/", [](){
    server.send(200, "text/html", webPage);
  });
  
  server.on("/XXX", [](){
    server.send(200, "text/html", webPage);
    digitalWrite(gpio0_pin, HIGH);
    delay(500);
    digitalWrite(gpio0_pin, LOW);
  });
  
  server.begin();
  Serial.println("HTTP server started");
}
 
void loop(void){
  server.handleClient();
}

Password protection is not really an option because the purpose is to easily open the front door.

Then, don't store anything valuable in your house.

mrExplore:
I build a simple door opener using an ESP8266.

I suspect it will not be possible to make it sufficiently secure to be acceptable to your home insurance company.

...R

Well, I live in a building with several other people, called, anti-squat i think ?
It's like an abandonned apartment building so it doesn't have to be super tight security.

More like preventing people from accidentally opening it or a port scan on our ip that opens it.

You could use cookies or localstorage to keep a session id, meaning you don't have to enter a password every time. Alternatively, you could have a secret key/password in an app you write yourself.

You can use TLS for the server: HelloServerSecure.ino

Pieter

I found a solution good enough for now.

I have a few buttons (1,2,3 and OK) in the ESP’s html and the user has to enter a code.
The only thing that’s annoying is that when each time a button is pressed the page has to reload :frowning:
Is there some workaround for that ?

My code:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

MDNSResponder mdns;
ESP8266WebServer server(80);

// Replace with your network credentials
const char* ssid = "XXX";
const char* password = "XXX";

//Variables to process input
int arrEnteredCode[] = {0,0,0};
int arrPassCode[] = {X,X,X};
String strReceived; 
int intDigitReceived;
int intIndex = 0;

String strStartSpace = "


";    //3 lines of spacing which are replaced by the entered code
String strStartPage;
String strNewPage;

//Relais connected to:
int gpio0_pin = 5;


void setup(void){
  
  // preparing GPIOs
  pinMode(gpio0_pin, OUTPUT);
  
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  if (mdns.begin("esp8266", WiFi.localIP())) {
    Serial.println("MDNS responder started");
  }
  
  server.on("/", fncIndex); 
  server.on("/c", fncCheckCode);
  
  server.begin();
  Serial.println("HTTP server started");

  strStartPage = "<center><a href=\"c?n=1\"> <button style=font-size:50px;width:50%;height:150> 1 </button>


";
  strStartPage += "<a href=\"c?n=2\"> <button style=font-size:50px;width:50%;height:150> 2 </button>


";
  strStartPage += "<a href=\"c?n=3\"> <button style=font-size:50px;width:50%;height:150> 3 </button>


";
  strStartPage += "<a href=\"c?n=4\"> <button style=font-size:50px;width:50%;height:150> OK </button>


";
  strStartPage += "</a></center>";

}

void fncIndex(){
  Serial.println(server.arg(0) );
  arrEnteredCode[0] = 0;
  arrEnteredCode[1] = 0;
  arrEnteredCode[2] = 0;
  server.send(200, "text/html", strStartSpace + strStartPage);
}

void fncCheckCode(){
  Serial.println(server.arg(0) );
  
  strReceived = server.arg(0);
  intDigitReceived = strReceived.toInt();

  //app wil request /c?n=XXX for instantly opening the door
  if(intDigitReceived == XXX){
      digitalWrite(gpio0_pin, HIGH);
      delay(500);
      digitalWrite(gpio0_pin, LOW);
      arrEnteredCode[0] = 0;
      arrEnteredCode[1] = 0;
      arrEnteredCode[2] = 0;
  }

  
  //if OK is pressed and the code is correct, open the door
  if(intDigitReceived == 4 && arrEnteredCode[0] == arrPassCode[0] && arrEnteredCode[1] == arrPassCode[1] && arrEnteredCode[2] == arrPassCode[2]){
      arrEnteredCode[0] = 0;
      arrEnteredCode[1] = 0;
      arrEnteredCode[2] = 0;
      digitalWrite(gpio0_pin, HIGH);
      delay(500);
      digitalWrite(gpio0_pin, LOW);
      server.send(200, "text/html", strStartSpace + strStartPage);
    }else{
    
        // 3 is the first digit of the passcode, if three is entered start at the beginning of arrEnteredCode  
        if( intDigitReceived == 3){
          arrEnteredCode[0] = 3;
          arrEnteredCode[1] = 0;
          arrEnteredCode[2] = 0;
          intIndex = 1;
        }else{
          arrEnteredCode[intIndex] = intDigitReceived;
          intIndex++;
          if(intIndex == 3){
            intIndex = 0;
          }
        }
      
        //display entered code
        strNewPage = "
<center><font size=\"80\">" + String(arrEnteredCode[0]) + String(arrEnteredCode[1]) + String(arrEnteredCode[2]) + "</font></center>
" + strStartPage;
        server.send(200, "text/html", strNewPage);
    }
  
}
 
void loop(void){
  server.handleClient();
}