A Go proxy that routes traffic through domain fronting and Google Apps Script relays to bypass DPI/SNI-based filtering.
Client
│
├── :8080 ──► Cert Server
│
├── :443 ──► SNI Proxy ──┐
├── :10808 ─► HTTP Proxy ─┤
└── :10809 ─► SOCKS5 ─────┤
│
extract hostname
│
▼
Router
(domain lists, Geosite, IP lists, GeoIP)
│
▼
Outbound Transport
┌──────────────────┐
│ domain_front │ MITM + CDN edge re-dial (uTLS)
│ sni_forward │ raw TCP pass-through via CDN edge
│ relay │ HTTP via Google Apps Script
│ direct │ plain TCP
│ block │ drop connection
└──────────────────┘
Traffic enters through one of the inbound servers (SNI proxy, HTTP CONNECT, SOCKS5, DNS). The router extracts the target hostname/IP and matches it against domain list files, Xray/V2Ray geosite.dat categories, or GeoIP rules (first match wins, falls back to default_outbound). For IP rules, hostnames are resolved on demand and cached, matching Xray's IPOnDemand behavior. Matched traffic is sent through the corresponding outbound transport.
- domain_front — Intercepts client-side TLS (MITM), then re-dials a CDN edge with a Chrome uTLS fingerprint. Target attempts are staggered and raced with bounded concurrency; the last successful configured edge is preferred on later connections. Profiles can preserve the original destination or force a redirect target, advertise H1 or H2/H1 to clients, and verify the public upstream certificate against an allowlist.
- sni_forward — Raw TCP tunnel through a CDN edge. No MITM, no certificate required on the client. The client's original TLS handshake (including SNI) passes through unchanged; the CDN routes it to the correct origin.
- relay — HTTP requests forwarded through Google Apps Script endpoints over a domain-fronted connection. Supports H1 pooling, H2 multiplexing, request batching, and response coalescing.
- direct — plain TCP, no MITM.
- block — immediately closes the connection.
# build
make build
# run
./mattlab -c config.jsonCross-compile all platforms:
make releaseConfig is a single JSON file. Domain lists and GeoIP files are referenced by relative path from the config file directory.
{
"listen_host": "0.0.0.0",
"log_level": "info",
"inbounds": {
"sni_proxy": { "enabled": false, "port": 443 },
"http_proxy": { "enabled": true, "port": 10808 },
"socks5": { "enabled": true, "port": 10809 },
"cert_server": { "enabled": true, "port": 8080 },
"dns_server": { "enabled": false, "port": 53 }
},
"outbounds": [
{
"tag": "akamai-mitm",
"type": "domain_front",
"target_ips": [
"a248.e.akamai.net",
"23.215.0.206"
],
"target_port": 443,
"front_sni": "",
"fingerprint": "chrome"
},
{
"tag": "fastly-mitm",
"type": "domain_front",
"target_ips": ["pypi.org"],
"target_port": 443,
"front_sni": "pypi.org",
"fingerprint": "chrome"
},
{
"tag": "cdn-forward",
"type": "sni_forward",
"front_addr": "92.123.102.43:443"
},
{
"tag": "gas-relay",
"type": "relay",
"target_ip": "216.239.38.120",
"target_port": 443,
"front_sni": "google.com",
"script_ids": ["YOUR_SCRIPT_ID"],
"auth_key": "",
"relay_domain": "script.google.com",
"format": "json",
"batch_enabled": true,
"h2_enabled": true
},
{ "tag": "direct", "type": "direct" },
{ "tag": "block", "type": "block" }
],
"routes": [
{ "domains": "domains/psiphon-akamai.txt", "outbound": "akamai-mitm" },
{ "domains": "domains/psiphon-akamai-ips.txt", "outbound": "akamai-mitm" },
{ "geoip": "geoip.dat", "geocode": "FASTLY", "outbound": "fastly-mitm" },
{ "domains": "domains/local.txt", "outbound": "direct" }
],
"default_outbound": "direct"
}| Field | Type | Description |
|---|---|---|
tag |
string | Unique name referenced by routes |
type |
string | domain_front, sni_forward, relay, direct, block |
target_ips |
string[] | Optional fallback or redirect CDN edge addresses to try in order (hostnames DNS-resolved at dial time) |
target_ip |
string | Single CDN edge address (legacy; use target_ips) |
target_port |
int | CDN edge port (default 443) |
front_sni |
string | TLS SNI sent to CDN. Empty = use each target address as its own SNI |
fingerprint |
string | uTLS fingerprint: chrome (Chrome-83), chrome120, chrome133, firefox, safari, edge, random |
alpn |
string[] | Protocols advertised by the local MITM endpoint, such as ["http/1.1"] or ["h2", "http/1.1"] |
verify_names |
string[] | Allowed public upstream certificate names. Use from_mitm to include the client destination hostname |
dial_original_destination |
bool | Try the client destination before target_ips (default true). Set false for redirect-only profiles |
dial_concurrency |
int | Maximum simultaneous target attempts (default 4) |
dial_fallback_delay_ms |
int | Delay before racing the next target (default 300) |
front_addr |
string | host:port of CDN edge for sni_forward |
script_ids |
string[] | Google Apps Script IDs for relay |
For compatibility with older Psiphon profiles, an empty verify_names list keeps the previous permissive upstream verification behavior. New browser profiles should always set verify_names.
Routes are evaluated in order; first match wins.
| Field | Description |
|---|---|
domains |
Path to a domain list .txt file |
geosite + geocode |
Path to an Xray/V2Ray geosite.dat file and category to match (e.g. "GOOGLE" or "CATEGORY-ADS-ALL") |
geoip + geocode |
Path to a GeoIP .dat file and the code to match (e.g. "FASTLY") |
outbound |
Tag of the outbound to use |
# exact match
youtube.com
# suffix match (matches *.youtube.com AND youtube.com)
.youtube.com
# keyword/contains match
~blogspot
# CIDR range (IPv4 or IPv6)
23.215.0.0/16
# exact IP
92.123.102.43
"dns_server": {
"enabled": true,
"port": 53,
"dot_port": 853,
"mode": "sniproxy",
"upstream_dns": "8.8.8.8:53"
}Modes: sniproxy (resolve upstream, reply with the proxy IP for routed domains) or doh (DNS-over-HTTPS via a configured outbound).
The config.mitm-domain-fronting.example.json profile follows the current MITM-DomainFronting v22 reference. It adds separate profiles for:
| Profile | Traffic | Upstream behavior |
|---|---|---|
googlevideo-mitm |
YouTube video hosts | original destination, Google SNI, HTTP/1.1 |
google-mitm |
Google and YouTube services | original destination, Google SNI, H2/H1 |
fastly-mitm |
Reddit, GitHub, CNN, BuzzFeed, Fastly sites | redirect through github.githubassets.com, H2/H1 |
meta-mitm |
Facebook, Instagram, WhatsApp, Meta sites | original destination, Microsoft SNI, H2/H1 |
dns-mitm |
optional DoH queries | redirect through Cloudflare IPs |
Place current Xray/V2Ray geosite.dat and geoip.dat files next to the config, then start with:
cp config.mitm-domain-fronting.example.json config.json
./mattlab -c config.jsonOn first run mattlab creates .mattlab_ca/ca.crt. Open http://<host>:8080 from the client device and install that personal CA only on devices you control.
The profile mirrors the upstream routing order: ads block; local, private, Iranian, and Khan Academy domains direct; Google video over H1; Google over H2/H1; Fastly, Reddit, CNN, and BuzzFeed through the Fastly redirect; Meta services through the Meta profile; explicit blocked CIDRs; private and Iranian IPs direct; Fastly IPs through the Fastly redirect; then direct fallback. The small domains/mitm-*.txt files only cover upstream rules that are not Geosite categories.
mattlab replaces Xray in the MITM-DomainFronting approach for Psiphon. It requires a patched Psiphon client (see PsiphonOverMITM/) that uses mattlab as its upstream proxy.
Psiphon (patched)
│ upstream proxy: 127.0.0.1:10808
▼
mattlab HTTP/SOCKS5 proxy
│ MITM: terminates client TLS, re-dials CDN with Chrome-83 uTLS
│
├── ~akamai hostnames ──► akamai-mitm ──► Akamai CDN edge ──► Psiphon meek server
├── Akamai IPs (9x) ──► akamai-mitm ──► (same, via DNS fallback)
├── Fastly IPs ──► fastly-mitm ──► Fastly CDN (pypi.org front) ──► Psiphon meek server
└── everything else ──► direct
Psiphon's FrontedMeekDialOverrides (injected by the patch) tells tunnel-core to use Chrome-83 TLS profile, per-IP SNI, and http/1.1 ALPN for Akamai and h2+http/1.1 for Fastly. mattlab matches this exactly.
Psiphon hardcodes 9 specific Akamai edge IPs. When these are TCP-blocked (common in Iran), mattlab tries CDN hostnames first (a248.e.akamai.net, a.akamaized.net) which DNS-resolve to locally-reachable Akamai edges. The meek Host: header inside the tunnel routes the request to Psiphon's origin regardless of which edge is used.
mattlab auto-generates a local CA on first run (stored in .mattlab_ca/ next to the config). Install the CA on the device:
- Windows/Android: open
http://<host>:8080in a browser — the cert server serves the CA cert and an iOS/Android profile for download. - mattlab signs per-domain certs on the fly; no manual cert management needed.
{
"inbounds": {
"http_proxy": { "enabled": true, "port": 10808 },
"socks5": { "enabled": true, "port": 10809 },
"cert_server": { "enabled": true, "port": 8080 }
},
"outbounds": [
{
"tag": "akamai-mitm",
"type": "domain_front",
"target_ips": [
"a248.e.akamai.net",
"a.akamaized.net",
"23.215.0.206", "23.215.0.203",
"23.212.250.91", "23.212.250.78",
"23.12.147.13", "23.12.147.29",
"23.73.207.8", "23.73.207.15",
"92.123.102.43"
],
"target_port": 443,
"front_sni": "",
"fingerprint": "chrome"
},
{
"tag": "fastly-mitm",
"type": "domain_front",
"target_ips": ["pypi.org"],
"target_port": 443,
"front_sni": "pypi.org",
"fingerprint": "chrome"
},
{ "tag": "direct", "type": "direct" }
],
"routes": [
{ "domains": "domains/psiphon-akamai.txt", "outbound": "akamai-mitm" },
{ "domains": "domains/psiphon-akamai-ips.txt", "outbound": "akamai-mitm" },
{ "geoip": "geoip.dat", "geocode": "FASTLY", "outbound": "fastly-mitm" }
],
"default_outbound": "direct"
}Then set Psiphon's upstream proxy to 127.0.0.1:10808 (HTTP) or 127.0.0.1:10809 (SOCKS5).
| File | Matches | Routes to |
|---|---|---|
domains/psiphon-akamai.txt |
any hostname containing akamai |
akamai-mitm |
domains/psiphon-akamai-ips.txt |
the 9 specific Psiphon Akamai IPs | akamai-mitm |
GeoIP FASTLY |
Fastly IP ranges | fastly-mitm |
- MasterHttpRelayVPN
- @patterniha — Xray domain fronting config reference