captive

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2019 License: MIT Imports: 11 Imported by: 0

README

go-captive

A very simple library to build captive portals.

go-captive handles the whitelisting, redirection and forwarding of HTTP(s) traffic to a user-defined captive portal. It provides the captive portal developer with the necessary shortcuts to just setup a custom "login" handler to allow/deny client's access to the internet.

The portal works as a man-in-the-middle TCP proxy. Non-allowed clients are forwarded to a handler which triggers an HTTP redirect to the user-provided portal server. This means your application needs to be configured as a traffic proxy, receiving all the traffic of the clients (see below).

Modern software like Firefox or Android should automatically detect a captive-portal and offer the user to redirect to it. Otherwise, any unallowed HTTP traffic will be redirected to the portal. Unallowed HTTPs is terminated.

Usage

See https://godoc.org/github.com/hsanjuan/go-captive for library documentation.

You will need to provide your own Captive Portal Website (TODO: provide an example one), and instantiate captive.Portal as part of your Go application.

Simplest usage:

package main


import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/hsanjuan/go-captive"
)

func loginHandler(r *http.Request) bool {
	// Clicking on a "/login" link will allow traffic for that user.
	return true
}

func main() {
	proxy := &captive.Portal{
		LoginPath:           "/login",
		PortalDomain:        "myCaptivePortalDomain.com",
		AllowedBypassPortal: false,
		WebPath:             "staticContentFolder",
		LoginHandler:        loginHandler,
	}

	// For local debugging, run the website also on a local port.
	go func() {
		http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
			ok := loginHandler(r)
			if ok {
				w.WriteHeader(http.StatusAccepted)
			} else {
				w.WriteHeader(http.StatusUnauthorized)
			}
		})
		fs := http.FileServer(http.Dir("staticContentFolder"))
		http.Handle("/", fs)
		log.Fatal(http.ListenAndServe(":9080", nil))
	}()

	err := proxy.Run()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

Proxy configuration

If you want to run a Wifi hotspot, you can use hostapd and create_ap:

create_ap -d wlan1            wlan0          wlan-name <password>

             ^^hotspot-iface  ^^bridge-iface

Once you have an interface that is receiving all client traffic, you need to forward it to the captive portal so it is allowed or denied. This is usually done with iptables.

This assumes the interface receiving client traffic is ap0 and that the captive portal is running on ports tcp:8080 (http) and tcp:8081 (https).

Run as root:

iface=ap0
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv4.conf.all.send_redirects=0

iptables -I INPUT -p tcp -m tcp --dport 8080 -j ACCEPT
iptables -I INPUT -p tcp -m tcp --dport 8081 -j ACCEPT
iptables -t nat -A PREROUTING -i $iface -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -i $iface -p tcp --dport 443 -j REDIRECT --to-port 8081

Documentation

Overview

Package captive provides a TCP/IP proxy for HTTP/HTTPs traffic controlled by a user-defined captive portal (client-IP based).

In order to use the portal, TCP traffic for ports 80 and 443 must be forwarded to the portal ports (usually this is done using "iptables").

The proxy acts as a man-in-the-middle only letting through HTTP(s) traffic from IPs which have been allowed. Along with the proxy, captive.Portal runs HTTP servers to redirect and serve the portal website, which is user-defined. The portal server handles a login endpoint which allows clients to be whitelisted based on a user-provided function.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Portal

type Portal struct {
	// The TCP port to capture or allow HTTP requests through. 8080 by
	// default.
	HTTPPort int
	// The TCP port to allow HTTPs requests through. 8081 by default.
	HTTPSPort int
	// If you want to serve the portal with HTTPS, set CertFile and KeyFile
	// to a valid path. The certificate must be valid for the PortalDomain.
	CertFile string
	KeyFile  string
	// The path on disk of the Portal website shown to unlogged users and
	// seemingly running on PortalDomain. This should be a folder with at
	// least an index.html in it and is served using http.FileServer.
	WebPath string
	// The path to handle users logins and potentially allow HTTP and HTTPs
	// traffic. POST requests will trigger the LoginHandler and return
	// either 202 (Accepted) or 401 (Unauthorized).
	// GET requests will return 204 for authorized clients, or 403
	// for the rest. This should not be "/".
	LoginPath string
	// The captive's portal domain. Users get redirected here and served
	// the contents from the WebRoot directory. This domain must exist and
	// be resolvable.  Otherwise browsers will not make requests to it.
	PortalDomain string
	// Additonal subdomains to handle (i.e. "www", "login"). Defaults
	// to ["www"].
	PortalSubdomains []string
	// Are allowed clients shown the portal at all or are they let
	// through to the actual real PortalDomain site.
	AllowedBypassPortal bool
	// A Handler for LoginPath. Returns true if the client's traffic
	// should be let through or false otherwise. Not setting this will
	// authenticate all clients that request it.
	LoginHandler func(loginReq *http.Request) bool
	// An optional path to run the user-provided CustomHandler. This
	// allows the Portal to implement any other server-side functionality.
	CustomHandlerPath string
	// An optional custom http.HandleFunc to be called for
	// requests to CustomHandlerPath
	CustomHandler func(w http.ResponseWriter, r *http.Request)
	// contains filtered or unexported fields
}

Portal creates a tcp/ip proxy for HTTP and HTTPs traffic that can be launched with Run(). Clients whose IPs have not been allowed are redirected to the PortalDomain. Clients visiting the PortalDomain will be served the website contents in WebPath.

HTTP POST requests to LoginPath are used to allow clients by executing the LoginHandler function. If successful, traffic from authorized clients is let through to its original destination. GET requests to login path can be used to determine if a user is whitelisted or not.

The captive portal operates on the TCP/IP layer, thus the client IP is used for authentication (and not MAC address -yet).

func (*Portal) Close

func (p *Portal) Close() error

Close shuts down the proxy and the portal servers.

func (*Portal) Run

func (p *Portal) Run() error

Run starts the proxy and captive portal servers. It will throw errors if some Portal fields are not correctly set.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL