No description
Find a file
gregorio.petruzzi b55dc2e192 fix
2026-01-27 16:19:38 +01:00
backend fix/add: services news, fix some bugs for frontend 2025-12-17 17:14:06 +01:00
middleware fix/add: services news, fix some bugs for frontend 2025-12-17 17:14:06 +01:00
public fix 2026-01-27 16:19:38 +01:00
.DS_Store add: favicon 2025-12-05 20:47:35 +01:00
.gitignore fix: ldap auth admin 2025-10-14 15:24:14 +00:00
config template.yaml test: test with shorewall 2025-12-02 11:42:21 +01:00
README.md Aggiustato le password, messo l'auth per gli admin di adm e aggiunto gli env correttamente 2025-09-19 14:18:25 +00:00
SHOREWALL_SETUP.md test: ipv6 with ipset 2025-12-03 09:48:25 +01:00
start.sh fix: ldap auth admin 2025-10-14 15:24:14 +00:00

Captive Portal con Backend Go & Node.js (con Script di Avvio e Proxy HTTPS Caddy)

Questo progetto implementa un captive portal che, posizionato su un gateway di rete, obbliga gli utenti a effettuare lautenticazione (tramite LDAP interno o registrazione) prima di poter navigare su Internet.
Larchitettura si basa su:

  • Backend Go per la gestione di iptables, autenticazione LDAP, integrazione con Kerberos e database SQLite.
  • Backend Node.js per fornire il frontend (pagine HTML/Tailwind) e alcune API di supporto, inclusa la pagina di amministrazione.
  • Uno script start.sh per avviare entrambi i backend in modo semplice.
  • Un proxy basato su Caddy per gestire lHTTPS e il reverse proxy.
  • Un servizio systemd (opzionale) che monitora e avvia automaticamente lo script start.sh.

Indice

  1. Introduzione Generale
  2. Struttura del Progetto
  3. Backend Go
    • API Principali
    • Regole di iptables
    • Autenticazione LDAP e Kerberos
    • Database SQLite
  4. Backend Node.js
    • Route Principali
    • Frontend (HTML + Tailwind CSS)
  5. Flusso di Autenticazione
  6. Avvio del Progetto
    • Script start.sh
    • Esecuzione come Servizio systemd
    • Esempio di Configurazione Caddy
  7. Conclusioni

1. Introduzione Generale

Il captive portal intercetta il traffico degli utenti su una rete e li reindirizza a uninterfaccia web. Solo dopo lautenticazione (o la registrazione) viene concesso laccesso alla rete. In questo progetto:

  • Il backend in Go si occupa di interagire con iptables, di verificare le credenziali di un utente su un server LDAP e (se necessario) di creare nuove entry su LDAP tramite strumenti FreeIPA.
  • Il backend Node.js fornisce le pagine web di login, registrazione e amministrazione, e si interfaccia col backend Go tramite API REST.

2. Struttura del Progetto

La struttura (semplificata) può apparire così:

/home/debian/adm-wifi-pass/
├── main.go               # Sorgente Go
├── wifi-pass             # Binario Go buildato
├── iptables.db           # Database SQLite
├── frontend/
│   ├── main.js           # Backend Node.js
│   ├── public/           # File statici (HTML, CSS, JS)
│   │   ├── index.html
│   │   ├── register.html
│   │   ├── login_admin.html
│   │   ├── admin.html
│   │   └── ...
│   └── ...
├── start.sh              # Script di avvio
├── Caddyfile             # Configurazione per Caddy (proxy HTTPS)
└── README.md             # Questo file

3. Backend Go

Il backend Go (file main.go, compilato in un binario es. wifi-pass) si occupa di:

  • Aggiunta/Rimozione di regole iptables per consentire o bloccare il traffico.
  • Autenticazione su LDAP interno e (in alcuni casi) Kerberos (UniBo).
  • Salvataggio dati in un database SQLite per:
    • Sessioni di utenti connessi (tabella users).
    • Richieste di registrazione (tabella registrationRequests).
  • Creazione automatica di utenti in LDAP tramite ipa user-add, una volta che lamministratore approva la richiesta.

API Principali

  1. GET /subscribe?mac=&ip=&email=&password=

    • Verifica se lutente (MAC address) è già presente con una sessione attiva.
    • Tenta lautenticazione LDAP (ldapAuth).
    • Se OK, aggiunge le regole iptables (addIptablesRule) e memorizza lutente in DB (addUser).
  2. GET /getmac?ip=

    • Usa ip neigh show per trovare la MAC address associata allIP.
  3. POST /request

    • Inserisce una nuova richiesta di registrazione nella tabella registrationRequests.
  4. POST /auth

    • Esegue lautenticazione Kerberos (UniBo) (kerberosAuth).
    • Restituisce un messaggio di successo o errore.
  5. POST /authorize

    • Riceve un ID di registrationRequests.
    • Crea effettivamente lutente su LDAP (addUserToLDAP) e imposta authorized=true in DB.
  6. GET /users

    • Restituisce la lista di richieste di registrazione.

