Πώς να δημιουργήσετε μια αιχμάλωτη πύλη για την επιχείρησή σας με ένα Raspberry Pi Pico W

Ρίκο σμέουρων pico w captive portal που έχει συσταθεί

Εάν διευθύνετε μια επιχείρηση, τότε η δημιουργία μιας αποκλειστικής πύλης μπορεί να αποτελέσει σημαντικό εργαλείο για το δίκτυό σας. Έτσι, σε αυτό το άρθρο, θα σας δείξω πώς να δημιουργήσετε ένα captive portal με ένα Raspberry Pi Pico W.

Μια δεσμευμένη πύλη παρέχει έναν ασφαλή τρόπο για να προσφέρετε WiFi σε επισκέπτες, πελάτες ή πελάτες. Απαιτεί από τους χρήστες να συνδεθούν ή να πιστοποιήσουν τον εαυτό τους πριν μπορέσουν να χρησιμοποιήσουν το διαδίκτυο.

Σκεφτείτε πώς λειτουργεί σε ένα αεροδρόμιο ή σε μια αλυσίδα καφετεριών.

Μια πύλη αιχμαλωσίας σας επιτρέπει να ελέγχετε και να παρακολουθείτε το δίκτυό σας. Παρέχει επίσης την ευκαιρία να επεκτείνετε το εμπορικό σας σήμα. Μπορείτε να προσαρμόσετε την αιχμάλωτη πύλη με το λογότυπό σας.

Τι κάνει μια αιχμάλωτη πύλη;

Όταν συνδέεστε σε ένα Pico W που λειτουργεί ως σημείο πρόσβασης, δεν θα σας σερβίρεται μια ιστοσελίδα. Με την εφαρμογή μιας πύλης αιχμαλωσίας, μόλις το WiFi συνδεθεί στο hotspot σας, θα εμφανιστεί μια ιστοσελίδα.

Επομένως, μπορείτε να παραλείψετε το βήμα της σύνδεσης στο δίκτυο και, στη συνέχεια, να μεταβείτε στο πρόγραμμα περιήγησής σας και να πληκτρολογήσετε χειροκίνητα μια διεύθυνση IP.

Σε αυτό το σημείο πρέπει να αναγνωρίσω Kevin McAleer για το βίντεο του που χρησιμεύει ως βάση για αυτό το σεμινάριο.

Η δημιουργία ενός captive portal με ένα Pico W είναι μια φανταστική ευκαιρία. Δεν είναι μόνο ότι μια αιχμάλωτη πύλη είναι επιτακτική ανάγκη για το δίκτυο της επιχείρησής σας. A Raspberry Pi Pico W είναι μόλις μερικά ευρώ το πολύ, οπότε πρόκειται επίσης για μια εξαιρετικά αποδοτική λύση.

Στόχοι για αυτό το σεμινάριο

Το σεμινάριο του Kevin σας δείχνει μόνο πώς να ενεργοποιήσετε μια πύλη αιχμαλωσίας σε μια συσκευή Apple.

Αυτό το σεμινάριο θα προχωρήσει περαιτέρω εξηγώντας σας πώς να ενεργοποιήσετε την αναδυόμενη πύλη αιχμαλωσίας σε συσκευές Android, Windows και Apple.

Θα χρησιμοποιήσουμε το Phew της Pimoroni, το οποίο είναι μια βιβλιοθήκη για έναν διακομιστή ιστού Pico W. Είναι κάτι σαν το Express για το NodeJS.

Έχω δοκιμάσει τον κώδικά μου σε τέσσερις συσκευές:

  • Apple iPhone 8 με έκδοση λειτουργικού συστήματος 15.4.1 ✔️
  • Amazon Fire tablet με Android 9 ✔️
  • Windows 10 PC ✔️
  • Google Pixel 6 με Android 13 ✔️
  • Samsung Note 9 με Android 10 ❌

Ο κώδικας λειτούργησε σε όλα, εκτός από το Samsung Note 9, και δεν τον έχω δοκιμάσει στο Linux.

Περιπτώσεις χρήσης;

Αυτό είναι λίγο δύσκολο.

Αρχικά, ήθελα να δημιουργήσω κάτι που θα έκανε Rickroll σε κάποιον, αλλά συνειδητοποίησα ότι δεν μπορώ να ενσωματώσω ένα βίντεο από το YouTube, επειδή δεν θα υπάρχει σύνδεση στο διαδίκτυο, αφού το Pico W δεν έχει σύνδεση στο διαδίκτυο.

