Community-driven coverage of elementary OS — news, guides & forums
Dark abstract low-poly geometric landscape with layered triangular facets in deep navy, charcoal, and muted teal, illuminated by a soft electric-blue glow near the horizon

News roundups, tutorials, application guides, and forums — built by users, for users of the elegant Linux distribution.

elementary weekly
#20
Latest roundup · 18 Apr 2015
Freya Release
Final
Covered in weekly #19 & #20
Forum Topics
Active
Installation, customization & more

Configure System-Wide Network Filtering on elementary OS

Network filtering is most useful when one policy applies to browsing, package updates and other networked applications. On elementary OS 8, the GNOME desktop provides a manual proxy setting, while a local filtering service can decide which requests are allowed. This guide shows how to set up a system-wide proxy on elementary OS for network filtering, including HTTPS inspection.

Not every application obeys the desktop proxy. Some use their own settings, some resolve names directly, and some ignore both. A useful setup therefore combines a local proxy, a clearly defined rule set and application-specific configuration rather than assuming one switch covers everything.

The example uses mitmproxy on a workstation you control. It can filter HTTP and HTTPS hostnames, show blocked requests and work with GNOME applications. The same local service can be reused by other users, but a router-level solution is usually better for filtering an entire Australian home or office network.

Understand the scope of system-wide filtering

Here, system-wide refers to traffic on one Linux machine, not automatically every device on the local network. A proxy on 127.0.0.1 is reachable by that machine’s applications. Other desktop accounts need their own GNOME proxy preference, and an organisation-wide policy needs central configuration or a filtering gateway.

Proxy routing also has limits. Web requests sent to the proxy are visible to it, but encrypted HTTPS content is not visible unless the proxy establishes a trusted local certificate. Applications that bypass proxies, use their own encrypted DNS, or connect directly to an IP address can escape hostname-based rules.

Use this on equipment you own or administer, and tell affected users what is filtered and logged. Local inspection changes the trust boundary of the machine: keep the certificate private key and proxy configuration protected, remove obsolete trust certificates, and avoid collecting more request data than the policy needs.

Choose a suitable filtering engine

mitmproxy is a good fit for a single workstation because it handles both ordinary web requests and HTTPS interception, with rules written in Python. Squid is a stronger choice for large, centrally managed caching and access-control setups. Privoxy is lightweight for HTTP filtering, while DNS filtering tools such as Pi-hole or unbound are complementary rather than replacements.

The browser alone can block some content, but that leaves updates, game launchers and other apps outside the policy. Put the filtering service on the workstation and point applications towards it. This gives one place to revise rules and review matching traffic.

Install the tooling with apt and pipx so Python package management stays isolated from the operating system. elementary OS 8 is based on Ubuntu 24.04 LTS, so the following commands use its standard package repositories:

sudo apt update
sudo apt install python3-venv pipx
pipx install mitmproxy
pipx ensurepath

The pipx installation normally places mitmdump under ~/.local/bin. That path matters when creating a service later.

Install mitmproxy and write the rules

Create a directory for the filtering script and save the following as ~/.config/mitmproxy/filter.py:

from mitmproxy import http

BLOCKED_HOSTS = {
    "example.com",
    "ads.example.com.au",
}

ALLOWED_HOSTS = {
    "mybank.example.au",
}


def request(flow):
    host = flow.request.pretty_host.lower()

    if host in ALLOWED_HOSTS:
        return

    if host in BLOCKED_HOSTS:
        flow.response = http.Response.make(
            403,
            b"Blocked by the local filtering policy.\n",
            {"Content-Type": "text/plain; charset=utf-8"},
        )

Each entry matches an exact hostname. Subdomains need their own entries unless the script uses suffix matching. The exemption runs first, allowing a trusted service even when it shares a blocked domain.

Start the proxy in the foreground while testing:

mitmdump --listen-host 127.0.0.1 --listen-port 8080 \
  --scripts ~/.config/mitmproxy/filter.py

The first run creates a local certificate authority under ~/.mitmproxy. Keep that directory private because it contains the CA private key.

Confirm the rule works before changing the desktop:

curl -x http://127.0.0.1:8080 http://example.com \
  -o /dev/null -s -w '%{http_code}\n'

The expected status is 403. A request sent directly to the same site can provide a useful comparison.

Connect elementary OS applications to the proxy

Open elementary OS Settings, select Network and find the network proxy controls. Choose manual configuration, enter 127.0.0.1 as the hostname and 8080 as the port for both HTTP and HTTPS. Do not populate the SOCKS field because this listener is an HTTP proxy.

The equivalent command-line configuration is:

gsettings set org.gnome.system.proxy mode 'manual'
gsettings set org.gnome.system.proxy.http host '127.0.0.1'
gsettings set org.gnome.system.proxy.http port 8080
gsettings set org.gnome.system.proxy.https host '127.0.0.1'
gsettings set org.gnome.system.proxy.https port 8080
gsettings set org.gnome.system.proxy ignore-hosts \
  "['localhost', '127.0.0.1', '::1', '.local']"

For settings that should reach all users at future login, add these entries to /etc/environment:

http_proxy=http://127.0.0.1:8080
https_proxy=http://127.0.0.1:8080
HTTP_PROXY=http://127.0.0.1:8080
HTTPS_PROXY=http://127.0.0.1:8080
no_proxy=localhost,127.0.0.1,::1,.local
NO_PROXY=localhost,127.0.0.1,::1,.local

