Raspberry PI - Point d'accès avec portail captif

J'ai dans mes cartons une idée depuis longtemps : mettre en place une Raspberry PI (certainement une Zero/Zero W, ou à défaut une A+) en mode "AP" (Access Point) avec un portail captif qui afficherait ce qui est filmé par la caméra.

L'idée étant de mettre en place un système autonome de timelapse grâce à la caméra et de pouvoir vérifier le cadrage de l'ensemble avant de le laisser en place.

Problématique

  1. A l'heure actuelle, la dernière version en date de Raspbian est basé sur Debian Stretch (release du mois d'août 2017).
    Un grand nombre de pages traitant du sujet sont adaptées à la version antérieure, Jessie.

  2. Beaucoup d'exemples mettent en place des systèmes pour se connecter à internet à travers une framboise ainsi paramétrée : je ne souhaite servir que du contenu local.
    Aucun paramétrage iptable à prévoir.

Etapes

Voici les grandes étapes de ce paramétrage :

  • préparation du système
  • installation des dépendances
  • paramétrage des différents outils

remarque :
ce guide ne traitera pas de la partie timelapse et/ou streaming vidéo.
Si jamais vous souhaitez mettre en place une solution de streaming vidéo, vous pouvez vous référer à la page suivante : Raspberry PI : streaming caméra

Préparation du système

L'une des nouveauté introduite par Debian Stretch est Predictable Interface Names
Cela a pour effet de ne plus nommer les interfaces classiquement comme nous avons l'habitude depuis fort longtemps (eth0, wlan0 etc.) et donne des nom du type wl0b2n0 ou encore wlx74da38542ef6
Pas très pratique !
Surtout dans mon cas où je n'aurais qu'une seule interface, donc aucun risque de collision de nom.

Pour désactiver ce comportement, il suffit d'insérer la carte SD contenant votre raspbian fraîchement installée et d'éditer le fichier cmdline.txt pour ajouter l'option net.ifnames=0 (en début ou fin de ligne, peut importe).

Voila à quoi ressemble le mien sur une installation toute fraîche :

net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=ee397c53-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet init=/usr/lib/raspi-config/init_resize.sh

Pour se simplifier l'installation, vous pouvez suivre ce guide
Raspberry PI - Configuration headless
pour rapidement activer le wifi et ssh afin d'avoir une carte rapidement opérationnelle

Vous pouvez à présent remettre votre carte SD en place dans votre framboise et la démarrer.

Installation des dépendances

Nous allons avoir besoin des paquets suivants :

  • hostapd : gestion du point d'accès
  • dnsmasq : serveur DNS/DHCP léger
  • nginx : serveur web léger et rapide
sudo apt install -y hostapd dnsmasq nginx

Configuration

Voici la partie la plus longue : configurer chacun des acteurs entrant en jeu afin de réaliser notre hotspot wifi autonome !

DNS & DHCP

Commencez par éditer le fichier /etc/dhcpcd.conf : c'est ici que nous définission l'adresse IP static de notre framboise.

sudo vim /etc/dhcpcd.conf
interface wlan0
static ip_address=192.168.1.1/24
static routers=192.168.1.1
static domain_name_servers=8.8.8.8

Nous devons ensuite éditer le fichier /etc/dnsmasq.conf pour paramétrer notre serveur DNS.

sudo vim /etc/dnsmasq.conf
log-facility=/var/log/dnsmasq.log
log-queries
# Never forward addresses in the non-routed address spaces.
bogus-priv

# Add other name servers here, with domain specs if they are for
# non-public domains.
server=/localnet/192.168.1.1

# Add local-only domains here, queries in these domains are answered
# from /etc/hosts or DHCP only.
local=/localnet/

# Make all host names resolve to the Raspberry Pi's IP address
address=/#/192.168.1.1

# If you want dnsmasq to listen for DHCP and DNS requests only on
# specified interfaces (and the loopback) give the name of the
# interface (eg eth0) here.
# Repeat the line for more than one interface.
interface=wlan0

# Set the domain for dnsmasq. this is optional, but if it is set, it
# does the following things.
# 1) Allows DHCP hosts to have fully qualified domain names, as long
#     as the domain part matches this setting.
# 2) Sets the "domain" DHCP option thereby potentially setting the
#    domain of all systems configured by DHCP
# 3) Provides the domain part for "expand-hosts"
domain=localnet

