[READ-ONLY] Mirror of https://github.com/andrioid/ublproxy. andrioid.github.io/ublproxy/
adblock adblock-plus-list adblocker privacy-tools proxy-server self-hosted
0

Configure Feed

Select the types of activity you want to include in your feed.

57 2 30

Clone this repository

https://git.vm.fail/andri.dk/ublproxy https://git.vm.fail/did:plc:j3t5y42yc4kx4norr5wprx2v
ssh://git@knot1.tangled.sh:2222/andri.dk/ublproxy ssh://git@knot1.tangled.sh:2222/did:plc:j3t5y42yc4kx4norr5wprx2v

For self-hosted knots, clone URLs may differ based on your setup.


README.md

ublproxy#

A network-wide adblock proxy-server w. adblock list support, custom rules and passkey users. Easy to set up and host yourself.

Problem domain#

Browsers were supposed to be "user-agents", but modern browsers are far more catered to ad-selling corporations, than they are to users.

Existing solutions, such as pihole and other dns-based solutions are only sufficient, if you want to block an entire hostname. Browser extensions used to work well, but with the latest Manifest changes, they are not as effective as they used to be.

Architecture#

ublproxy sits between your devices and the internet, intercepting HTTP/HTTPS traffic to block ads and tracking at the network level.

graph LR
    subgraph LAN["Local Network"]
        D1["Desktop"]
        D2["Laptop"]
        D3["Phone"]
    end

    subgraph UBL["ublproxy"]
        HTTP[":8080<br/>HTTP"]
        HTTPS[":8443<br/>HTTPS"]
        BL["Blocklist<br/>Engine"]
        CA["CA + Cert<br/>Cache"]
        DB["SQLite<br/>Store"]
    end

    UP["Upstream<br/>Servers"]

    D1 --> HTTPS
    D2 --> HTTPS
    D3 --> HTTP

    HTTPS --> BL
    HTTP --> BL
    BL --> CA
    BL --> UP

    HTTPS --> DB

The proxy operates in one of two modes:

Explicit proxy mode (default)#

Browsers are configured to send traffic through the proxy via PAC files or manual proxy settings.

sequenceDiagram
    participant B as Browser
    participant P as ublproxy
    participant U as Upstream

    B->>P: CONNECT example.com:443
    P->>P: Check blocklist
    alt Blocked
        P-->>B: 403 Forbidden
    else Excepted (@@)
        P->>U: TCP tunnel (passthrough)
        U-->>B: Direct TLS (no MITM)
    else Normal
        P-->>B: 200 OK
        B->>P: TLS handshake (MITM cert)
        P->>P: Generate cert for example.com
        B->>P: GET /page
        P->>U: GET /page (real TLS)
        U-->>P: HTML response
        P->>P: Strip blocked resources
        P->>P: Inject element-hiding CSS
        P-->>B: Modified HTML
    end

Transparent proxy mode (--transparent)#

A firewall redirects all traffic from a VLAN to the proxy. No client configuration needed.

sequenceDiagram
    participant D as Device
    participant FW as Firewall
    participant P as ublproxy
    participant U as Upstream

    Note over D,FW: New device joins VLAN

    D->>FW: HTTP to captive.apple.com
    FW->>P: Redirect to :8080
    P->>P: Untrusted client?
    P-->>D: 302 Redirect to setup page

    Note over D: OS shows captive portal UI
    Note over D: User installs CA cert

    D->>FW: HTTPS to example.com
    FW->>P: Redirect to :8443
    P->>P: Extract SNI from ClientHello
    P->>P: Generate MITM cert
    D->>P: TLS handshake (trusts CA)
    P->>P: Mark client as trusted
    P->>U: Forward request
    U-->>P: Response
    P-->>D: Modified response

Features#

Adblock Plus lists#

Subscribe to community-maintained blocklists like EasyList and EasyPrivacy. Lists are fetched and parsed automatically, and rules are applied to all proxied traffic.

Custom rules#

Add your own blocking and element-hiding rules using adblock filter syntax, or use the interactive element picker (Alt+Shift+B) to visually select elements to hide on any proxied page.

Encrypted, all the way#

Desktop browsers connect to the proxy over HTTPS. The proxy generates per-host TLS certificates on the fly using its own CA. Mobile devices (iOS/Android) connect over plain HTTP because they don't support HTTPS proxy connections — the MITM tunnel within the connection is still TLS-encrypted.

Strips away scripts, images and embeds#

Blocked requests for scripts, images, iframes and other embedded resources are stopped at the proxy before they reach your browser.

Hides the rest#

CSS is injected into HTML responses to hide elements matching element-hiding rules. The proxy decompresses HTML, injects the CSS, and serves it back — removing ad containers, banners and other unwanted elements visually.

Users and custom rules#

WebAuthn passkey authentication gives each user their own set of rules and subscriptions, layered on top of any server-configured blocklists.

Transparent proxy mode#

Deploy on a VLAN with firewall rules to intercept all traffic automatically — no client-side proxy configuration needed. A captive portal guides new devices through CA certificate installation. Enable with --transparent.

Security#

Man-In-The-Middle#

It's important to be aware, that by using this solution, you're essentially decrypting all of your traffic, messing with it and then encrypting it again before it reaches the browser. If ublproxy was a service on the Internet, that should make you very suspicious. But, this is intended to be run on small local networks to improve privacy, and ad-free browsing.

Known limitations#

  • Element hiding on zstd HTML: CSS injection for element hiding works with gzip, brotli, and uncompressed HTML. Zstd-encoded HTML passes through without element hiding CSS.
  • No re-compression: After decompressing gzip for CSS injection, HTML is served uncompressed to the client. This is fine when the proxy runs on localhost.
  • Cert cache: Generated TLS certificates are cached indefinitely with no eviction. Certificates have 24-hour validity but expired entries are never cleaned up. Fine for personal use.
  • Session-to-IP mapping: Sessions are bound to client IP. Multiple users behind the same NAT IP share a single session slot (last login wins).
  • Mobile proxy connection is unencrypted: iOS and Android don't support HTTPS proxy connections. Mobile devices use a plain HTTP CONNECT proxy on port 8080. The CONNECT metadata (target hostname) is visible on the LAN, though the tunneled content is TLS-encrypted. The element picker is disabled on mobile connections to avoid leaking the session token.

References#