Package managers and sandboxed applications need separate settings. Create /etc/apt/apt.conf.d/90local-proxy with:

Acquire::http::Proxy "http://127.0.0.1:8080";
Acquire::https::Proxy "http://127.0.0.1:8080";

For Snap, use snap set system proxy.http=127.0.0.1:8080 and the equivalent HTTPS command. An individual Flatpak can receive the variables with flatpak override --user --env=http_proxy=http://127.0.0.1:8080 --env=https_proxy=http://127.0.0.1:8080 APP_ID.

Add trusted HTTPS inspection

Installing the local CA lets applications inspect HTTPS requests without certificate warnings. Once mitmproxy has run, install its public certificate:

sudo install -m 0644 \
  "$HOME/.mitmproxy/mitmproxy-ca-cert.pem" \
  /usr/local/share/ca-certificates/mitmproxy-local.crt
sudo update-ca-certificates

Restart open applications so they reload the system certificate store. Do not distribute mitmproxy-ca.pem, which contains the private key. Anyone holding that key could impersonate protected sites.

Firefox and Chromium-based browsers may also maintain their own certificate databases. If a browser reports an unknown issuer, import the public PEM file through its certificate manager rather than disabling certificate validation. Check the installed certificate with:

openssl x509 -in ~/.mitmproxy/mitmproxy-ca-cert.pem \
  -noout -subject -fingerprint -sha256

Certificate pinning prevents some apps from accepting the local CA. Such apps may fail the connection instead of exposing their traffic for inspection. Treat that as an application-specific limitation and use an application firewall where appropriate, rather than weakening TLS checks for the whole system.

Verify filtering and DNS behaviour

Test both protocols through the proxy. With example.com blocked, both commands should return 403:

curl -x http://127.0.0.1:8080 http://example.com \
  -o /dev/null -s -w '%{http_code}\n'
curl -x http://127.0.0.1:8080 https://example.com \
  -o /dev/null -s -w '%{http_code}\n'

Then check the mitmproxy terminal for the matching request and response. Restart existing browsers and apps after changing proxy settings because long-running processes may retain their original configuration.

DNS filtering remains separate. The local proxy can block a hostname when the request reaches it, but it cannot stop an application from sending its own DNS queries. resolvectl status shows the resolver used by the system, while dig +short example.com reveals whether a lookup bypasses the intended service. Apps with encrypted DNS can also ignore the system resolver.

Australian domains deserve explicit treatment in the rule set. Blocking example.com should not automatically exempt example.com.au, .au, .edu.au or government domains such as .nsw.gov.au. Add deliberate exceptions for services that must remain reachable instead of exempting an entire country suffix.

Operate the proxy and confirm the setup

Create ~/.config/systemd/user/mitmproxy-filter.service so the filtering service starts with your session:

[Unit]
Description=Local mitmproxy filtering service
After=network-online.target

[Service]
ExecStart=%h/.local/bin/mitmdump --listen-host 127.0.0.1 --listen-port 8080 --scripts %h/.config/mitmproxy/filter.py --set flow_detail=1
Environment=http_proxy= https_proxy= HTTP_PROXY= HTTPS_PROXY=
Restart=on-failure

[Install]
WantedBy=default.target

The empty proxy variables stop the service from treating itself as its own upstream. If pipx installed mitmdump elsewhere, replace that path with the output from command -v mitmdump. Enable the unit with systemctl --user daemon-reload followed by systemctl --user enable --now mitmproxy-filter.service. Other user accounts still require their own desktop preferences and service instance.

Australian networks add practical complications. NBN connections may use fibre to the premises, fibre to the node, copper to the cabinet, fixed wireless or satellite, depending on the address. Major providers include Telstra, Optus, iiNet, Aussie Broadband and Vodafone, and their router-level filtering options vary. A rule on one elementary OS computer does not cover a television, phone or internet-of-things device, so the ACSC’s Clean Machines guidance on router DNS filtering is valuable for the rest of the household.

Running the proxy locally avoids a round trip to an overseas filtering server for users in Sydney, Melbourne or Brisbane. In Perth, regional centres and remote areas, a local service still avoids unnecessary external latency, although the underlying fixed-wireless or satellite connection remains the limiting factor.

The first acceptance test is a fresh request to http://example.com in a newly opened browser window, with the local 403 policy page as the expected result.

Browse the News Archive
Latest Updates

From the elementary weekly series

Low-poly faceted abstract render in dark charcoal and electric blue tones, suggesting a news bulletin or announcement
elementary news

elementary weekly #20

The first week with the final Freya release — community reactions, tips, and early impressions gathered in one roundup.

Abstract low-poly geometric scene in midnight blue and soft cyan, conveying a live broadcast or event atmosphere
elementary news

elementary SPECIAL

A live Hangouts event with the elementary OS founders, held on 11 April 2015, discussing the Freya final release.

Low-poly faceted render in deep navy and muted teal with subtle amber highlights, suggesting a tutorial or guide
Tips and Tricks

Timeshift Guide

How to use Timeshift — the intuitive system restore utility for elementary OS — to recover from configuration mishaps.

Explore

Topics & Resources

Dive into guides, application recommendations, and community discussions covering every aspect of elementary OS.