0

I have created a website that will be hosted on an Arduino web server.This is used to convert speech to text, send it back to the Arduino server. The received string is then printed on an LCD. Basically, it is a voice based notice board that can be used in an institution.

To allow access to this website to specific users only, I have created a login form that can be seen in this link: http://176.32.230.47/noticeboard.com/php/index.php

After successful login, it redirects to a page that looks something like this: the mainpage which is in-turn used to access one of the Arduino web servers in the LAN

As evident in this main-page, the buttons for the classes will be used to redirect to the Arduino web-server in that particular class. Let me say the ip address of one such server is 192.168.1.5. The problem is, I don't want other users on the same LAN to be able to access the website hosted on the Arduino by typing it's ip address in their browsers.

How can I make this page on the Arduino web server accessible only after login? It shouldn't be in such a way that by simply typing the ip address of the Arduino, one can access the web page hosted on it. I don't know if Arduino web server can hold php files so that I can include the following piece of code:

session_start();
        if($_SESSION['id']==null)

        header("Location:"name_of_the_file_i_want_to_redirect_to.php");

If the Arduino web-server can be accessed by anyone on the LAN, the whole objective of this log in system is lost. Kindly help me.

PS: The login page and the main-page( the one that is used to re-direct to the appropriate website served by one of the Arduinos in the LAN) are hosted on a different server.

Rakesh V
  • 146
  • 2
  • 16
  • 1
    You should perhaps embed images into your question, rather than linking to other sites which may change in future. You should probably also consider sharing what you have tried already, and the problems you have come across. – Rook Mar 01 '16 at 17:04
  • Thanks, Rook! I will make appropriate edits as soon as possible. – Rakesh V Mar 01 '16 at 17:38

2 Answers2

1

You can not make any web server "unaccessible" within a network. Rather, you shall implement some sort of authorization.

For example, you can make the Arduino code so that it requires some sort of secret to return the full page. If the secret does not match, then Arduino returns a HTTP answer 404 (Not Found) or Not authorized, or something similar.

You can implement this by:

  • having a secret as part of the url of the http request, i.e.: 192.168.0.5?secret=psst
  • or having a secret passed as a cookie (Arduino will get all cookies for the same domain/host when a browser asks for a web page - however this requires that the logon is also on the same domain, i.e. the logon is done in Arduino)

As a simplistic solution, you can use some hardcoded random secret, e.g. 192.168.0.5?secret=2r43REFGWRE34teeswd. This is not a real security measure but works well to avoid accidentally getting to your protected page by anyone.

How it works in real servers

This secret is called session cookie in usual web servers. Normally after login, the web server generates a random session cookie, and that is authenticating the browser to the server. Since the cookie is random, it is very hard to figure out what a valid cookie is. The cookie shall also have an expiration time, disallowing reusing a captured cookie by an attacker later on.

The problem in your case is whether you can validate a session cookie on the Arduino. This would either require the Arduino to access to the main login server which can decide whether a cookie is valid or not, or would require the cookie to be constructed with an additional cryptographic data (this path leads too far... not a task for an Arduino.)

What can you do

Your idea of having the login and having the real site in two different hosts imposes challenges. I suggest that the login system will generate a session cookie, but instead of using it as a cookie, put to the redirect.

Note that this all looks quite ugly, and will not really work once someone starts navigating amongst the pages of 192.168.0.5. Each page GET should be authenticated as well, and to achieve that you may consider using the standard http cookie mechanism. That means that the Arduino side has to use standard cookies once the login secret from the PHP server has been validated.

Considering this mess, would you consider thinking of a different solution?

  • If you would have the login and the whole website on Arduino, that would make things a lot simpler
  • I suggest of not doing a web server on Arduino (except if you do it as a hobbyst project or as a proof of concept). It is very much not built for that. If you want to expose some real-world interface to the web, host the actual web pages in a web server, and make the webserver talk to the Arduino over a separate channel (even a simple serial link would do).
  • how did you plan to access to 192.168.0.5? It will work from the local net only, as it is an internal IP address.
Gee Bee
  • 1,794
  • 15
  • 17
  • Thanks for the prompt reply. I'm a beginner and I don't know how to use cookies yet. However, I have a basic understanding of sessions. What I would like to know is: 1) Can I include php code in the Arduino webserver file index.php ( currently named as index.html ) that checks if a session has started or not. If not, then redirect to login page (that's hosted on a different server) 2) I don't completely understand what you mean by include a secret to serve the webpage. Please consider guiding me on this topic. Thanks for your time ! – Rakesh V Mar 01 '16 at 17:36
  • You can not run PHP on Arduino up to my understanding. However PHP is nothing more than a script language driving what does a server return. As you have your own server on Arduino, you can similarly drive what does it return in C. There is a basic problem with your solution though: the login and the real page are on different servers and therefore the cookie will not work well. It means that instead of adding a cookie at login, you have to explicitly pass the cookie data (aka secret) to Arduino at the redirect. Then Arduino will see the secret in the URL parameter as I wrote above. – Gee Bee Mar 01 '16 at 20:37
  • Thanks! The aim of the project is to have several Arduino web-servers deployed in different classes of my school(say 3 classes). All of these fall under one LAN. Then, a teacher has to choose which class he wishes to make an announcement in. This leads him to the website hosted on the Arduino. It allows converting speech to text that is then displayed as a notice on an LCD. What i don't want happening is this: students on the same LAN accessing this website. So i thought of creating a login page(which i did) that redirects to a main-page allowing the teacher to choose which class he wishes ... – Rakesh V Mar 02 '16 at 08:28
  • ...to make an announcement in. The links on the main-page redirect to the Arduino based web-site in that particular class. I plan to access the Arduino web server by port-forwarding it/ accessing the websites through a device connected to the same LAN. I don't understand how i can pass cookies to the Arduino web-server and how it can extract this data to provide access to the page hosted on it. I don't see any other way how this speech-text data can be displayed on a device.So i found Arduino to be a good solution.The project works good except for the fact that I'm able to access the ... – Rakesh V Mar 02 '16 at 08:35
  • ...page hosted on the Arduino by simply typing it's ip address in my browser. This bypasses all security features incorporated earlier. Please guide me to resources on how i can go about doing this. Thanks for your time ! – Rakesh V Mar 02 '16 at 08:38
  • Cookies are simple text data pieces in key-value pairs. They go with the HTTP protocol. When a browser visits a page, it puts the value of all the cookies valid for the domain of the server to the http request header. When the server answers, it can set cookies also in the response header, and the browser will remember to the value of the cookies. See http://stackoverflow.com/questions/3467114/how-are-cookies-passed-in-the-http-protocol for more. However the cookies will give no help here, as you have a different host for login, and another on the arduino(s). – Gee Bee Mar 03 '16 at 00:58
  • ...and then the very easy solution is to use an URL on the Arduino which can not be just "guessed". This is not an industrial or finance software, so we can live with a naive security solution. I.e. instead of serving the web page in Arduino from the root url, 192.168.0.5, ensure that the web page does have a little tricky url. E.g. 192.168.0.5/wrefFWE3423f3. That's it. Students accidentally navigating to 192.168.0.5 shall get a HTTP error 404, and students will not *guess* that the right url is 192.168.0.5/wrefFWE3423f3. (assume no wifi with WEP, no network analyzer they have) – Gee Bee Mar 03 '16 at 01:01
  • Thanks ! This helped :-) Also, is there any method to grant access to a particular website only if it has been redirected from another website,say www.google.com ? – Rakesh V Mar 03 '16 at 03:19
  • There is no way to detect that reliably. However, as *you* do the redirect, nothing stops you of putting some info to the URL about the source. For example, you can add an URL parameter making the URL 192.168.0.5/wrefFWE3423f3?currentuser=jim from the PHP side. Then on the Arduino side you can get this parameter from the URL when serving the page. Btw, just for the records, *how* do you made a web server from Arduino? (Ethernet shield+some library?) I am using Arduino as an educational platform, and being courious. :) – Gee Bee Mar 03 '16 at 11:58
  • Thanks ! Yeah, I used an ethernet shield to make the Arduino webserver. The html page is loadded in an SD card plugged into the ethernet shield. Here's a link to the tutorial i referred to https://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/ – Rakesh V Mar 03 '16 at 18:41
  • Nice :) Referring to this tutorial in your question would be a really great help. In fact, the problem is that this is not a web server. It is a simple TCP/IP socket server, which returns a web page. The difference is subtle or big - depending your needs. For example, handling of different request urls, handling url params, handling cookies, etc... are all not implemented in the Arduino side, which helps me understanding why you feel lost. – Gee Bee Mar 03 '16 at 20:47