Regole di iptables

Allaggiunta di un nuovo utente (addIptablesRule), il backend Go inserisce:

-m mac --mac-source <MAC> -j ACCEPT
  (su FORWARD, per consentire il traffico)

-m mac --mac-source <MAC> -p udp -m udp --dport 53 -j RETURN
  (su PREROUTING, per permettere le query DNS)

La funzione removeIptablesRule rimuove queste regole, bloccando nuovamente il traffico.

Autenticazione LDAP e Kerberos

  • ldapAuth(email, password):
    Effettua un bind con credenziali di amministrazione su LDAP, e poi prova il bind con lutente (uid=). Se va a buon fine, lutente è autenticato.

  • kerberosAuth(email, password):
    Usa la libreria gokrb5 per validare credenziali di un account UniBo (es. .@unibo.it). In caso di successo, prosegue con la registrazione nel DB.

Database SQLite

Nella funzione init() vengono create (se non esistono) due tabelle:

CREATE TABLE IF NOT EXISTS users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  email TEXT NOT NULL,
  mac TEXT NOT NULL,
  ip TEXT NOT NULL,
  starttime DATETIME NOT NULL,
  endtime DATETIME
);

CREATE TABLE IF NOT EXISTS registrationRequests (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  nome TEXT NOT NULL,
  cognome TEXT NOT NULL,
  username TEXT NOT NULL,
  email TEXT NOT NULL UNIQUE,
  date DATETIME NOT NULL,
  password TEXT NOT NULL,
  authorized BOOLEAN DEFAULT false
);
  • users traccia le sessioni attive (e storicizzate).
  • registrationRequests elenca le richieste di nuovi account in attesa di approvazione.

4. Backend Node.js

Nella cartella frontend/ è presente il file main.js che avvia un server Express (porta di default 3000). Fornisce:

  1. Servizio di file statici (HTML, CSS, JS) per il captive portal e il pannello admin.
  2. API che fungono da interfaccia tra i form del frontend e il backend Go.

Route Principali

  • GET /api/client-ip
    Raccoglie lIP del client e interroga /getmac sul Go per restituire la MAC address.

  • POST /api/login
    Prende i parametri dal form di login (username, password, mac), li inoltra a /subscribe (Go).

  • POST /api/register
    Inoltra la richiesta di registrazione a /request (Go).

  • POST /api/ldap
    Verifica le credenziali Kerberos su /auth (Go).

  • POST /api/admin/login
    Effettua login amministratore (controllo statico username=admin, password=123) ed emette un token JWT (se voluto).

  • GET /api/users
    Restituisce la lista di richieste di registrazione chiedendola a /users (Go).

  • PUT /api/users/:userId/authorize
    Inoltra /authorize con lID della richiesta da approvare.

Frontend (HTML + Tailwind CSS)

Nella cartella public/ troviamo:

  • index.html: Pagina principale di login del captive portal.
  • register.html: Pagina di registrazione (richiede login Kerberos).
  • login_admin.html: Form di login admin.
  • admin.html: Pannello di amministrazione (filtra e approva le richieste).

5. Flusso di Autenticazione

  1. Connessione: Un utente non autenticato prova a navigare. Le regole iptables reindirizzano il traffico a index.html.
  2. Login: Compila il form (username, password, mac) -> POST /api/login -> Node.js -> Go /subscribe.
    • Go valida su LDAP. Se ok, aggiunge le regole iptables e registra lutente in DB.
    • Lutente ora può navigare.
  3. Registrazione (se lutente non esiste su LDAP):
    • Pagina register.html: chiede un login UniBo (POST /api/ldap -> /auth).
    • Lutente inserisce dati (nome, cognome, email, username, password) -> /api/register -> /request.
    • Viene creata una entry in registrationRequests.
    • Un admin, da admin.html, approva la richiesta (PUT /api/users/:id/authorize -> /authorize), che crea lutente in LDAP (ipa user-add).
    • Ora lutente è authorized=true e potrà loggarsi.

6. Avvio del Progetto

Script start.sh

Allinterno della directory /home/debian/adm-wifi-pass (o dove preferisci), è presente uno script di nome start.sh che automatizza lavvio di entrambi i backend. Esempio:

#!/bin/bash

# Esegui l'applicazione Go
cd /home/debian/adm-wifi-pass &
go build .
sudo /home/debian/adm-wifi-pass/wifi-pass &

# Esegui l'applicazione Node.js
/usr/bin/node /home/debian/adm-wifi-pass/frontend/main.js &

# Attendi che entrambi i processi siano avviati
wait
  1. Compila il codice Go (go build .) per ottenere wifi-pass.
  2. Esegue wifi-pass in background (privilegi iptables -> sudo).
  3. Esegue il backend Node.js (main.js) in background.
  4. wait mantiene lo script in esecuzione fino allinterruzione dei processi.

Utilizzo:

chmod +x /home/debian/adm-wifi-pass/start.sh
/home/debian/adm-wifi-pass/start.sh

Esecuzione come Servizio systemd

Per controllare start.sh con systemd (avvio automatico e riavvio in caso di crash), è possibile usare un file come /etc/systemd/system/captive-portal.service:

[Unit]
Description=Go and Node.js Applications
After=network.target

[Service]
ExecStart=/home/debian/adm-wifi-pass/start.sh
Restart=always
User=debian
Environment=PATH=/usr/bin:/usr/local/bin:/usr/local/go/bin
EnvironmentFile=/home/debian/adm-wifi-pass/frontend/.env
WorkingDirectory=/home/debian/adm-wifi-pass
StandardOutput=syslog
StandardError=syslog

[Install]
WantedBy=multi-user.target

Attiva il servizio con:

sudo systemctl daemon-reload
sudo systemctl enable wifi-pass.service
sudo systemctl start wifi-pass.service

Esempio di Configurazione Caddy

Per esporre lapplicazione in HTTPS, è possibile utilizzare Caddy come reverse proxy. Esempio di Caddyfile:

auth.lab.students.cs.unibo.it {
    reverse_proxy /go http://localhost:8080
    reverse_proxy /node http://localhost:3000
}

Adattalo a seconda di come vuoi mappare le route. Se usi Lets Encrypt, Caddy gestirà automaticamente il certificato HTTPS su auth.lab.students.cs.unibo.it.


7. Esempio di Configurazione iptables Originale

Qui di seguito un esempio di configurazione iptables (iptables-save).
Può essere usata come riferimento o punto di partenza.

# Generated by iptables-save v1.8.9 (nf_tables) on Tue Jan 14 11:28:02 2025
*filter
:INPUT DROP [7370:466327]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [153750:37031040]
-A INPUT -i eth1 -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i eth1 -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i eth1 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i eth1 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i eth1 -p icmp -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth1 -m mac --mac-source 18:fe:34:d3:6a:dc -m comment --comment "Allow ESP for 3d printer" -j ACCEPT
-A FORWARD -i eth1 -m mac --mac-source a0:a3:b3:ff:35:a4 -m comment --comment "Allow Esp32 for Caffe (ESPresso32)" -j ACCEPT
-A FORWARD -i eth1 -m mac --mac-source 10:9a:dd:a0:34:ec -m comment --comment "Allow ADM Wall (Firewall)" -j ACCEPT
-A FORWARD -j DROP
COMMIT
# Completed on Tue Jan 14 11:28:02 2025
# Generated by iptables-save v1.8.9 (nf_tables) on Tue Jan 14 11:28:02 2025
*nat
:PREROUTING ACCEPT [303882:118416308]
:INPUT ACCEPT [11218:719758]
:OUTPUT ACCEPT [7239:522970]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -i eth1 -p udp -m udp --dport 53 -j DNAT --to-destination 130.136.201.190
-A PREROUTING -i eth1 -p tcp -m tcp --dport 53 -j DNAT --to-destination 130.136.201.190
COMMIT
# Completed on Tue Jan 14 11:28:02 2025

8. Conclusioni

Questo progetto offre un esempio completo di captive portal:

  • Backend Go per iptables e interazione con LDAP.
  • Backend Node.js per la parte di frontend, con pagine di login, registrazione e amministrazione.
  • Script di avvio (start.sh) per comodità, monitorato da un servizio systemd (opzionale).
  • Proxy HTTPS tramite Caddy (facoltativo, ma consigliato).

Grazie allintegrazione con un server LDAP (FreeIPA) e un database SQLite, la soluzione risulta autonoma e scalabile. Il pannello di amministrazione consente di approvare nuovi utenti e gestire facilmente la base di iscritti.

Per eventuali customizzazioni (regole iptables, design delle pagine, sicurezza, logging) è sufficiente modificare il codice Go, Node.js o la configurazione di Caddy in base alle necessità.

Buon utilizzo!