mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-31 18:38:10 +00:00 
			
		
		
		
	| @@ -1,77 +0,0 @@ | ||||
| # Copyright (c) Facebook, Inc. and its affiliates. | ||||
| # All rights reserved. | ||||
| # | ||||
| # This source code is licensed under the license found in the | ||||
| # LICENSE file in the root directory of this source tree. | ||||
| # | ||||
|  | ||||
|  | ||||
| include $(TOPDIR)/rules.mk | ||||
|  | ||||
| PKG_NAME:=fbwifi | ||||
| PKG_VERSION:=2 | ||||
| PKG_RELEASE:=0 | ||||
| PKG_LICENSE:=GPL-2.0 | ||||
|  | ||||
| PKG_MAINTAINER:=Simon Kinane <skinane@fb.com> | ||||
|  | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
|  | ||||
| include $(INCLUDE_DIR)/package.mk | ||||
|  | ||||
| define Package/fbwifi | ||||
|   SUBMENU:=Captive Portals | ||||
|   SECTION:=net | ||||
|   CATEGORY:=Network | ||||
|   DEPENDS:=+iptables +luasec +luasocket \ | ||||
| 	+libuci-lua +luaposix \ | ||||
| 	+lua-cjson +uhttpd | ||||
|   TITLE:=Facebook Wi-Fi | ||||
|   PKGARCH:=all | ||||
| endef | ||||
|  | ||||
| define Package/fbwifi/description | ||||
|   Facebook Wi-Fi, an AP authorisation solution | ||||
| endef | ||||
|  | ||||
|  | ||||
| define Package/luci-app-fbwifi | ||||
|   SUBMENU:=3. Applications | ||||
|   SECTION:=luci | ||||
|   CATEGORY:=LuCI | ||||
|   TITLE:=LuCI support for Facebook Wi-Fi | ||||
|   DEPENDS:= \ | ||||
| 	+fbwifi \ | ||||
| 	+luci-base +luci-mod-network +luci-mod-status +luci-theme-bootstrap | ||||
| endef | ||||
|  | ||||
| define Package/luci-app-fbwifi/description | ||||
|   LuCI support for Facebook Wi-Fi | ||||
| endef | ||||
|  | ||||
|  | ||||
| define Package/fbwifi/conffiles | ||||
| /etc/config/fbwifi | ||||
| endef | ||||
|  | ||||
| define Build/Prepare | ||||
| endef | ||||
|  | ||||
| define Build/Configure | ||||
| endef | ||||
|  | ||||
| define Build/Compile | ||||
| endef | ||||
|  | ||||
| define Package/fbwifi/install | ||||
| 	$(INSTALL_DIR) $(1) | ||||
| 	$(CP) ./files/fbwifi/* $(1)/ | ||||
| endef | ||||
|  | ||||
| define Package/luci-app-fbwifi/install | ||||
| 	$(INSTALL_DIR) $(1) | ||||
| 	$(CP) ./files/luci-app-fbwifi/* $(1) | ||||
| endef | ||||
|  | ||||
| $(eval $(call BuildPackage,fbwifi)) | ||||
| $(eval $(call BuildPackage,luci-app-fbwifi)) | ||||
| @@ -1,22 +0,0 @@ | ||||
| # Facebook Wi-Fi v2.0 Reference Implementation for OpenWrt  | ||||
|  | ||||
| ## Getting started | ||||
|  | ||||
| Case studies for OEM customers are available at the official page of [Facebook Wi-Fi](https://www.facebook.com/facebook-wifi). | ||||
|  | ||||
| For OEM engineers, start by reading the init script in [files/etc/init.d/fbwifi](https://github.com/facebookincubator/fbc_owrt_feed/blob/master/fbwifi/files/etc/init.d/fbwifi) | ||||
|  | ||||
| To enable Facebook Wi-Fi, configure the gateway_token in `/etc/config/fbwifi`, and run `fbwifi enable`. | ||||
| To disable Facebook Wi-Fi, run `fbwifi disable`. | ||||
|  | ||||
| ## Contents | ||||
|  | ||||
| The 'files' subdirectory contains two subdirectories, one for the fbwifi | ||||
| package that implements the Facebook Wi-Fi v2.0 standard for OpenWrt, and | ||||
| another one containing a LuCI application to configure Facebook Wi-Fi. | ||||
|  | ||||
| The folder structures follow *nix conventions: | ||||
| - 'etc' is the boot time scripts and configuration | ||||
| - 'usr' contains procedural scripts, lua common code module and GUI prototype for luci | ||||
| - 'www' contains the HTTP endpoints as CGI handlers  | ||||
|  | ||||
| @@ -1,6 +0,0 @@ | ||||
| config fbwifi 'main' | ||||
| 	option enabled '0' | ||||
| 	option gateway_token 'FBWIFI:GATEWAY|123456789|0123456789|abcdeABCDE123456789' | ||||
| 	option http_port '2060' | ||||
| 	option https_port '2061' | ||||
| 	option zone 'lan' | ||||
| @@ -1,10 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| [ "$ACTION" = ifup ] || exit 0 | ||||
|  | ||||
| /etc/init.d/fbwifi enabled || exit 0 | ||||
|  | ||||
| ip route get fibmatch 1.1.1.1 | grep -q "$DEVICE" || exit 0 | ||||
|  | ||||
| logger -t fbwifi "Reloading fbwifi due to $ACTION of $INTERFACE ($DEVICE)" | ||||
| /etc/init.d/fbwifi restart | ||||
| @@ -1,43 +0,0 @@ | ||||
| #!/bin/sh /etc/rc.common | ||||
|  | ||||
| START=90 | ||||
|  | ||||
| USE_PROCD=1 | ||||
|  | ||||
| reload_service() { | ||||
| 	restart | ||||
| } | ||||
|  | ||||
| service_triggers() { | ||||
| 	procd_add_reload_trigger fbwifi | ||||
| } | ||||
|  | ||||
| start_service() { | ||||
|  | ||||
| 	config_load fbwifi | ||||
| 	config_get_bool enabled 'main' 'enabled' '0' | ||||
| 	[ "$enabled" -eq 0 ] && return | ||||
|  | ||||
| 	config_get http_port main http_port | ||||
| 	[ -z "$http_port" ] && { | ||||
| 		logger -t fbwifi "required option http_port not set" | ||||
| 		exit 1 | ||||
| 	} | ||||
|  | ||||
| 	config_get https_port main https_port | ||||
| 	[ -z "$https_port" ] && { | ||||
| 		logger -t fbwifi "required option https_port not set" | ||||
| 		exit 1 | ||||
| 	} | ||||
|  | ||||
| 	logger "[fbwifi] Enabled; starting" | ||||
|  | ||||
| 	mkdir -p /tmp/fbwifi | ||||
|  | ||||
| 	/usr/sbin/fbwifi reload | ||||
|  | ||||
| 	procd_open_instance | ||||
| 	procd_set_param command /usr/sbin/fbwifi_validate_token_db | ||||
| 	procd_set_param respawn 1 300 0 | ||||
| 	procd_close_instance | ||||
| } | ||||
| @@ -1,156 +0,0 @@ | ||||
| -- SPDX-License-Identifier: GPL-2.0-only | ||||
| -- Copyright (c) Facebook, Inc. and its affiliates. | ||||
| -- | ||||
| -- FBWIFI Lua library | ||||
| -- function table | ||||
| local fbwifi = {} | ||||
|  | ||||
| local http = require("ssl.https") | ||||
| local json = require("cjson") | ||||
| local log = require("posix.syslog") | ||||
| local uci = require("uci") | ||||
|  | ||||
| function fbwifi.gateway_token() | ||||
| 	token = uci.get("fbwifi.main.gateway_token") | ||||
| 	if token and string.len(token) > 0 then | ||||
| 		return token | ||||
| 	else | ||||
| 		log.syslog( log.LOG_WARNING, "[fbwifi] UCI option fbwifi.main.gateway_token is missing" ) | ||||
| 		return nil | ||||
| 	end  | ||||
| end | ||||
|  | ||||
| function fbwifi.validate_token( token ) | ||||
|  | ||||
| 	local valid = false | ||||
|  | ||||
| 	if string.len(token or '' ) > 0 then | ||||
|  | ||||
| 	        GATEWAY_TOKEN = fbwifi.gateway_token() | ||||
|  | ||||
| 	        URL="https://api.fbwifi.com/v2.0/token" | ||||
| 	        BODY="token="..token | ||||
| 	        body, code, headers = http.request(URL.."?access_token="..GATEWAY_TOKEN, BODY) | ||||
|  | ||||
| 	        if code==200 then | ||||
| 	                valid = true | ||||
| 	        else | ||||
| 	                log.syslog(log.LOG_WARNING, "[fbwifi] validate_token:"..body) | ||||
| 	        end | ||||
|  | ||||
| 	end | ||||
|  | ||||
| 	return valid | ||||
| end | ||||
|  | ||||
| local mac_to_purge='' | ||||
| function remove_client_by_mac(client) | ||||
| 	state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
|  | ||||
| 	for key, value in pairs(client) do | ||||
| 		if | ||||
| 			key == 'mac' and | ||||
| 			value == mac_to_purge | ||||
| 		then | ||||
| 			log.syslog(log.LOG_INFO, string.format("[fbwifi] Purging DB entry %s for MAC %s", client['.name'] or 'unknown', mac_to_purge) ) | ||||
| 			state:delete("fbwifi", client['.name']) | ||||
| 			return | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function fbwifi.instate_client_rule( token, client_mac ) | ||||
|  | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] Validating client "..client_mac) | ||||
|  | ||||
| 	state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
| 	state_name = "token_" .. token | ||||
|  | ||||
| 	RULE_COND="iptables -w -L FBWIFI_CLIENT_TO_INTERNET -t mangle | grep -i -q \"%s\"" | ||||
| 	RULE_FMT="iptables -w -t mangle -%s FBWIFI_CLIENT_TO_INTERNET -m mac --mac-source \"%s\" -j MARK --set-mark 0xfb" | ||||
| 	local RULE | ||||
|  | ||||
| 	log.syslog(log.LOG_INFO, string.format("[fbwifi] Cleaning DB for MAC %s", client_mac) ) | ||||
| 	mac_to_purge = client_mac | ||||
| 	state:foreach("fbwifi", "client", remove_client_by_mac) | ||||
| 	 | ||||
| 		 | ||||
| 	log.syslog(log.LOG_INFO, string.format("[fbwifi] Adding DB entry %s for MAC %s", state_name, client_mac) ) | ||||
| 	state:set("fbwifi", state_name, "client") | ||||
| 	state:set("fbwifi", state_name, "token", token) | ||||
| 	state:set("fbwifi", state_name, "mac", client_mac) | ||||
| 	state:set("fbwifi", state_name, "authenticated", "true") | ||||
| 				 | ||||
| 	-- verify a rule exists for the given client MAC,  | ||||
| 	--   OR install it | ||||
| 	RULE=string.format(RULE_COND.." || "..RULE_FMT, client_mac, "A", client_mac) | ||||
|  | ||||
| 	log.syslog(log.LOG_INFO, string.format( "[fbwifi] Opening iptables for %s", client_mac ) ) | ||||
| 	res = os.execute(RULE) | ||||
| 	if res ~= 0 then  | ||||
| 		log.syslog(log.LOG_WARNING, string.format( "[fbwifi] Failed to update iptables (%s)", res ) ) | ||||
| 	end | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] "..RULE) | ||||
|  | ||||
| 	state:save('fbwifi') | ||||
| 	state:commit('fbwifi') | ||||
| end | ||||
|  | ||||
| function fbwifi.revoke_client_rule( token ) | ||||
|          | ||||
|         if (token == nil) then | ||||
|                 log.syslog(log.LOG_INFO, "[fbwifi] Invalidating token, but token is Nil") | ||||
|                 return | ||||
|         end | ||||
|  | ||||
| 	log.syslog(log.LOG_INFO, string.format( "[fbwifi] Invalidating token (%s)", token) ) | ||||
|  | ||||
| 	state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
| 	state_name = "token_" .. token | ||||
| 	 | ||||
| 	client_mac = state:get("fbwifi", state_name, "mac") | ||||
|  | ||||
| 	if client_mac then | ||||
| 		RULE_COND="iptables -w -L FBWIFI_CLIENT_TO_INTERNET -t mangle | grep -i -q \"%s\"" | ||||
| 		RULE_FMT="iptables -w -t mangle -%s FBWIFI_CLIENT_TO_INTERNET -m mac --mac-source \"%s\" -j MARK --set-mark 0xfb" | ||||
|  | ||||
| 		-- verify a rule exists for the given client MAC,  | ||||
| 		--  AND delete it | ||||
| 		RULE=string.format(RULE_COND.." && "..RULE_FMT, client_mac, "D", client_mac) | ||||
|  | ||||
| 		res = os.execute(RULE) | ||||
| 		if res ~= 0 then  | ||||
| 			log.syslog(log.LOG_WARNING, string.format( "[fbwifi] Failed to update iptables (%s)", res ) ) | ||||
| 		end | ||||
| 		log.syslog(log.LOG_INFO, "[fbwifi] "..RULE) | ||||
|  | ||||
| 		state:delete("fbwifi", state_name) | ||||
| 		state:save('fbwifi') | ||||
| 		state:commit('fbwifi') | ||||
| 	else | ||||
| 		log.syslog(log.LOG_WARNING, string.format( "[fbwifi] Client MAC not found in DB (%s)", state_name ) ) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function fbwifi.reset() | ||||
|  | ||||
| 	local success = false | ||||
|         GATEWAY_TOKEN = fbwifi.gateway_token() | ||||
|         URL="https://api.fbwifi.com/v2.0/gateway/reset" | ||||
| 	BODY="{}" | ||||
|         body, code, headers = http.request(URL.."?access_token="..GATEWAY_TOKEN, BODY) | ||||
|  | ||||
|         if code==200 then | ||||
|                 log.syslog(log.LOG_INFO, "[fbwifi] Reset committed") | ||||
|                 success = true | ||||
|         else | ||||
|                 log.syslog(log.LOG_WARNING, "[fbwifi] Reset failed : "..body) | ||||
|         end | ||||
|  | ||||
| 	return success | ||||
| end | ||||
|  | ||||
| -- | ||||
| -- Return the function table to the host script | ||||
| -- | ||||
| return fbwifi | ||||
| @@ -1,58 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| case "$1" in | ||||
| disable) | ||||
| 	uci set fbwifi.main.enabled=0 | ||||
|  | ||||
| 	uci delete firewall.fbwifi | ||||
|  | ||||
| 	uci delete uhttpd.fbwifi_redirect | ||||
|  | ||||
| 	uci delete uhttpd.main.json_script | ||||
| 	uci set uhttpd.main.cert='/etc/uhttpd.crt' | ||||
| 	uci set uhttpd.main.key='/etc/uhttpd.key' | ||||
| 	uci set uhttpd.main.rfc1918_filter=1 | ||||
| 	;; | ||||
| enable) | ||||
| 	uci set fbwifi.main.enabled=1 | ||||
|  | ||||
| 	uci set firewall.fbwifi=include | ||||
| 	uci set firewall.fbwifi.enabled=1 | ||||
| 	uci set firewall.fbwifi.family=ipv4 | ||||
| 	uci set firewall.fbwifi.path=/usr/share/fbwifi/firewall.include | ||||
| 	uci set firewall.fbwifi.reload=1 | ||||
| 	uci set firewall.fbwifi.type=script | ||||
|  | ||||
| 	uci set uhttpd.fbwifi_redirect=uhttpd | ||||
| 	uci set uhttpd.fbwifi_redirect.enabled=1 | ||||
| 	uci set uhttpd.fbwifi_redirect.cert='/tmp/fbwifi/https_server_cert' | ||||
| 	uci set uhttpd.fbwifi_redirect.home='/dev/null' | ||||
| 	uci set uhttpd.fbwifi_redirect.json_script='/tmp/fbwifi/uhttpd-redirect.json' | ||||
| 	uci set uhttpd.fbwifi_redirect.key='/tmp/fbwifi/https_server_key' | ||||
| 	uci set uhttpd.fbwifi_redirect.listen_http='0.0.0.0:2060' | ||||
| 	uci set uhttpd.fbwifi_redirect.listen_https='0.0.0.0:2061' | ||||
|  | ||||
| 	uci set uhttpd.main.cert='/tmp/fbwifi/https_server_cert' | ||||
| 	uci set uhttpd.main.json_script='/usr/share/fbwifi/uhttpd.json' | ||||
| 	uci set uhttpd.main.key='/tmp/fbwifi/https_server_key' | ||||
| 	uci set uhttpd.main.rfc1918_filter=0 | ||||
| 	;; | ||||
| reload) | ||||
| 	/usr/sbin/fbwifi_get_config | ||||
|  | ||||
| 	login_url=$(uci -c /var/state get fbwifi.main.captive_portal_url) | ||||
| 	[ -z "$login_url" ] && { | ||||
| 		logger -t fbwifi "captive_portal_url not available yet" | ||||
| 		exit 1 | ||||
| 	} | ||||
| 	printf '{ "request": [ ["redirect", "%s", 302] ] }' "$login_url" > /tmp/fbwifi/uhttpd-redirect.json | ||||
|  | ||||
| 	/etc/init.d/uhttpd restart | ||||
|  | ||||
| 	exit 0 | ||||
| 	;; | ||||
| esac | ||||
|  | ||||
| uci commit | ||||
| /etc/init.d/uhttpd restart | ||||
| reload_config | ||||
| @@ -1,8 +0,0 @@ | ||||
| echo -e "Runtime configuration and token DB\n" | ||||
| uci -c /var/state export fbwifi | ||||
|  | ||||
| echo -e "\nDynamic firewall flow rules\n" | ||||
| iptables -t mangle -L FBWIFI_CLIENT_TO_INTERNET | ||||
|  | ||||
| echo -e "\nDHCP leases\n" | ||||
| cat /tmp/dhcp.leases | ||||
| @@ -1,39 +0,0 @@ | ||||
| #!/usr/bin/lua | ||||
|  | ||||
| http = require("ssl.https") | ||||
| json = require("cjson") | ||||
| log = require("posix.syslog") | ||||
| socket = require("socket") | ||||
| require("uci") | ||||
| fbwifi = require("fbwifi") | ||||
|  | ||||
| GATEWAY_TOKEN = fbwifi.gateway_token() | ||||
| state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
|  | ||||
| payload="name="..socket.dns.gethostname() | ||||
|  | ||||
| function queue_ssid_update(iface) | ||||
| 	bssid_file="/sys/class/net/br-"..iface["network"].."/address" | ||||
| 	local file = io.open(bssid_file) | ||||
|         if file then | ||||
|             for line in file:lines() do | ||||
| 		payload=payload.."&bssid[]="..line | ||||
|             end | ||||
| 	    file:close() | ||||
| 	    payload=payload.."ssid[]="..iface["ssid"] | ||||
|         else | ||||
| 	    log.syslog(log.LOG_WARNING, "[fbwifi] Failed to find BSSID for interface br-"..iface["network"]) | ||||
|         end | ||||
| end | ||||
|  | ||||
| state:foreach("wireless", "wifi-iface", queue_ssid_update) | ||||
|  | ||||
| URL="https://api.fbwifi.com/v2.0/gateway" | ||||
| body, code, headers = http.request(URL.."?access_token="..GATEWAY_TOKEN, payload) | ||||
| if code == 200 then  | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] gateway information updated "..body) | ||||
| 	os.exit(0) | ||||
| else | ||||
| 	log.syslog(log.LOG_WARNING, "[fbwifi] gateway API failed "..body) | ||||
| 	os.exit(code) | ||||
| end | ||||
| @@ -1,111 +0,0 @@ | ||||
| #!/usr/bin/lua | ||||
| http = require("ssl.https") | ||||
| json = require("cjson") | ||||
| require("uci") | ||||
| log = require("posix.syslog") | ||||
| fbwifi = require("fbwifi") | ||||
|  | ||||
| GATEWAY_TOKEN = fbwifi.gateway_token() | ||||
|  | ||||
| http_port = uci.get("fbwifi.main.http_port") | ||||
| https_port = uci.get("fbwifi.main.https_port") | ||||
|  | ||||
| statefile = assert(io.open("/var/state/fbwifi", "a"), "could not create state file") | ||||
| statefile:close() | ||||
|  | ||||
| state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
|  | ||||
| URL="https://api.fbwifi.com/v2.0/gateway" | ||||
| body, code, headers = http.request(URL.."?access_token="..GATEWAY_TOKEN.."&fields=config,config_version") | ||||
|  | ||||
| if code == 200 then | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] Got gateway config ("..code..")") | ||||
| else | ||||
| 	log.syslog(log.LOG_CRIT, "[fbwifi] Failed to get gateway config ("..code..")") | ||||
| 	os.exit(1) | ||||
| end | ||||
|  | ||||
| obj = json.decode(body) | ||||
|  | ||||
| function save_cert(name, value) | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] Saving cert "..name) | ||||
| 	local f = assert(io.open("/tmp/fbwifi/"..name, "w")) | ||||
| 	f:write(value) | ||||
| 	f:close() | ||||
| end | ||||
|  | ||||
| function process_redirect(ix, host) | ||||
| 	IP_SET = "ip addr replace dev lo "..host | ||||
| 	local result = os.execute(IP_SET) | ||||
| 	if result == 0 then | ||||
| 		log.syslog(log.LOG_INFO, "[fbwifi] Redirect address applied "..host) | ||||
| 	else | ||||
| 		log.syslog(log.LOG_WARNING, "[fbwifi] Failed to apply redirect address "..host) | ||||
| 	end | ||||
|  | ||||
| 	ip = string.match(host, '([0-9\.]*)/([0-9]*)') | ||||
| 	RULE_FMT="grep -q \"%s\" /etc/hosts || echo \"%s\tstar.fbwifigateway.net\" >> /etc/hosts" | ||||
| 	HOSTS_RULE = string.format(RULE_FMT, ip, ip) | ||||
| 	result = os.execute(HOSTS_RULE) | ||||
| 	if result == 0 then | ||||
| 		log.syslog(log.LOG_INFO, "[fbwifi] Cached redirect host for DNS") | ||||
| 	else | ||||
| 		log.syslog(log.LOG_WARNING, "[fbwifi] Failed to amend /etc/hosts") | ||||
| 		log.syslog(log.LOG_INFO, "[fbwifi] "..HOSTS_RULE) | ||||
| 	end | ||||
|  | ||||
| 	result = os.execute("iptables -t nat -A FBWIFI_HOST_REDIRLIST -p tcp --dport 80 -d "..ip.." -j ACCEPT # REDIRECT --to-ports "..http_port) | ||||
| 	--print(result) | ||||
| 	result = os.execute("iptables -t nat -A FBWIFI_HOST_REDIRLIST -p tcp --dport 443 -d "..ip.."  -j ACCEPT # REDIRECT --to-ports "..https_port) | ||||
| 	--print(result) | ||||
| end | ||||
|  | ||||
| save_cert("https_server_cert", obj['config']['https_server_cert']) | ||||
| save_cert("https_server_key", obj['config']['https_server_key']) | ||||
|  | ||||
| result = os.execute("iptables -t nat -F FBWIFI_HOST_REDIRLIST") | ||||
| --print(result) | ||||
| table.foreach(obj['config']['host_redirect_ips'], process_redirect) | ||||
|  | ||||
| RULE_FORMAT = "iptables -t mangle -A FBWIFI_TRAFFIC_ALLOWLIST -d %s -p %s --dport %s -j MARK --set-mark 0xfb" | ||||
| function process_traffic_rule(ix, rule) | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] Traffic rule "..ix) | ||||
| 	 | ||||
| 	if rule["protocol"] == 6 then | ||||
| 		PROTO = "tcp" | ||||
| 	elseif rule["protocol"] == 17 then | ||||
| 		PROTO = "udp" | ||||
| 	end | ||||
| 	RULE = string.format(RULE_FORMAT, rule["ip"], PROTO, rule["port"]) | ||||
| 	local result = os.execute(RULE) | ||||
| 	if result == 0 then | ||||
| 		log.syslog(log.LOG_INFO, "[fbwifi] Traffic rule "..ix) | ||||
| 	else | ||||
| 		log.syslog(log.LOG_WARNING, "[fbwifi] Failed to install traffic rule ; "..RULE) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local cross_origin_list = {} | ||||
| function process_cross_origin_rule(ix, url) | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] Cross origin rule "..url) | ||||
| 	table.insert(cross_origin_list, url) | ||||
| end | ||||
|  | ||||
| function process_url(url_purpose, fqdn) | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] Caching "..url_purpose) | ||||
| 	state:set("fbwifi", "main", url_purpose, fqdn)	 | ||||
| end | ||||
|  | ||||
| state:set("fbwifi", "main", "config") | ||||
|  | ||||
| result = os.execute("iptables -t mangle -F FBWIFI_TRAFFIC_ALLOWLIST ") | ||||
| --print(result) | ||||
| table.foreach(obj['config']['traffic_allowlist'], process_traffic_rule) | ||||
| table.foreach(obj['config']['cross_origin_allowlist'], process_cross_origin_rule) | ||||
| table.foreach(obj['config']['urls'], process_url) | ||||
|  | ||||
| state:set("fbwifi", "main", "cross_origin_allow_rules", cross_origin_list) | ||||
| state:set("fbwifi", "main", "config_version", obj['config_version']) | ||||
|  | ||||
| state:save('fbwifi') | ||||
| state:commit('fbwifi') | ||||
| @@ -1,75 +0,0 @@ | ||||
| #!/usr/bin/lua | ||||
|  | ||||
| https = require("ssl.https") | ||||
| json = require("cjson") | ||||
| log = require("posix.syslog") | ||||
| fbwifi = require("fbwifi") | ||||
| require("uci") | ||||
|  | ||||
| state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
| GATEWAY_TOKEN = fbwifi.gateway_token() | ||||
|  | ||||
| request = {  | ||||
| 	tokens = {},  | ||||
| 	traffic_type = "total", | ||||
| 	config_version = state:get("fbwifi", "main", "config_version") | ||||
| } | ||||
|  | ||||
| function queue_token(client) | ||||
|  | ||||
| 	request.tokens[client.token]={ | ||||
| 		incoming = json.null, | ||||
| 		outgoing = json.null, | ||||
| 		connected_time_sec = json.null, | ||||
| 		inactive_time_sec = json.null, | ||||
| 		signal_rssi_dbm = json.null, | ||||
| 		--expected_tpus_mbps = json.null, | ||||
| 		is_connected = true | ||||
| 	} | ||||
|  | ||||
| end | ||||
|  | ||||
| state:foreach("fbwifi", "client", queue_token) | ||||
| print( "\nRequest:\n"..json.encode(request) ) | ||||
|  | ||||
| URL="https://api.fbwifi.com/v2.0/tokens" | ||||
| BODY=string.format( | ||||
| 	"tokens=%s&traffic_type=%s&config_version=%s", | ||||
| 	json.encode(request.tokens), | ||||
| 	"total", | ||||
| 	state:get("fbwifi", "main", "config_version") | ||||
| ) | ||||
|  | ||||
| body, code, headers = https.request(URL.."?access_token="..GATEWAY_TOKEN, BODY) | ||||
|  | ||||
| if code then | ||||
| 	print( "\nResponse:\n"..body ) | ||||
| end | ||||
|  | ||||
| response = json.decode(body) | ||||
| --print(response) | ||||
| --table.foreach(response,print) | ||||
| --table.foreach(response.tokens,print) | ||||
|  | ||||
| if response.config_valid then | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] Config validated") | ||||
| else | ||||
| 	log.syslog(log.LOG_WARNING, "[fbwifi] config is stale, refreshing config") | ||||
|         local result = os.execute("/usr/sbin/fbwifi reload") | ||||
|         if result == 0 then | ||||
|                 log.syslog(log.LOG_INFO, "[fbwifi] successfully fetched and loaded new config ") | ||||
|         else | ||||
|                 log.syslog(log.LOG_WARNING, "[fbwifi] failed to fetch and load new config, possible stale config") | ||||
|         end | ||||
| end | ||||
|  | ||||
| function process_token(token, metadata) | ||||
| 	table.foreach(metadata,print) | ||||
| 	if metadata.valid then | ||||
| 		print("OK: "..token)	 | ||||
| 	else | ||||
| 		print("Nok: "..token)	 | ||||
| 		fbwifi.revoke_client_rule( token ) | ||||
| 	end | ||||
| end | ||||
| table.foreach(response.tokens,process_token) | ||||
| @@ -1,75 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| # SPDX-License-Identifier: GPL-2.0-only | ||||
| # Copyright (c) Facebook, Inc. and its affiliates. | ||||
|  | ||||
| IPT4="/usr/sbin/iptables" | ||||
|  | ||||
| set -- --wait 1 --wait-interval 100 | ||||
|  | ||||
| fbwifi_http_port="$(uci get fbwifi.main.http_port)" | ||||
| [ -n "$fbwifi_http_port" ] || { | ||||
| 	logger -t fbwifi "required option http_port not set" | ||||
| 	exit 1 | ||||
| } | ||||
|  | ||||
| fbwifi_https_port="$(uci get fbwifi.main.https_port)" | ||||
| [ -n "$fbwifi_https_port" ] || { | ||||
| 	logger -t fbwifi "required option https_port not set" | ||||
| 	exit 1 | ||||
| } | ||||
|  | ||||
| fbwifi_zone="$(uci get fbwifi.main.zone)" | ||||
| [ -n "$fbwifi_zone" ] || { | ||||
| 	logger -t fbwifi "required option zone  not set" | ||||
| 	exit 1 | ||||
| } | ||||
|  | ||||
| fbwifi_ifaces="$(fw3 -q zone "$fbwifi_zone")" | ||||
|  | ||||
| ## Create custom chains | ||||
| "$IPT4" "$@" -t filter -N FBWIFI_FORWARD 2>/dev/null | ||||
| "$IPT4" "$@" -t filter -N FBWIFI_INPUT 2>/dev/null | ||||
| "$IPT4" "$@" -t mangle -N FBWIFI_CLIENT_TO_INTERNET 2>/dev/null | ||||
| "$IPT4" "$@" -t mangle -N FBWIFI_PREROUTING 2>/dev/null | ||||
| "$IPT4" "$@" -t mangle -N FBWIFI_TRAFFIC_ALLOWLIST 2>/dev/null | ||||
| "$IPT4" "$@" -t nat -N FBWIFI_CLIENT_TO_INTERNET 2>/dev/null | ||||
| "$IPT4" "$@" -t nat -N FBWIFI_PREROUTING 2>/dev/null | ||||
| "$IPT4" "$@" -t nat -N FBWIFI_HOST_REDIRLIST 2>/dev/null | ||||
|  | ||||
| ## Flush custom chains | ||||
| "$IPT4" "$@" -t filter -F FBWIFI_FORWARD | ||||
| "$IPT4" "$@" -t filter -F FBWIFI_INPUT | ||||
| "$IPT4" "$@" -t mangle -F FBWIFI_CLIENT_TO_INTERNET | ||||
| "$IPT4" "$@" -t mangle -F FBWIFI_PREROUTING | ||||
| "$IPT4" "$@" -t mangle -F FBWIFI_TRAFFIC_ALLOWLIST | ||||
| "$IPT4" "$@" -t nat -F FBWIFI_CLIENT_TO_INTERNET | ||||
| "$IPT4" "$@" -t nat -F FBWIFI_PREROUTING | ||||
| "$IPT4" "$@" -t nat -F FBWIFI_HOST_REDIRLIST | ||||
|  | ||||
| ## Populate custom chains | ||||
| "$IPT4" "$@" -t filter -A FBWIFI_FORWARD -p udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT | ||||
| "$IPT4" "$@" -t filter -A FBWIFI_FORWARD -m conntrack --ctstate NEW -m mark --mark 0xfb -j ACCEPT | ||||
| "$IPT4" "$@" -t filter -A FBWIFI_FORWARD -j REJECT | ||||
| "$IPT4" "$@" -t filter -A FBWIFI_INPUT -p tcp --dport "$fbwifi_http_port" -m conntrack --ctstate NEW -j ACCEPT | ||||
| "$IPT4" "$@" -t filter -A FBWIFI_INPUT -p tcp --dport "$fbwifi_https_port"  -m conntrack --ctstate NEW -j ACCEPT | ||||
| "$IPT4" "$@" -t filter -A FBWIFI_INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT | ||||
| "$IPT4" "$@" -t mangle -A FBWIFI_PREROUTING -j FBWIFI_CLIENT_TO_INTERNET | ||||
| "$IPT4" "$@" -t mangle -A FBWIFI_PREROUTING -j FBWIFI_TRAFFIC_ALLOWLIST | ||||
| "$IPT4" "$@" -t nat -A FBWIFI_PREROUTING -j FBWIFI_CLIENT_TO_INTERNET | ||||
| "$IPT4" "$@" -t nat -A FBWIFI_CLIENT_TO_INTERNET -p tcp --dport 80 -m conntrack --ctstate NEW -j FBWIFI_HOST_REDIRLIST | ||||
| "$IPT4" "$@" -t nat -A FBWIFI_CLIENT_TO_INTERNET -p tcp --dport 443 -m conntrack --ctstate NEW -j FBWIFI_HOST_REDIRLIST | ||||
| "$IPT4" "$@" -t nat -A FBWIFI_CLIENT_TO_INTERNET -p udp --dport 443 -m conntrack --ctstate NEW -j FBWIFI_HOST_REDIRLIST | ||||
| "$IPT4" "$@" -t nat -A FBWIFI_CLIENT_TO_INTERNET -p tcp --dport 80 -m conntrack --ctstate NEW -m mark --mark 0xfb -j ACCEPT | ||||
| "$IPT4" "$@" -t nat -A FBWIFI_CLIENT_TO_INTERNET -p tcp --dport 443 -m conntrack --ctstate NEW -m mark --mark 0xfb -j ACCEPT | ||||
| "$IPT4" "$@" -t nat -A FBWIFI_CLIENT_TO_INTERNET -p udp --dport 443 -m conntrack --ctstate NEW -m mark --mark 0xfb -j ACCEPT | ||||
| "$IPT4" "$@" -t nat -A FBWIFI_CLIENT_TO_INTERNET -p tcp --dport 80 -m conntrack --ctstate NEW -j REDIRECT --to-ports "$fbwifi_http_port" | ||||
|  | ||||
| ## Hook custom chains in firewall3 chains | ||||
| "$IPT4" "$@" -t filter -I "zone_${fbwifi_zone}_input" 2 -j FBWIFI_INPUT | ||||
| "$IPT4" "$@" -t filter -I "zone_${fbwifi_zone}_forward" 2 -j FBWIFI_FORWARD | ||||
| "$IPT4" "$@" -t nat -I "zone_${fbwifi_zone}_prerouting" 2 -j FBWIFI_PREROUTING | ||||
| # There are no firewall3 zone chains in the mangle table so we need to do this for all interfaces in the zone | ||||
| for iface in $fbwifi_ifaces; do | ||||
| 	"$IPT4" "$@" -t mangle -I PREROUTING -i "$iface" -j FBWIFI_PREROUTING | ||||
| done | ||||
| @@ -1,8 +0,0 @@ | ||||
| { | ||||
|   "request": [ | ||||
|     [ "if", | ||||
|       [ "regex", "REQUEST_URI", "^/fbwifi" ], | ||||
|       [ "rewrite", "/cgi-bin%REQUEST_URI%" ] | ||||
|     ] | ||||
|   ] | ||||
| } | ||||
| @@ -1,70 +0,0 @@ | ||||
| #!/usr/bin/lua | ||||
| require("uci") | ||||
| log = require("posix.syslog") | ||||
| fbwifi = require("fbwifi") | ||||
|  | ||||
| state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
| function process_cors() | ||||
| 	origin = os.getenv("HTTP_ORIGIN") | ||||
| 	log.syslog(log.LOG_INFO, string.format("[fbwifi] [auth] process_cors origin %s", origin or 'not found') ) | ||||
| 	if string.len(origin or '') > 0 then | ||||
| 		allow_list = state:get("fbwifi", "main", "cross_origin_allow_rules") | ||||
| 		for _, value in pairs(allow_list) do | ||||
|     			if value == origin then | ||||
| 				log.syslog(log.LOG_INFO, "[fbwifi] [auth] process_cors Appending CORS Headers to HTTP") | ||||
| 				print("Access-Control-Allow-Origin: "..origin) | ||||
| 				print("Vary: Origin") | ||||
| 				break | ||||
| 			end | ||||
| 		end | ||||
| 	else	 | ||||
| 		log.syslog(log.LOG_INFO, "[fbwifi] [auth] process_cors No CORS Headers added to Response") | ||||
| 	end | ||||
| end | ||||
|  | ||||
| method = os.getenv("REQUEST_METHOD") | ||||
| if method == 'GET' then | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] [auth] GET handler") | ||||
| 	print("Status: 302 Found") | ||||
| 	print("Location: "..state:get("fbwifi", "main", "landing_page_url")) | ||||
| 	process_cors() | ||||
| 	print ('\n') | ||||
|  | ||||
| elseif method == 'POST' then | ||||
| 	local token | ||||
| 	 | ||||
| 	log.syslog(log.LOG_INFO, "[fbwifi] [auth] POST handler") | ||||
| 	process_cors() | ||||
| 	print("Status: 200 OK") | ||||
|  | ||||
| 	form_data=io.read() | ||||
| 	while form_data do | ||||
| 		token = string.match(form_data, '[%d]+') | ||||
| 		if string.len(token or '') > 14 then | ||||
|  | ||||
| 			client = os.getenv("REMOTE_ADDR") | ||||
| 			f = io.popen("awk '/"..client..".*0x2/ { printf(\"%s\", $4) }' /proc/net/arp", 'r') | ||||
| 			client_mac = assert(f:read('*a')) | ||||
| 			f:close() | ||||
|  | ||||
| 			if fbwifi.validate_token(token) then | ||||
|                                 log.syslog(log.LOG_INFO, string.format( "[fbwifi] [auth] POST handler : Validating Token (%s) for MAC (%s)", token or 'nil', client_mac or 'nil') ) | ||||
| 				fbwifi.instate_client_rule(token, client_mac) | ||||
| 				print("\n{\"valid\":true}\n") | ||||
| 			else | ||||
|                                 log.syslog(log.LOG_WARNING, string.format( "[fbwifi] [auth] POST handler : ! Invalid token (%s) for mac (%s) !", token or 'nil', client_mac or 'nil') ) | ||||
| 				fbwifi.revoke_client_rule(token) | ||||
| 				print("\n{\"valid\":false}\n") | ||||
| 			end | ||||
| 			log.syslog(log.LOG_INFO, "[fbwifi] [auth] POST handler completed") | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		form_data=io.read() | ||||
| 	end | ||||
| 	print ('\n') | ||||
|  | ||||
| 	log.syslog(log.LOG_WARNING, string.format("[fbwifi] [auth] POST handler : token not found" )) | ||||
| 	fbwifi.revoke_client_rule(token) | ||||
| 	print("\n{\"valid\":false}\n") | ||||
| end | ||||
| @@ -1,42 +0,0 @@ | ||||
| #!/usr/bin/lua | ||||
| json = require("cjson") | ||||
| require("uci") | ||||
|  | ||||
| state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
| client_mac = "" | ||||
| token = "" | ||||
|  | ||||
| response = {} | ||||
| response['venue-info-url'] = state:get("fbwifi", "main", "capport_venue_info_url") | ||||
|  | ||||
| function map_remote_mac_to_token(client) | ||||
|         for key, value in pairs(client) do | ||||
|                 if | ||||
|                         key == 'mac' and | ||||
|                         value == client_mac | ||||
|                 then | ||||
| 			token = client.token | ||||
|                         return false | ||||
|                 end | ||||
|         end | ||||
| end | ||||
|  | ||||
| function hasValidToken(client_ip) | ||||
| 	f = io.popen("awk '/"..client_ip..".*0x2/ { printf(\"%s\", $4) }' /proc/net/arp", 'r') | ||||
| 	client_mac = assert(f:read('*a')) | ||||
| 	f:close() | ||||
| 	state:foreach("fbwifi", "client", map_remote_mac_to_token) | ||||
|  | ||||
| 	return 0 < string.len(token) | ||||
| end | ||||
|  | ||||
| print("Content-type: application/captive+json; charset=utf-8\n") | ||||
|  | ||||
| client = os.getenv("REMOTE_ADDR") | ||||
| response['captive'] = not hasValidToken(client) | ||||
|  | ||||
| if response['captive'] then | ||||
| 	response['user-portal-url'] = state:get("fbwifi", "main", "captive_portal_url") | ||||
| end | ||||
|  | ||||
| print( json.encode(response) ) | ||||
| @@ -1,57 +0,0 @@ | ||||
| #!/usr/bin/lua | ||||
| json = require("cjson") | ||||
| fbwifi = require("fbwifi") | ||||
|  | ||||
| state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
| GATEWAY_TOKEN = fbwifi.gateway_token() | ||||
|  | ||||
| response = { api_version = "2.0", token = json.null } | ||||
| client_mac = "" | ||||
|  | ||||
| function process_cors() | ||||
|         origin = os.getenv("HTTP_ORIGIN") | ||||
|         if string.len(origin or '') > 0 then | ||||
|                 allow_list = state:get("fbwifi", "main", "cross_origin_allow_rules") | ||||
|                 for _, value in pairs(allow_list) do | ||||
|                         if value == origin then | ||||
|                                 print("Access-Control-Allow-Origin: "..origin) | ||||
|                                 print("Vary: Origin") | ||||
|                                 break | ||||
|                         end | ||||
|                 end | ||||
|         end | ||||
| end | ||||
|  | ||||
| function map_remote_mac_to_token(client) | ||||
|  | ||||
| 	for key, value in pairs(client) do | ||||
| 		if | ||||
| 			key == 'mac' and | ||||
| 			value == client_mac | ||||
| 		then | ||||
| 			response.token = client.token | ||||
| 			return false -- escape outer loop | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function getClientToken(client_ip) | ||||
| 	f = io.popen("awk '/"..client_ip..".*0x2/ { printf(\"%s\", $4) }' /proc/net/arp", 'r') | ||||
| 	client_mac = assert(f:read('*a')) | ||||
| 	f:close() | ||||
|  | ||||
| 	state:foreach("fbwifi", "client", map_remote_mac_to_token) | ||||
| end | ||||
|  | ||||
| function getGatewayId() | ||||
| 	id = string.match(GATEWAY_TOKEN, 'FBWIFI:GATEWAY|[0-9]*|([0-9]*)') | ||||
| 	return id | ||||
| end | ||||
|  | ||||
| process_cors() | ||||
| print("Content-type: application/json; charset=utf-8\n") | ||||
|  | ||||
| getClientToken(os.getenv("REMOTE_ADDR")) | ||||
| response.gateway_id = getGatewayId() | ||||
|  | ||||
| print( json.encode(response) ) | ||||
| @@ -1,12 +0,0 @@ | ||||
| -- SPDX-License-Identifier: GPL-2.0-only | ||||
| -- Copyright (c) Facebook, Inc. and its affiliates. | ||||
|  | ||||
| module("luci.controller.fbwifi", package.seeall) | ||||
|  | ||||
| sys = require "luci.sys" | ||||
| ut = require "luci.util" | ||||
|  | ||||
| function index() | ||||
|     entry({"admin", "network", "fbwifi"}, template("fbwifi"), "Facebook Wi-Fi", 90).dependent=false | ||||
| end | ||||
|  | ||||
| @@ -1,16 +0,0 @@ | ||||
| <%# | ||||
|  Copyright | ||||
|  Licensed to the public under the GNU General Public License v2. | ||||
| -%> | ||||
|  | ||||
| <%+header%> | ||||
|  | ||||
| <h1>Facebook Wi-Fi</h1> | ||||
| <% | ||||
| 	require("uci") | ||||
| 	state = uci.cursor("/var/state", "/tmp/fbwifi") | ||||
| 	url = state:get("fbwifi", "main", "captive_portal_config_url") | ||||
| %> | ||||
| <a href="<% print(url) %>">Configure FB business page</a> | ||||
|  | ||||
| <%+footer%> | ||||
| @@ -9,7 +9,6 @@ feeds: | ||||
| include: | ||||
|   - webui | ||||
|   - openflow | ||||
|   - fbwifi | ||||
|   - chilli-redirect | ||||
|   - qosify | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 John Crispin
					John Crispin