0

Adding a new answer, since a new solution is needed. The Ardunio side is built on this example: https://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/SD-card-web-server/ There is no real HTTP server involved, rather just a no-brainer solution to spit back a web page once an empty line is received in the HTTP request.

HTTP communication

When you ask an url, e.g. http://192.168.0.5, this conversation happens between a browser and your server (left: browser request, right: server response)

GET / HTTP/1.0
<some optional headers what we can ignore>
<empty line>

    HTTP/1.0 200 OK
    <empty line>
    <HTML.. etc... web page content

When you ask a different url, e.g. http://192.168.0.5/mypage?secret=1234, this happens:

GET /mypage?secret=1234 HTTP/1.0
<empty line>

    HTTP/1.0 200 OK
    <content-type and other headers>
    <empty line>
    <HTML.. etc... web page content

Processing the HTTP request

The implementation of the web server is quite simple. It does not actually process the GET request at all, therefore you have no access to the full URL or the URL parameters passed. The Arduino code simply waits for the first empty line - which marks the end of the request - and writes out a http response (HTTP/1.0 200 OK, empty line) then renders the content.

To get some sort of authorization, you shall read the HTTP GET request, and check how it looks like.

  • collect all chars of the first line
  • check if it is a GET request for a known url with a tricky secret
  • if so, use the code in the Arduino example to return a web page
  • if not, return noting. This will cause the browser to time out if a kid just navigates to 192.168.0.5.

