Architecture¶
A core technology used in the upribox software is Ansible [1]: a python-based configuration management software. Our rationale behind using Ansible is twofold:
Reproducibility Every setting, installed package etc. should be documented in code. We use Ansible’s default push mode to configure the base image in order to deploy the latest upribox software and harden the base image. All changes we perform on a given base images can be reproduced (see Development).
Continuous delivery Ansible enables us to roll out bugfixes as well as new features continuously. Once the upribox software is deployed it automatically gets changes from our Github repository and deploys them using Ansible’s pull mode.
Note
Config files are overwritten periodically (see Customization).
Modules¶
Base setup¶
init¶
This role is responsible for basic configurations of the operating system such as
- expanding disk space
- configuring locale
- user management
- creating sudo group
- creating remote user
- removing default user (pi)
- setting the hostname (upri)
- adding authorized key
common¶
The common role lays the groundwork for the following more specific roles. The main parts of this role are the following:
- building the infrastructure for logging
- creating the logging directory (
/var/tmp/log
for production and/var/log/log
for development mode, see Development vs. Production mode)- updating rsyslog config and deleting old rsyslog logfiles
- configuring logrotate
- settings and configurations
- writing default settings
- copying ansible config
- creating directory for local facts (see Customization)
- The upribox updates every 4 hours to the latest version on github via ansible. For this purpose the common role needs to execute among others the following tasks before updating
- installing ansible
- configuring a cron job
- copying the update script
- copying git deployment key
- update of the filter rules
- creating crontab entry to parse user-agents which are used to fingerprint the devices connected to the upribox
Networking¶
arp¶
The upribox provides a zero-config service called Apate (see Apate) which allows you to benefit from the ad-blocking functionality on every device in your network not just when connected to the upribox WiFi. This works with a technique called ARP spoofing. In this role the Apate daemon files are copied and configured, requirements are installed to a virtual environment and eventually the daemon is (re)started.
iptables¶
In order to be able to configure ad-blocking (Silent Mode) and Tor (Ninja Mode) for each device separately the upribox
adds and removes iptables rules dynamically. Two lists of MAC addresses - one for devices which don’t need ad-blocking and
one for devices with Tor enabled - are stored in local facts. If a user deactivates ad-blocking or activates Tor for a device
in the user interface the MAC address will be added to the no_adblocking list and the tor list, respectively. The iptables
rules are immediately copied to /etc/iptables/
and to take effect the service is restarted.
vpn¶
The upribox uses OpenVPN [3] as a VPN service to protect your communication security on the road. This can be used to protect your sensitive information when using public WiFi hotspots. The role creates the necessary certificates and keys and installs and sets up the service.
Note
For security reasons OpenVPN is not executed as root and uses SHA384 for the packet HMAC authentication and AES-256 (CBC mode) for encryption.
wlan¶
This role is responsible for installing and configuring all WiFi and network related services such as hostapd or isc-dhcp-server. Interface wlan0 is used as the WiFi interface for the Silent Mode whereas a virtual interface wlan0_0 is added in case of an activated Ninja Mode.
Silent Mode¶
Silent Mode creates a wireless network with the default SSID upribox. If your device is connected to this network ads and trackers will automatically be blocked.
Privacy¶
dns¶
The upribox uses the dnsmasq daemon to filter DNS requests. This role set-ups dnsmasq on all interfaces and listens for requests. Filtered domains are loaded from /etc/dnsmasq.d.
dns_ninja¶
The DNS ninja dnsmasq daemon filters domains and in additions resolves all requests via the Tor network. The daemons listens for requests on port 5300/UDP. This setup also does not log any DNS requests it receives.
dns_unfiltered¶
The upribox needs another instance of the dnsmasq service which is responsible for handling DNS requests from devices on which ad-blocking is deactivated.
nginx¶
This role is used to install and set-up nginx for the upribox. The nginx web server is responsible for a number of tasks:
upribox blackhole¶
The blackhole setup returns an empty response for any request it receives, depending on the type of request this could be either an empty HTML page, or a blank image file. The server in addition attempts to reset/delete browser cookies for filtered domains: for every cookie the server receives, the server responds with the same cookie with empty values and a validity of 0. This setup ensures that tracking cookies are deleted from the user’s browser the moment the request for a domain filtered by the upribox is made.
upribox CSS filter¶
The upribox serves custom CSS files to remove ad-content from websites. The custom domain to serve CSS files is: filter.upri.box. CSS filters are loaded from /etc/nginx/lua/css.lua and periodically updated.
upribox web interface¶
The nginx role finally prepares the setup for the upribox web interface. The nginx configuration ensures that requests to http://upri.box are forwarded to the upribox Django web interface.
privoxy¶
This role deploys the Privoxy [4] filter proxy on the upribox. The upribox uses Privoxy to: filter unwanted content in HTTP requests such as advertisement or tracker code. In addition to content filtering, Privoxy injects a custom CSS file into websites to stop (filtered) ads from showing up in websites. The filter configuration for Privoxy is stored in /etc/privoxy and updated periodically.
tor¶
This role setups the Tor network daemon for the upribox. The Tor daemon is configured for transparent proxying and offers its own DNS resolver to perform DNS queries through the Tor network.
User Interface¶
ssh¶
By default the upribox can be reached via SSH. This feature can be disabled in the admin page of the web interface or directly by calling the enable_ssh action of the configuration script upri-config.py (see django).
Note
In the web interface it is not possible to deactivate WiFi (Silent and Ninja), SSH and Apate, since this scenario would make the upribox unreachable. Therefore one of the services should always be up and running. (see Modes)
fingerprinting¶
The upribox provides a service called registrar which gathers MAC address, IP address and hostname of a device and saves the information into the database. A separate script uses the user-agents provided by squid and tries to extract a model name of the device. These names are later on suggested to the user in the web interface as a way to identify his or her device in a list of other devices on the network. Furthermore the chosen name acts as a label in the device overview.
squid¶
In order to gather user-agents of (and subsequently fingerprint) connected devices (see fingerprinting) the upribox uses squid [7]. The squid log file is later parsed and the information saved into the database.
django¶
The upribox user interface (see Web Interface) is based on the Python Web framework Django [6]. The role is responsible for installing the requirements to a virtual environment, copying the web interface files, setting up the database and installing services like a supervisor (for the rqworker) and the application container uWSGI. By deploying this role the upribox also starts a cleanup process for the saved statistic files removing data older than 6 months.
Note
For privacy reasons the upribox does not keep the ad-blocking logfile with timestamps and URLs but tries to aggregate the information as soon as possible to store only the information that is needed for the statistics and to assure anonymity. (see Logs)
CLI Tool¶
All changes to the upribox configuration are perfomed via upri-config.py
. This nifty command line tool can be used via SSH and also provides a secure way to perform a limited set of
privileged command via the Django webinterface.
usage: upri-config.py [-h]
{set_ssid,set_password,set_tor_ssid,set_tor_password,restart_wlan,enable_tor,enable_silent,restart_tor,restart_silent,enable_vpn,set_vpn_connection,set_wlan_channel,restart_vpn,enable_ssh,restart_ssh,enable_apate,enable_static_ip,restart_apate,parse_logs,parse_user_agents,generate_profile,delete_profile,restart_firewall,enable_device,disable_device,set_ip,configure_devices,set_dns_server,set_netmask,set_gateway,restart_network,set_dhcpd,restart_dhcpd,torify_device,exclude_device,untorify_device,include_device}
...
Actions¶
Actions cover tasks that are able to modify the configuration of the upribox
action | Possible choices: set_ssid, set_password, set_tor_ssid, set_tor_password, restart_wlan, enable_tor, enable_silent, restart_tor, restart_silent, enable_vpn, set_vpn_connection, set_wlan_channel, restart_vpn, enable_ssh, restart_ssh, enable_apate, enable_static_ip, restart_apate, parse_logs, parse_user_agents, generate_profile, delete_profile, restart_firewall, enable_device, disable_device, set_ip, configure_devices, set_dns_server, set_netmask, set_gateway, restart_network, set_dhcpd, restart_dhcpd, torify_device, exclude_device, untorify_device, include_device This script accepts the name of an action that shall be executed |
Sub-commands:¶
set_ssid¶
Sets a new SSID for the Silent WiFi by writing to the fact wlan
upri-config.py set_ssid [-h] ssid
Positional Arguments¶
ssid | The SSID for the Silent WiFi |
set_password¶
Sets a new password for the Silent WiFi by writing to the fact wlan
upri-config.py set_password [-h] password
Positional Arguments¶
password | The SSID for the Silent WiFi |
set_tor_ssid¶
Sets a new SSID for the Ninja WiFi by writing to the fact wlan
upri-config.py set_tor_ssid [-h] ssid
Positional Arguments¶
ssid | The SSID for the Silent WiFi |
set_tor_password¶
Sets a new password for the Ninja WiFi by writing to the fact wlan
upri-config.py set_tor_password [-h] password
Positional Arguments¶
password | The SSID for the Silent WiFi |
enable_tor¶
Enables/disables the Ninja WiFi by writing to the fact tor
upri-config.py enable_tor [-h] boolean
Positional Arguments¶
boolean | Possible choices: yes, no Whether or not Ninja WiFi is enabled (“yes” or “no”) |
enable_silent¶
Enables/disables the Silent WiFi by writing to the fact wlan
upri-config.py enable_silent [-h] boolean
Positional Arguments¶
boolean | Possible choices: yes, no Whether or not Silent WiFi is enabled (“yes” or “no”) |
restart_silent¶
Triggers the Ansible tasks with the tag toggle_silent
upri-config.py restart_silent [-h]
enable_vpn¶
Enables/disables the VPN by writing to the fact vpn
upri-config.py enable_vpn [-h] boolean
Positional Arguments¶
boolean | Possible choices: yes, no Whether or not VPN is enabled (“yes” or “no”) |
set_vpn_connection¶
Sets a custom port and protocol for the upribox OpenVPN server by writing to the fact vpn
upri-config.py set_vpn_connection [-h] port_protocol
Positional Arguments¶
port_protocol | The port and protocol used for the OpenVPN server (usage: “1194/udp”) |
set_wlan_channel¶
Sets a new WiFi channel for the Silent WiFi by writing to the fact wlan
upri-config.py set_wlan_channel [-h] channel
Positional Arguments¶
channel | The channel for the Silent WiFi |
enable_ssh¶
Enables/disables the ssh by writing to the fact ssh
upri-config.py enable_ssh [-h] boolean
Positional Arguments¶
boolean | Possible choices: yes, no Whether or not SSH is enabled (“yes” or “no”) |
enable_apate¶
Enables/disables the Apate (see arp) by writing to the fact apate
upri-config.py enable_apate [-h] boolean
Positional Arguments¶
boolean | Possible choices: yes, no Whether or not Apate is enabled (“yes” or “no”) |
enable_static_ip¶
Sets the upribox to DHCP or static IP mode by writing to the fact interfaces
upri-config.py enable_static_ip [-h] boolean
Positional Arguments¶
boolean | Possible choices: yes, no Whether or not a static IP is enabled (“yes” or “no”) |
restart_apate¶
Triggers the Ansible tasks with the tag toggle_apate
upri-config.py restart_apate [-h]
parse_logs¶
Parses the log files of the services and aggregates the statistics data
upri-config.py parse_logs [-h]
parse_user_agents¶
Parses the log file of the service squid containing MAC addresses, IP addresses and user-agents and saves the gathered information into the database
upri-config.py parse_user_agents [-h]
generate_profile¶
Generates openvpn client certificates and saves the generated openvpn client configuration into the database
upri-config.py generate_profile [-h] profile_id
Positional Arguments¶
profile_id | The profile ID of a profile that was created in the web interface |
delete_profile¶
Revokes previously generated openvpn client certificates
upri-config.py delete_profile [-h] profile_id
Positional Arguments¶
profile_id | The profile ID of a profile that was created in the web interface |
restart_firewall¶
Triggers the Ansible tasks with the tag iptables
upri-config.py restart_firewall [-h]
enable_device¶
Enables ARP spoofing via Apate (see arp) for a specific device
upri-config.py enable_device [-h] ip
Positional Arguments¶
ip | The IP address of the device that shall be enabled |
disable_device¶
Disables ARP spoofing via Apate (see arp) for a specific device
upri-config.py disable_device [-h] ip
Positional Arguments¶
ip | The IP address of the device that shall be disabled |
set_ip¶
Sets a static IP by writing to the fact interfaces
upri-config.py set_ip [-h] ip
Positional Arguments¶
ip | The static IP address for the upribox |
configure_devices¶
Triggers the Ansible tasks with the tag configure_devices
upri-config.py configure_devices [-h]
set_dns_server¶
Sets the DNS server by writing to the fact interfaces
upri-config.py set_dns_server [-h] dns
Positional Arguments¶
dns | The DNS server for the upribox |
set_netmask¶
Sets subnetmask by writing to the fact interfaces
upri-config.py set_netmask [-h] netmask
Positional Arguments¶
netmask | The subnetmask for the upribox |
set_gateway¶
Sets the gateway by writing to the fact interfaces
upri-config.py set_gateway [-h] gateway
Positional Arguments¶
gateway | The gateway for the upribox |
restart_network¶
Triggers the Ansible tasks with the tag network_config
upri-config.py restart_network [-h]
set_dhcpd¶
Enables/disables the DHCP server by writing to the fact dhcpd
upri-config.py set_dhcpd [-h] boolean
Positional Arguments¶
boolean | Possible choices: yes, no Whether or not the upribox acts as a DHCP server (“yes” or “no”) |
restart_dhcpd¶
Triggers the Ansible tasks with the tag dhcp_server
upri-config.py restart_dhcpd [-h]
torify_device¶
Adds iptables rule to torify a specific device
upri-config.py torify_device [-h] mac
Positional Arguments¶
mac | The MAC address of the device whose traffic shall be routed over the tor network |
exclude_device¶
Adds iptables rule to disable ad-blocking for a specific device
upri-config.py exclude_device [-h] mac
Positional Arguments¶
mac | The MAC address of the device whose traffic shall not be ad-blocked |
Footnotes
[1] | https://www.ansible.com |
[2] | https://wiki.debian.org/UnattendedUpgrades |
[3] | https://openvpn.net/ |
[4] | https://www.privoxy.org/ |
[5] | https://www.torproject.org/ |
[6] | https://www.djangoproject.com |
[7] | http://www.squid-cache.org/ |