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:
installation of required software
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)
In order to be able to update the upribox, following task are necessary:
installing ansible
copying the update script
copying git deployment key
deploying the upribox recovery mechanism
restarts update at system boot if the update was interrupted
unattended_upgrades¶
Unattended Upgrades [2] provides the upribox automatically with the latest security updates.
upri-config¶
The upri-config role deploys the upri-config script, which is used for configuring the upribox. Additionally necessary cron jobs for updates and other tasks are copied. The main parts of this role are the following:
deployment of the upri-config script
create virtualenv
copy upri-config files
link managament script
The upribox updates every hour to the latest version on github via ansible. For this purpose the common role needs to execute among others the following tasks before updating:
configuring cron jobs
update the upribox
update the filter rules
parse user-agents which are used to fingerprint the devices connected to the upribox
parse log files used for statistics
Networking¶
arp¶
The upribox provides a zero-config service called Apate (see Automatic) 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 upribox and to provide a wireless network with the default SSID upribox. Depending on the mode activated for a specific device, ads and trackers will automatically be blocked and the traffic might be routed through the Tor [5] network.
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 following URLs 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, 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 Installation) 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,restart_wlan,enable_silent,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,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,silent_device,check_device,filter_update,vpn_forward,vpn_unforward,backup_settings,restore_settings}
...
Actions¶
Actions cover tasks that are able to modify the configuration of the upribox
- action
Possible choices: set_ssid, set_password, restart_wlan, enable_silent, 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, 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, silent_device, check_device, filter_update, vpn_forward, vpn_unforward, backup_settings, restore_settings
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
restart_wlan¶
Triggers the Ansible tasks with the tag ssid
upri-config.py restart_wlan [-h]
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
restart_vpn¶
Triggers the Ansible tasks with the tag toggle_vpn
upri-config.py restart_vpn [-h]
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”)
restart_ssh¶
Triggers the Ansible tasks with the tag toggle_ssh
upri-config.py restart_ssh [-h]
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]
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
untorify_device¶
Removes iptables rule to untorify a specific device
upri-config.py untorify_device [-h] mac
Positional Arguments¶
- mac
The MAC address of the device whose traffic shall not be routed over the tor network
include_device¶
Removes iptables rule to enable ad-blocking for a specific device
upri-config.py include_device [-h] mac
Positional Arguments¶
- mac
The MAC address of the device whose traffic shall be ad-blocked
silent_device¶
Shortcut for calling of include_device and untorify_device
upri-config.py silent_device [-h] mac
Positional Arguments¶
- mac
The MAC address of the device whose mode shall be set to silent
check_device¶
Checks if device with given ip address is online
upri-config.py check_device [-h] ip
Positional Arguments¶
- ip
The IP address of the device to check
filter_update¶
updates the filter files
upri-config.py filter_update [-h]
vpn_forward¶
enables vpn port forwarding if possible
upri-config.py vpn_forward [-h] [--debug]
options¶
- --debug
Print additional debug messages
Default: False
vpn_unforward¶
removes vpn port forwarding
upri-config.py vpn_unforward [-h] [--debug]
options¶
- --debug
Print additional debug messages
Default: False
backup_settings¶
Saves settings and logs to a backup archive
upri-config.py backup_settings [-h] [path]
Positional Arguments¶
- path
The path of the backup archive
Default: “/home/upri”
restore_settings¶
Restore settings from backup archive
upri-config.py restore_settings [-h] path
Positional Arguments¶
- path
The path of the backup archive
Footnotes