In code:

void loop() {
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        String response="";
        while (client.connected()) {
            if (client.available()) {
                char c=client.read();
                if (c=='\n') {
                    // end of the first line
                    break; 
                }
                response+=c;
            }
        }
        if (response.startsWith("GET /mypage?secret=1234") {
            // now wait for the empty line and 
            // serve the web page normally
        }
        else {
            // we won't return anything since this 
            // is a request from a kid
        }
    }
}

Returning a correct HTTP not found error

You can improve this solution by actually returning a HTTP error in case of accessing a wrong url.

Then return instead of 200 OK, a 404 Not found error. This is just a plain text, refer to the example above where instead of 200 OK, a 404 Not found is returned:

GET / HTTP/1.0
<empty line>

    HTTP/1.0 404 Not Found
    <empty line>

A browser will interpret this as a page not found error and renders its error page. You might want to customize the error message by sending back a response body after the new line:

GET / HTTP/1.0
<empty line>

    HTTP/1.0 404 Not Found
    <empty line>
    Kids are not allowed to play with my Arduino!

Feel free to use HTML if you want:

GET / HTTP/1.0
<empty line>

    HTTP/1.0 404 Not Found
    Content-Type: text/html
    <empty line>
    <HTML><BODY><H1>Go away!</H1><P>Kids are not allowed to play with my Arduino!</P></BODY></HTML>

Note: each empty line literally means an empty line. In HTTP, all lines are separated by new line chars, i.e. crlf, or ascii 13 and ascii 10 and empty lines are used to mark the end of the http request header and http response header.

Gee Bee
  • 1,794
  • 15
  • 17