# Uncomment this to enable the integrated DHCP server, you need
# to supply the range of addresses available for lease and optionally
# a lease time. If you have more than one network, you will need to
# repeat this for each network on which you want to supply DHCP
# service.
dhcp-range=192.168.1.10,192.168.1.15,1h

# Override the default route supplied by dnsmasq, which assumes the
# router is the same machine as the one running dnsmasq.
dhcp-option=3,192.168.1.1

#DNS Server
dhcp-option=6,192.168.1.1

# Set the DHCP server to authoritative mode. In this mode it will barge in
# and take over the lease for any client which broadcasts on the network,
# whether it has a record of the lease or not. This avoids long timeouts
# when a machine wakes up on a new network. DO NOT enable this if there's
# the slightest chance that you might end up accidentally configuring a DHCP
# server for your campus/company accidentally. The ISC server uses
# the same option, and this URL provides more information:
# http://www.isc.org/files/auth.html
dhcp-authoritative

Il faut également modifier le fichier /etc/hosts et ajouter une ligne à la fin du fichier :

sudo vim /etc/hosts
192.168.1.1     picam.localnet

hostapd

Nous pouvons à présent éditer le fichier /etc/hostapd/hostapd.conf : c'est lui qui va nous permettre de paramétrer notre point d'accès wifi (ssid, mot de passe etc.).

sudo vim /etc/hostapd/hostapd.conf
interface=wlan0
ssid=PiCam
hw_mode=g
channel=6
auth_algs=1
wmm_enabled=0

Il faut ensuite dire à hostapd quel fichier de configuration utiliser :

sudo vim /etc/default/hostapd
DAEMON_CONF="/etc/hostapd/hostapd.conf"

Pour éviter les conflits entre hostapd et wpa, il faut supprimer toute la configuration wifi spécique présent dans le fichier /etc/wpa_supplicant/wpa_supplicant.conf :

sudo vim /etc/wpa_supplicant/wpa_supplicant.conf

Supprimez / commentez toute les définitions de réseau wifi connu et ne laissez que le fichier de base :

country=FR
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

Nginx

Afin de servir du contenu local, j'utilise Nginx comme serveur web.

Commençons par mettre en place la structure de notre serveur :

sudo mkdir /var/www/picam --mode=u+rwx,g+srw,o-w
sudo chown pi:www-data -R /var/www/picam

Puis créer deux fichiers :

  • le premier sera la page de visualisation des images issues de la webcam
  • la seconde est nécessaire pour gérer les périphériques Apple (et il me semble les windows phone également).
vim /var/www/picam/index.html
<html>
  <head>
    <title>PiCam</title>
  </head>
  <body>
    <img src="http://localhost:8080/?action=stream">
  </body>
</html>
vim /var/www/picam/hotspot.html
<html>
  <?xml version="1.0" encoding="UTF-8"?>
  <WISPAccessGatewayParam xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.wballiance.net/wispr_2_0.xsd">
    <Redirect>
      <MessageType>100</MessageType>
      <ResponseCode>0</ResponseCode>
      <VersionHigh>2.0</VersionHigh>
      <VersionLow>1.0</VersionLow>
      <AccessProcedure>1.0</AccessProcedure>
      <AccessLocation>PiCam Network</AccessLocation>
      <LocationName>Picam Network</LocationName>
      <LoginURL>http://picam.localnet/</LoginURL>
    </Redirect>
  </WISPAccessGatewayParam>
</html> 

Il faut à présent configurer Nginx !

sudo vim /etc/nginx/sites-available/picam.conf
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/picam;

    # For iOS
    if ($http_user_agent ~* (CaptiveNetworkSupport) ) {
        return 302 http://picam.localnet/hotspot.html;
    }
    
    # For Android
    location /generate_204 {
        return 302 http://picam.localnet/index.html;
    }

    # For others
    location / {
        return 302 http://picam.localnet/;
    }
}
server {
    listen 80;
    listen [::]:80;

    server_name picam.localnet;
    
    root /var/www/picam;
    
    index index.html;
    
    location / {
        try_files $uri $uri/ /index.html;
    }
}
# on active notre nouveau site
sudo ln -s /etc/nginx/sites-available/picam.conf /etc/nginx/sites-enabled/picam
# on désactive le site par défaut
sudo rm /etc/nginx/sites-enabled/default

Voilà !
Vous pouvez à présent redémarrer votre framboise : vous devriez voir apparaître un nouveau réseau wifi PiCam
Connectez-vous dessus pour voir le contenu filmé par la caméra :)

sources :