Skip to content

Commit a125330

Browse files
committed
Add README
1 parent 85048e8 commit a125330

File tree

4 files changed

+307
-0
lines changed

4 files changed

+307
-0
lines changed

LICENSE

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2015 The Chromium Authors. All rights reserved.
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions are
5+
// met:
6+
//
7+
// * Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
// * Redistributions in binary form must reproduce the above
10+
// copyright notice, this list of conditions and the following disclaimer
11+
// in the documentation and/or other materials provided with the
12+
// distribution.
13+
// * Neither the name of Google Inc. nor the names of its
14+
// contributors may be used to endorse or promote products derived from
15+
// this software without specific prior written permission.
16+
//
17+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# NaïveProxy ![build workflow](https://github.com/klzgrad/naiveproxy/actions/workflows/build.yml/badge.svg)
2+
3+
NaïveProxy uses Chromium's network stack to camouflage traffic with strong censorship resistence and low detectablility. Reusing Chrome's stack also ensures best practices in performance and security.
4+
5+
The following traffic attacks are mitigated by using Chromium's network stack:
6+
7+
* Website fingerprinting / traffic classification: [mitigated](https://arxiv.org/abs/1707.00641) by traffic multiplexing in HTTP/2.
8+
* [TLS parameter fingerprinting](https://arxiv.org/abs/1607.01639): defeated by reusing [Chrome's network stack](https://www.chromium.org/developers/design-documents/network-stack).
9+
* [Active probing](https://ensa.fi/active-probing/): defeated by *application fronting*, i.e. hiding proxy servers behind a commonly used frontend server with application-layer routing.
10+
* Length-based traffic analysis: mitigated by length padding.
11+
12+
## Architecture
13+
14+
[Browser → Naïve client] ⟶ Censor ⟶ [Frontend → Naïve server] ⟶ Internet
15+
16+
NaïveProxy uses Chromium's network stack to parrot traffic between regular Chrome browsers and standard frontend servers.
17+
18+
The frontend server can be any well-known reverse proxy that is able to route HTTP/2 traffic based on HTTP authorization headers, preventing active probing of proxy existence. Known ones include Caddy with its forwardproxy plugin and HAProxy.
19+
20+
The Naïve server here works as a forward proxy and a packet length padding layer. Caddy forwardproxy is also a forward proxy but it lacks a padding layer. A [fork](https://github.com/klzgrad/forwardproxy) adds the NaïveProxy padding layer to forwardproxy, combining both in one.
21+
22+
## Download NaïveProxy
23+
24+
Download [here](https://github.com/klzgrad/naiveproxy/releases/latest). Supported platforms include: Windows, Android (with [Exclave](https://github.com/dyhkwong/Exclave), [NekoBox](https://github.com/MatsuriDayo/NekoBoxForAndroid)), Linux, Mac OS, and OpenWrt ([support status](https://github.com/klzgrad/naiveproxy/wiki/OpenWrt-Support)).
25+
26+
Users should always use the latest version to keep signatures identical to Chrome.
27+
28+
Build from source: Please see [.github/workflows/build.yml](https://github.com/klzgrad/naiveproxy/blob/master/.github/workflows/build.yml).
29+
30+
## Server setup
31+
32+
The following describes the naïve fork of Caddy forwardproxy setup.
33+
34+
Download [here](https://github.com/klzgrad/forwardproxy/releases/latest) or build from source:
35+
```sh
36+
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
37+
~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy=github.com/klzgrad/forwardproxy@naive
38+
```
39+
40+
Example Caddyfile (replace `user` and `pass` accordingly):
41+
```
42+
{
43+
order forward_proxy before file_server
44+
}
45+
:443, example.com {
46+
tls me@example.com
47+
forward_proxy {
48+
basic_auth user pass
49+
hide_ip
50+
hide_via
51+
probe_resistance
52+
}
53+
file_server {
54+
root /var/www/html
55+
}
56+
}
57+
```
58+
`:443` must appear first for this Caddyfile to work. See Caddyfile [docs](https://caddyserver.com/docs/caddyfile/directives/tls) for customizing TLS certificates. For more advanced usage consider using [JSON for Caddy 2's config](https://caddyserver.com/docs/json/).
59+
60+
Run with the Caddyfile:
61+
```
62+
sudo setcap cap_net_bind_service=+ep ./caddy
63+
./caddy start
64+
```
65+
66+
See also [Systemd unit example](https://github.com/klzgrad/naiveproxy/wiki/Run-Caddy-as-a-daemon) and [HAProxy setup](https://github.com/klzgrad/naiveproxy/wiki/HAProxy-Setup).
67+
68+
## Client setup
69+
70+
Run `./naive` with the following `config.json` to get a SOCKS5 proxy at local port 1080.
71+
```json
72+
{
73+
"listen": "socks://127.0.0.1:1080",
74+
"proxy": "https://user:pass@example.com"
75+
}
76+
```
77+
78+
Or `quic://user:pass@example.com`, if it works better. See also [parameter usage](https://github.com/klzgrad/naiveproxy/blob/master/USAGE.txt) and [performance tuning](https://github.com/klzgrad/naiveproxy/wiki/Performance-Tuning).
79+
80+
## Third-party integration
81+
82+
* [v2rayN](https://github.com/2dust/v2rayN), GUI client, Windows
83+
* [NekoBox for Android](https://github.com/MatsuriDayo/NekoBoxForAndroid), Proxy toolchain, Android
84+
* [NekoRay / NekoBox For PC](https://github.com/MatsuriDayo/nekoray), Qt based GUI, Windows, Linux
85+
86+
## Notes for downstream
87+
88+
Do not use the master branch to track updates, as it rebases from a new root commit for every new Chrome release. Use stable releases and the associated tags to track new versions, where short release notes are also provided.
89+
90+
## Padding protocol, an informal specification
91+
92+
The design of this padding protocol opts for low overhead and easier implementation, in the belief that proliferation of expendable, improvised circumvention protocol designs is a better logistical impediment to censorship research than sophisicated designs.
93+
94+
### Proxy payload padding
95+
96+
NaïveProxy proxies bidirectional streams through HTTP/2 (or HTTP/3) CONNECT tunnels. The bidirectional streams operate in a sequence of reads and writes of data. The first `kFirstPaddings` (8) reads and writes in a bidirectional stream after the stream is established are padded in this format:
97+
```c
98+
struct PaddedData {
99+
uint8_t original_data_size_high; // original_data_size / 256
100+
uint8_t original_data_size_low; // original_data_size % 256
101+
uint8_t padding_size;
102+
uint8_t original_data[original_data_size];
103+
uint8_t zeros[padding_size];
104+
};
105+
```
106+
`padding_size` is a random integer uniformally distributed in [0, `kMaxPaddingSize`] (`kMaxPaddingSize`: 255). `original_data_size` cannot be greater than 65535, or it has to be split into several reads or writes.
107+
108+
`kFirstPaddings` is chosen to be 8 to flatten the packet length distribution spikes formed from common initial handshakes:
109+
- Common client initial sequence: 1. TLS ClientHello; 2. TLS ChangeCipherSpec, Finished; 3. H2 Magic, SETTINGS, WINDOW_UPDATE; 4. H2 HEADERS GET; 5. H2 SETTINGS ACK.
110+
- Common server initial sequence: 1. TLS ServerHello, ChangeCipherSpec, ...; 2. TLS Certificate, ...; 3. H2 SETTINGS; 4. H2 WINDOW_UPDATE; 5. H2 SETTINGS ACK; 6. H2 HEADERS 200 OK.
111+
112+
Further reads and writes after `kFirstPaddings` are unpadded to avoid performance overhead. Also later packet lengths are usually considered less informative.
113+
114+
### H2 RST_STREAM frame padding
115+
116+
In experiments, NaïveProxy tends to send too many RST_STREAM frames per session, an uncommon behavior from regular browsers. To solve this, an END_STREAM DATA frame padded with total length distributed in [48, 72] is prepended to the RST_STREAM frame so it looks like a HEADERS frame. The server often replies to this with a WINDOW_UPDATE because padding is accounted in flow control. Whether this results in a new uncommon behavior is still unclear.
117+
118+
### H2 HEADERS frame padding
119+
120+
The CONNECT request and response frames are too short and too uncommon. To make its length similar to realistic HEADERS frames, a `padding` header is filled with a sequence of symbols that are not Huffman coded and are pseudo-random enough to avoid being indexed. The length of the padding sequence is randomly distributed in [16, 32] (request) or [30, 62] (response).
121+
122+
### Opt-in of padding protocol
123+
124+
NaïveProxy clients should interoperate with any regular HTTP/2 proxies unaware of this padding protocol. NaïveProxy servers (i.e. any proxy server capable of the this padding protocol) should interoperate with any regular HTTP/2 clients (e.g. regular browsers) unaware of this padding protocol.
125+
126+
NaïveProxy servers and clients determines whether the counterpart is capable of this padding protocol by the presence of the `padding` header in the CONNECT request and response respectively. The padding procotol is enabled only if the `padding` header exists.
127+
128+
The first CONNECT request to a server cannot use "Fast Open" to send payload before response, because the server's padding capability has not been determined from the first response and it's unknown whether to send padded or unpadded payload for Fast Open.
129+
130+
## Changes from Chromium upstream
131+
132+
- Minimize source code and build size (0.3% of the original)
133+
- Disable exceptions and RTTI, except on Mac and Android.
134+
- Support OpenWrt builds
135+
- (Android, Linux) Use the builtin verifier instead of the system verifier (drop dependency of NSS on Linux) and read the system trust store from (following Go's behavior in crypto/x509/root_unix.go and crypto/x509/root_linux.go):
136+
- The file in environment variable SSL_CERT_FILE
137+
- The first available file of
138+
- /etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu/Gentoo etc.)
139+
- /etc/pki/tls/certs/ca-bundle.crt (Fedora/RHEL 6)
140+
- /etc/ssl/ca-bundle.pem (OpenSUSE)
141+
- /etc/pki/tls/cacert.pem (OpenELEC)
142+
- /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem (CentOS/RHEL 7)
143+
- /etc/ssl/cert.pem (Alpine Linux)
144+
- Files in the directory of environment variable SSL_CERT_DIR
145+
- Files in the first available directory of
146+
- /etc/ssl/certs (SLES10/SLES11, https://golang.org/issue/12139)
147+
- /etc/pki/tls/certs (Fedora/RHEL)
148+
- /system/etc/security/cacerts (Android)
149+
- Handle AIA response in PKCS#7 format
150+
- Allow higher socket limits for proxies
151+
- Force tunneling for all sockets
152+
- Support HTTP/2 and HTTP/3 CONNECT tunnel Fast Open using the `fastopen` header
153+
- Pad RST_STREAM frames
154+
155+
## Known weaknesses
156+
157+
* HTTP CONNECT Fast Open creates back to back h2 packets consistently, which should not appear so often. This could be fixed with a little bit of corking but it would require surgical change deep in Chromium h2 stack, not very easy to do.
158+
* TLS over TLS requires more handshake round trips than needed by common h2 requests, that is, no h2 requests need these many back and forth handshakes. There is no simple way to avoid this besides doing MITM proxying, breaking E2E encryption.
159+
* TLS over TLS overhead causes visible packet length enlargement and lack of small packets. Removing this overhead also requires MITM proxying.
160+
* TLS over TLS overhead also causes packets to consistently exceed MTU limits, which should not happen for an originating user agent. Fixing this requires re-segmentation and it is not easy to do.
161+
* Packet length obfuscation partly relies on h2 multiplexing, which does not work if there is only one connection, a scenario not uncommon. It is not clear how to create covering co-connections organically (i.e. not hard coded).
162+
* Multiplexing requires use of a few long-lived tunnel connections. It is not clearly how long is appropriate for parroting and how to convincingly rotate the connections if there is an age limit or how to detect and recover stuck tunnel connections convincingly.
163+

USAGE.txt

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
Usage: naive --listen=... --proxy=...
2+
naive [/path/to/config.json]
3+
4+
Description:
5+
6+
naive is a proxy that transports traffic in Chromium's pattern.
7+
It works as both a proxy client and a proxy server or together.
8+
9+
Options in the form of `naive --listen=... --proxy=...` can also be
10+
specified using a JSON file:
11+
12+
{
13+
"listen": "...",
14+
"proxy": "..."
15+
}
16+
17+
Specifying a flag multiple times on the command line is equivalent to
18+
having an array of multiple strings in the JSON file.
19+
20+
Uses "config.json" by default if run without arguments.
21+
22+
Options:
23+
24+
-h, --help
25+
26+
Shows help message.
27+
28+
--version
29+
30+
Prints version.
31+
32+
--listen=LISTEN-URI
33+
34+
LISTEN-URI = <LISTEN-PROTO>"://"[<USER>":"<PASS>"@"][<ADDR>][":"<PORT>]
35+
LISTEN-PROTO = "socks" | "http" | "redir"
36+
37+
Listens at addr:port with protocol <LISTEN-PROTO>.
38+
Can be specified multiple times to listen on multiple ports.
39+
Default proto, addr, port: socks, 0.0.0.0, 1080.
40+
41+
Note: redir requires specific iptables rules and uses no authentication.
42+
43+
(Redirecting locally originated traffic)
44+
iptables -t nat -A OUTPUT -d $proxy_server_ip -j RETURN
45+
iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports 1080
46+
47+
(Redirecting forwarded traffic on a router)
48+
iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-ports 1080
49+
50+
Also activates a DNS resolver on the same UDP port. Similar iptables
51+
rules can redirect DNS queries to this resolver. The resolver returns
52+
artificial addresses that are translated back to the original domain
53+
names in proxy requests and then resolved remotely.
54+
55+
The artificial results are not saved for privacy, so restarting the
56+
resolver may cause downstream to cache stale results.
57+
58+
--proxy=PROXY
59+
60+
PROXY = PROXY-CHAIN | SOCKS-PROXY
61+
PROXY-CHAIN = <PROXY-URI>[","<PROXY-CHAIN>]
62+
PROXY-URI = <PROXY-PROTO>"://"[<USER>":"<PASS>"@"]<HOSTNAME>[":"<PORT>]
63+
PROXY-PROTO = "http" | "https" | "quic"
64+
SOCKS-PROXY = "socks://"<HOSTNAME>[":"<PORT>]
65+
66+
Routes traffic via the proxy chain.
67+
The default proxy is directly connection without proxying.
68+
The last PROXY-URI is negotiated automatically for Naive padding.
69+
Limitations:
70+
* QUIC proxies cannot follow TCP-based proxies in a proxy chain.
71+
* The user needs to ensure there is no loop in the proxy chain.
72+
* SOCKS proxies do not support chaining, authentication, or Naive padding.
73+
74+
--insecure-concurrency=<N>
75+
76+
Use N concurrent tunnel connections to be more robust under bad network
77+
conditions. More connections make the tunneling easier to detect and less
78+
secure. This project strives for the strongest security against traffic
79+
analysis. Using it in an insecure way defeats its purpose.
80+
81+
If you must use this, try N=2 first to see if it solves your issues.
82+
Strongly recommend against using more than 4 connections here.
83+
84+
--extra-headers=...
85+
86+
Appends extra headers in requests to the proxy server.
87+
Multiple headers are separated by CRLF.
88+
89+
--host-resolver-rules="MAP proxy.example.com 1.2.3.4"
90+
91+
Statically resolves a domain name to an IP address.
92+
93+
--resolver-range=CIDR
94+
95+
Uses this range in the builtin resolver. Default: 100.64.0.0/10.
96+
97+
--log=[<path>]
98+
99+
Saves log to the file at <path>. If path is empty, prints to
100+
console. No log is saved or printed by default for privacy.
101+
102+
--log-net-log=<path>
103+
104+
Saves NetLog. View at https://netlog-viewer.appspot.com/.
105+
106+
--ssl-key-log-file=<path>
107+
108+
Saves SSL keys for Wireshark inspection.
109+
110+
--no-post-quantum
111+
112+
Overrides the default and disables post-quantum key agreement.

src/config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"listen": ["socks://127.0.0.1:1080", "http://127.0.0.1:8080"],
3+
"proxy": "https://user:pass@domain.example",
4+
"log": ""
5+
}

0 commit comments

Comments
 (0)