Στη συνέχεια, ήθελα να δημιουργήσω μια φορητή ψηφιακή επαγγελματική κάρτα όπου οι άνθρωποι θα μπορούσαν να συνδεθούν με το Pico W και να δουν μερικούς συνδέσμους. Κάτι σαν αυτούς τους καταλόγους με τις συνδέσεις στο Instagram. Και πάλι, χωρίς διαδίκτυο...

Υποθέτω ότι ένα από τα μεγαλύτερα πλεονεκτήματα του Pico W είναι ότι σας επιτρέπει τον ασύρματο έλεγχο των εξαρτημάτων.

Στο το mega-tutorial των εξαρτημάτων μας, μίλησα για το πώς μπορείτε να αποφύγετε τη χρήση φυσικών κουμπιών και κουμπιών για τον έλεγχο των LED, των βομβητών και των σερβομηχανισμών, χρησιμοποιώντας αντ' αυτού μια διεπαφή web. Αν τα εφαρμόσετε αυτά στην πύλη αιχμαλωσίας σας, μπορείτε να ελέγχετε ευκολότερα τις συσκευές σας, καθώς δεν θα χρειάζεται να συνδέεστε στο 192.168.4.1 κάθε φορά που θέλετε να μεταβείτε σε έναν πίνακα ελέγχου.

Φυσικά, θα ήθελα πολύ να ακούσω τι πιστεύετε ότι είναι δυνατό με μια αιχμάλωτη πύλη. Αφήστε ένα σχόλιο παρακάτω!

Πώς να ενεργοποιήσετε το αναδυόμενο παράθυρο

Όταν συνδέεστε σε ένα ασύρματο δίκτυο, οι συσκευές Windows, Android και Apple πραγματοποιούν ping σε διαφορετικούς ιστότοπους.

Κάθε ένα από αυτά τα pings απαιτεί απάντηση. Η σωστή απάντηση ξεκλειδώνει το αναδυόμενο παράθυρο. Δείτε πώς εξελίσσεται η συνομιλία ανάλογα με το λειτουργικό σύστημα:

Microsoft Windows 10

MS: "Psst... είναι /connecttest.txt εκεί;"

Pico W: "Ναι, 200“.

MS: "Εντάξει, πήγαινέ με στο /redirect

Pico W: "Ναι, 302, πηγαίνετε στο http://pico.wireless/ όπου θα σας εξυπηρετήσουμε index.html“.

Amazon Fire Android 9

AMZ: "Psst... /generate_204 εκεί;"

Pico W: "Από προεπιλογή, θα έλεγα 204, αλλά ξέρω ότι αυτό που πραγματικά θέλεις είναι 302 ανακατεύθυνση σε http://pico.wireless/ (η οποία αποδίδει την index.html ή αλλιώς την αιχμάλωτη σελίδα σας)"

Apple iPhone 8 με iOS 15

iPhone: "Είμαι cool και όλα αυτά, έτσι απλά ψάχνω για το αρχείο /hotspot-detect.html

Pico W: "Ναι, πήγαινε στο http://pico.wireless/

iPhone: "αλλά σε εμπιστεύομαι, οπότε θα πάω εκεί τώρα".

Κωδικός απάντησης 200: "OK", 204: "302: "Βρέθηκε".

Όπως μπορείτε να δείτε, διαφορετικές συσκευές ζητούν διαφορετικές διαδρομές και διαφορετικές ιστοσελίδες. Και αν απαντήσετε σωστά, θα ενεργοποιήσουν το αναδυόμενο παράθυρο.

Ακολουθεί μια σύνοψη των στοιχείων που χρειάζεστε για να στείλετε και να λάβετε:

Windows 10

URLΑνταπόκριση ενεργοποίησης
www.msftconnecttest.com/ncsi.txt200 OK
www.msftconnecttest.com/connecttest.txt200 OK
www.msftconnecttest.com/redirect302 ανακατεύθυνση (σε captive portal, π.χ. index.html)

Android 9, 10

URLΑνταπόκριση ενεργοποίησης
connectivitycheck.gstatic.com/generate_204302 ανακατεύθυνση (σε σελίδα πύλης αιχμαλωσίας)

Άλλες εκδόσεις Android ενδέχεται να αναζητούν άλλες διευθύνσεις URL. Πιστεύω ότι οι νεότερες εκδόσεις Android θα έχουν /generate_204 ως εναλλακτική λύση.

Ακολουθούν δύο πηγές για παλαιότερα Android:

https://lemariva.com/blog/2017/11/white-hacking-wemos-captive-portal-using-micropython

https://enterprisenetworkingatlarge.wordpress.com/2018/04/21/captive-portal-detection-on-android-and-others-client-vendors-vs-ap-vendors/

iOS 15

URLΑνταπόκριση ενεργοποίησης
captive.apple.com/hotspot-detect.html200 OK (απάντηση με μια ιστοσελίδα)

Το Samsung Note 9 με Android 10 ήταν το πιο δύσκολο να σπάσει. Φαινομενικά, θα ακολουθούσατε τα τυπικά μοτίβα του Android, αλλά δυστυχώς, τίποτα δεν λειτούργησε!

Κατάφερα να λάβω την προτροπή "Απαιτείται σύνδεση", αλλά μόνο αφού άλλαξα το DNS σε μια δημόσια IP LAN (μια IP εκτός της περιοχής '10.0.0.0/8, 172.16.0.0/12 ή 192.168.0.0/16'). Δείτε αυτό το σχόλιο του Stack Exchange.

Αλλά κάνοντας τα παραπάνω έσπασε η πύλη αιχμαλωσίας κάθε άλλης συσκευής...

Βιβλιοθήκη Pimoroni Phew για την πύλη αιχμαλωσίας Pico W

Pimoroni's Phew Η βιβλιοθήκη καθιστά πολύ πιο εύκολη τη δημιουργία μιας πύλης αιχμαλωσίας, επειδή έχει κάνει όλη τη δύσκολη δουλειά.

Πρώτα, πρέπει να κατεβάσετε τη βιβλιοθήκη. Χρησιμοποίησα την έκδοση 0.0.3 το οποίο μπορείτε να κατεβάσετε εδώ.

Στη συνέχεια, εξάγετε τα αρχεία και ανεβάστε το φάκελο με όνομα Φτου στο Pico W. Προσωπικά, χρησιμοποίησα το Thonny IDE και μπορείτε να μάθετε πώς να ανεβάζετε αρχεία εδώ.

Μέχρι το τέλος του σεμιναρίου, θα πρέπει να έχετε έναν κατάλογο που θα μοιάζει με αυτόν.

Ας κωδικοποιήσουμε το αναδυόμενο hotspot!

Έτσι, επιτρέψτε μου να ξεκινήσω με main.py:

from phew import logging, server, access_point, dns
from phew.template import render_template
from phew.server import redirect

DOMAIN = "pico.wireless"  # This is the address that is shown on the Captive Portal


@server.route("/", methods=['GET'])
def index(request):
    """ Render the Index page"""
    if request.method == 'GET':
        logging.debug("Get request")
        return render_template("index.html")

# microsoft windows redirects
@server.route("/ncsi.txt", methods=["GET"])
def hotspot(request):
    print(request)
    print("ncsi.txt")
    return "", 200


@server.route("/connecttest.txt", methods=["GET"])
def hotspot(request):
    print(request)
    print("connecttest.txt")
    return "", 200


@server.route("/redirect", methods=["GET"])
def hotspot(request):
    print(request)
    print("****************ms redir*********************")
    return redirect(f"http://{DOMAIN}/", 302)

# android redirects
@server.route("/generate_204", methods=["GET"])
def hotspot(request):
    print(request)
    print("******generate_204********")
    return redirect(f"http://{DOMAIN}/", 302)

# apple redir
@server.route("/hotspot-detect.html", methods=["GET"])
def hotspot(request):
    print(request)
    """ Redirect to the Index Page """
    return render_template("index.html")


@server.catchall()
def catch_all(request):
    print("***************CATCHALL***********************\n" + str(request))
    return redirect("http://" + DOMAIN + "/")


# Set to Accesspoint mode
# Change this to whatever Wifi SSID you wish
ap = access_point("Pico W Captive")
ip = ap.ifconfig()[0]
# Grab the IP address and store it
logging.info(f"starting DNS server on {ip}")
# # Catch all requests and reroute them
dns.run_catchall(ip)
server.run()                            # Run the server
logging.info("Webserver Started")

Για να είμαι σαφής, προσάρμοσα αυτόν τον κώδικα από τον Kevin McAleer και τον τροποποίησα για τους σκοπούς μας. Αν θέλετε να παρακολουθήσετε τη λεπτομερή εξήγηση του Kevin για το πώς λειτουργούν τα πράγματα, δείτε αυτό το βίντεο στο YouTube.

Επιτρέψτε μου όμως να αναφερθώ εν συντομία στα διάφορα τμήματα.

