Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 6844

MicroPython • MicroPython HTTPS server

$
0
0
Finding examples of how to create a MicroPython HTTPS Server on a Pico W, 2W or other networked RP2 board, determining the information to do that, is quite challenging and time consuming.

I have therefore published this simple MicroPython HTTPS server example which works for me. It is not much of a server but shows what has to change to handle HTTPS and is a foundation for others to build upon.

The first thing to do is to create a security certificate and key which MicroPython can use and copy that to your RP2 board running MicroPython.

We can create a free self-signed certificate suitable for MicroPython use on your Pi as below -

Code:

openssl ecparam -name prime256v1 -genkey -noout -out ec_key.der -outform DERopenssl req -new -x509 -nodes -key ec_key.der -out ec_cert.der -outform DER -days 3650
You can make it last as long as you would like and pretty much put anything you want into the certificate, though be aware that anyone connecting to it via a browser will be able to see its details. I found the following ideal for my use - Note the full-stop for State or Province Name
Country Name (2 letter code) [AU]:UK
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Self-signed
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:RP2 device
Email Address []:
The certificate and key can be copied to your RP2 board from the command line or by other means -

Code:

mpremote fs cp ec_cert.der :mpremote fs cp ec_key.der :
After that you can load and run the following code, connect to your RP2 using a browser with a URL address of 'https://192.168.0.206' or similar - The code reports what that should be.

Code:

##############################################################################                                                                           ##       HTTPS Web Server Example for MicroPython                            ##                                                                           ##       MIT Licensed : Copyright 2025, "Hippy"                              ##                                                                           ##############################################################################import gcimport networkimport secretsimport socket# .-------------------------------------------------------------------------.# | We will need the Secure Socket Layer 'ssl' module                       |# |-------------------------------------------------------------------------|# |                                                                       # |import ssl                                                                # |# |                                                                       # |# `-------------------------------------------------------------------------'import timeWEB_PAGE = """<!DOCTYPE html><html>  <head>    <title>{COUNT} {IP}</title>    <meta http-equiv="refresh" content="5">  </head>  <body>    {COUNT} {NOW} {ELAPSED}  </body></html>"""print("Connecting to '{}'".format(secrets.ssid))wlan = network.WLAN(network.STA_IF)wlan.config(pm=0xA11140)wlan.active(True)wlan.connect(secrets.ssid, secrets.password)while not wlan.isconnected():    print("  Waiting for connection ...")    time.sleep(1)ip = wlan.ifconfig()[0]print("Connected - Access from a browser using 'https://{}'".format(ip))# .-------------------------------------------------------------------------.# | Listen on Port 443 (HTTPS) rather than Port 80 (HTTP)                   |# |-------------------------------------------------------------------------|# |                                                                       # |adr = socket.getaddrinfo('0.0.0.0', 443)[0][-1]                           # |# |                                                                       # |# `-------------------------------------------------------------------------'skt = socket.socket()skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)skt.bind(adr)skt.listen(1)# .-------------------------------------------------------------------------.# | We need to create a security context from the certificate and key       |# |-------------------------------------------------------------------------|# |                                                                       # |context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)                         # |context.verify_mode = ssl.CERT_NONE                                       # |context.load_cert_chain("ec_cert.der", "ec_key.der")                      # |# |                                                                       # |# `-------------------------------------------------------------------------'count = 0now   = time.time()print("Waiting for connections")while True:    # Maximise memory availability    gc.collect()    # Wait for a connection    client, addr = skt.accept()    try:        # .-----------------------------------------------------------------.        # | Input is from a secure 'wrapped' socket, not 'client'           |        # |-----------------------------------------------------------------|        # |                                                               # |        wrapped = context.wrap_socket(client, server_side=True)           # |        request = wrapped.recv(1024)                                      # |        # |                                                               # |        # `-----------------------------------------------------------------'        # Return a timestamp        was = now        now = time.time()        elapsed = now - was        count += 1        # Form a web page reply        html = WEB_PAGE.replace("{IP}",      str(ip     )) \                       .replace("{COUNT}",   str(count  )) \                       .replace("{NOW}",     str(now    )) \                       .replace("{ELAPSED}", str(elapsed)) \                       .strip()        # Send the reply        # .-----------------------------------------------------------------.        # | Output is through the secure 'wrapped' socket, not 'client'     |        # |-----------------------------------------------------------------|        # |                                                               # |        wrapped.sendall("HTTP/1.0 200 OK\r\n")                            # |        wrapped.sendall("Content-type: text/html\r\n\r\n")                # |        wrapped.sendall(html)                                             # |        wrapped.close()                                                   # |        # |                                                               # |        # `-----------------------------------------------------------------'        # Report the details locally        print("{} {} {}". format(count, now, elapsed))    except Exception as e:        print(e)    client.close()
On the first attempt to connect there will be some "Whoa there!" challenges as the browser asks you to confirm acceptance of the RP2's certificate.

Once that's done, and you have 'accepted the risks' and whatever, things should be plain sailing. Though you might need to power-cycle the RP2 and re-run the server code a few times to get there.

When you are connected you should see a three number report; an incrementing count, the RP2's 'epoch time', and how many seconds since the previous page request was made. The page will be auto-refreshed every 5 seconds so can be left to test the durability of the connection -

CAPTURE.jpg

Note the browser may report the connection as "not secure" because the certificate is self-signed but this does not necessarily mean the connection isn't encrypted.


Please note that while the code appears to work reliably with Firefox from my Windows 10 PC using Chrome from the same causes a considerable number of exceptions. I have no idea why that is.

This may also result in MicroPython / LwIP / whatever dropping packets and exhibiting huge latency issues which no one has so far got to the bottom of. That usually sorts itself out after a while.

YMMV.

Statistics: Posted by hippy — Fri Jun 06, 2025 6:17 pm — Replies 2 — Views 74



Viewing all articles
Browse latest Browse all 6844

Trending Articles