Υπάρχουν τρία τμήματα με σχόλια "#android redirects", "#apple redir" και "# microsoft windows redirects". Αυτά τα τμήματα χειρίζονται τις δοκιμές που θέτει κάθε λειτουργικό σύστημα και απαντούν με τη σωστή απάντηση.

Στο τέλος των απαντήσεων, ανακατευθύνονται στο http://{DOMAIN}/, εκτός από τη διαδρομή Apple (επειδή ο Kevin το έγραψε έτσι και αν δεν είναι χαλασμένο...).

Η ανακατεύθυνση σε DOMAIN, δηλωμένο ως "pico.wireless" θα μας έδινε μια λιγότερο αντιαισθητική διεύθυνση URL.

Έτσι, αντί να βλέπουμε "www.msftconnecttest.com" στη γραμμή διευθύνσεων, θα βλέπουμε "pico.wireless" στη γραμμή διευθύνσεων. Φυσικά, αυτό είναι κάτι που πρέπει να έχετε κατά νου για την αιχμάλωτη πύλη της επιχείρησής σας.

Pimoroni Phew μειώνει τον κώδικα που πρέπει να γράψετε

Το ωραίο με το Phew είναι ότι γράφετε σημαντικά λιγότερο κώδικα από ό,τι αν τον γράφατε από την αρχή.

Για παράδειγμα, αν θέλατε να εκκινήσετε το SoftAP στο Pico W, θα γράφατε κώδικα κάπως έτσι:

import network
# start up network in access point mode
wlan = network.WLAN(network.AP_IF)
wlan.config(essid=ssid)
if password:
    wlan.config(password=password)
else:
    wlan.config(security=0)  # disable password
wlan.active(True)
return wlan

Με το Phew του Pimoroni, η επιβάρυνσή σας μειώνεται σε:

ap = access_point("Pico W Captive")

Κατά τη γνώμη μου, το καλύτερο μέρος είναι το dns.run_catchall() συνάρτηση που εκτελεί ένα φορτίο ζωτικής σημασίας, αλλά περίπλοκου κώδικα:

import uasyncio, usocket
from . import logging

async def _handler(socket, ip_address):
  while True:
    try:
      yield uasyncio.core._io_queue.queue_read(socket)
      request, client = socket.recvfrom(256)
      response = request[:2] # request id
      response += b"\x81\x80" # response flags
      response += request[4:6] + request[4:6] # qd/an count
      response += b"\x00\x00\x00\x00" # ns/ar count
      response += request[12:] # origional request body
      response += b"\xC0\x0C" # pointer to domain name at byte 12
      response += b"\x00\x01\x00\x01" # type and class (A record / IN class)
      response += b"\x00\x00\x00\x3C" # time to live 60 seconds
      response += b"\x00\x04" # response length (4 bytes = 1 ipv4 address)
      response += bytes(map(int, ip_address.split("."))) # ip address parts
      socket.sendto(response, client)
    except Exception as e:
      logging.error(e)

def run_catchall(ip_address, port=53):
  logging.info("> starting catch all dns server on port {}".format(port))

  _socket = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM)
  _socket.setblocking(False)
  _socket.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1)
  _socket.bind(usocket.getaddrinfo(ip_address, port, 0, usocket.SOCK_DGRAM)[0][-1])

  loop = uasyncio.get_event_loop()
  loop.create_task(_handler(_socket, ip_address))

Το Phew διευκολύνει επίσης τη σύνταξη δρομολογίων. Το μόνο που έχετε να κάνετε είναι να γράψετε κάτι τέτοιο:

@server.route("/[your_route_here]", methods=["GET"])
def your_function_here(request):
  pass

@server.catchall()
def catchall(request):
  pass

Όπως μπορείτε να δείτε παραπάνω, η δημιουργία μιας διαδρομής είναι πανεύκολη. Το μόνο που χρειάζεται να κάνετε είναι να χρησιμοποιήσετε @server.route, και περάστε μια διαδρομή καθώς και τις μεθόδους. Στη συνέχεια, ορίστε μια συνάρτηση παρακάτω με την αίτημα παράμετρος.

Τέλος, υπάρχει το @server.catchall() η οποία χειρίζεται όλες τις διαδρομές που δεν έχετε εκχωρήσει.

Φτου, το κάνει πολύ εύκολο!

Επισκεφθείτε το Github repo του Phew εδώ.

index.html

Είναι μια πραγματικά απλή απόδειξη της έννοιας index.html που βγάζει ένα <h1> λέγοντας "Pico W Captive Portal".

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Pico W Captive Portal</title>
  </head>
  <body>
    <h1>Pico W Captive Portal</h1>
  </body>
</html>

Συμπέρασμα

Ορίστε λοιπόν. Αυτά είναι όλα όσα πρέπει να ξέρετε για να δημιουργήσετε ένα captive portal σε ένα Pico W για την επιχείρησή σας.

Αν έχετε οποιεσδήποτε ερωτήσεις, μη διστάσετε να μας ενημερώσετε στα σχόλια παρακάτω!

8 Σχόλια

  1. cinos στις Ιανουάριος 8, 2023 στις 4:11 μμ

    Ένας καλός αντικαταστάτης του piratebox (αν και χωρίς δυνατότητα συνομιλίας και μεταφόρτωσης).

  2. OkinKun στις Μάρτιος 31, 2023 στις 5:07 μμ

    Αυτό είναι ακριβώς αυτό που έψαχνα!
    Τα πράγματα λειτουργούν ως επί το πλείστον, ωστόσο ο ιστότοπος δεν εμφανίζεται από μόνος του, και αντ' αυτού βλέπω ένα σφάλμα:

    2023-03-31 12:02:35 [info / 160kB] > GET /generate_204 (302 Found) [236ms]
    Η εξαίρεση της εργασίας δεν ανακτήθηκε
    μέλλον: coro=
    Traceback (πιο πρόσφατη κλήση τελευταία):
    Αρχείο "uasyncio/core.py", γραμμή 1, σε run_until_complete
    Αρχείο "phew/server.py", γραμμή 242, σε _handle_request
    Αρχείο "phew/server.py", γραμμή 161, σε _parse_headers
    ValueError: χρειάζονται περισσότερες από 1 τιμές για την αποσυμπίεση

    Αναρωτιέμαι μήπως έχει να κάνει με το παλιό μου τηλέφωνο που εξακολουθεί να είναι Android 6..

  3. Dingleberry στις Ιούνιος 21, 2023 στις 10:57 μμ

    Πώς θα μπορούσε κανείς να επεξεργαστεί αυτόν τον κώδικα για να συμπεριλάβει τον κώδικα HTML μέσα στο πρόγραμμα; Έκανα μια δοκιμή και δεν λειτούργησε για μένα.

    Βρίσκω τη ροή του προγράμματος πολύ συγκεχυμένη.

    • Adam Bobeck στις Ιούνιος 26, 2023 στις 2:51 μμ

      Γεια σας! Χαίρομαι που θα σας βοηθήσω! Μπορείτε να περιγράψετε το πρόβλημά σας με περισσότερες λεπτομέρειες και να μου πείτε ποια συσκευή χρησιμοποιείτε για την πύλη αιχμαλωσίας;

  4. NewbiePicoWHacker στις Οκτώβριος 1, 2023 στις 3:36 μμ

    Γεια σας! Προσπαθώ να τρέξω αυτό σε ένα Pico W.. το AP ξεκινάει, το DNS ξεκινάει, ο διακομιστής ιστού είτε δεν ξεκινάει ποτέ είτε παίρνει πολύ χρόνο (αρκετά λεπτά) για να ξεκινήσει. Έχετε καμιά ιδέα/υποδείξεις/προτάσεις για το γιατί; Ευχαριστώ!

  5. Prithwiraj Bose στις Νοέμβριος 5, 2023 στις 3:43 μμ

    Μπορείτε να με βοηθήσετε να καταλάβω ποια γραμμή κώδικα επιβάλλει/ανοίγει αυτόματα την πύλη αιχμαλωσίας στο πρόγραμμα περιήγησης του πελάτη, μετά την επιτυχή σύνδεση στο hotspot; Δεν φαίνεται να ανοίγει αυτόματα τίποτα. Συνδέομαι από το φορητό μου υπολογιστή.

  6. Peter στις Νοέμβριος 24, 2023 στις 8:13 μμ

    Ευχαριστώ για την καλή περιγραφή.

    Θα ήθελα να προσθέσω ένα δεύτερο ή και τρίτο SSID στο ίδιο AP. Υπάρχει τρόπος να το κάνω αυτό με το Phew;

    Καμία σκέψη;

    • Toby στις Μάιος 28, 2024 στις 5:13 μμ

      Όχι, θα πρέπει να χρησιμοποιήσετε ένα raspberry pi pico για κάθε ssid.

Αφήστε ένα σχόλιο