Pichi
Flexible Rule-Based Proxy
Install / Use
/learn @pichi-router/PichiREADME
Pichi 
Pichi is a flexible rule-based proxy.
Build Status
Server/Desktop
| OS | Ubuntu 22.04 | macOS 14 | Windows Server 2022 |
|:---:|:---:|:---:|:---:|
| Toolchain | GCC 12.1.0 | Xcode 16.0 | Visual Studio 2022 |
| Status | |
|
|
Mobile
| OS | Android | iOS |
|:---:|:---:|:---:|
| Toolchain | Android NDK 27c | Xcode 16.0 |
| Status | |
|
Security Alert
According to the report, the TLS fingerprint can be used to recognize the type of TLS client for some censorship. If you want to avoid being censored, please make sure:
- Version 1.5.0 or later is used.
- On TLS client side,
- CMake option
TLS_FINGERPRINTwas enabled while building, and snifield is set for each TLS egress.
- CMake option
- On TLS server side,
- CMake option
TLS_FINGERPRINTwas disabled while building.
- CMake option
Pichi 1.5.0 is trying to emulate TLS fingerprint e47eae8f8c4887b6, which is the fingerprint of Google Chrome lower than 109.
On the other hand, Pichi 1.5.1 or later would randomise TLS extension order to emulate normailised TLS fingerprint N/ffa2ee96ff7b42d4, which is the default behavior of Google Chrome since version 109.
Overview
Pichi is designed
- to support common proxy protocols: HTTP(S)/Socks5(s)/Shadowsocks;
- to dynamically and flexibly control the proxy route: just use RESTful APIs;
- developer oriented: NO GUI, but can be easily integrated into other GUIs;
- for personal usage: performance is important, but not the first priority;
- for multiple platforms: at least Windows, POSIX-compatible, Android and iOS.
Motivation
Proxy is widely applied to traverse through the firewall, hide or change the original address, expose internal service port, etc. But if we iterate some famous proxy tools, it's easily recognized that each of them has at least one of these cons list below:
- Not support all of HTTP, Socks5, Shadowsocks
- Not support multiple ingresses or egresses
- No rule-based routing
As a result, the motivation of pichi is to provide a tool, which can
- support sufficient proxy protocols,
- be easily integrated with GUIs/APPs/scripts, which might have their own rule database,
- control rule-based routing at runtime.
Use cases
Alternative to PAC
If an individual user is using a proxy, it's very common that the network traffic is probably split into 2 pieces of flow, one going through the proxy and another going directly. PAC is a good choice if web browsing is heavily used. But unfortunately, not all applications support PAC, such as most of MUA, IM, and so on.
Pichi is an alternative choice for this situation. It separates routing rules from every application.
<img src="images/use_case_0.png" alt="Use Case 0" width="1024"/>Unify proxy configuration
If the configuration for remote proxies is volatile, such as changing IP/Port periodically, it's a nightmare that lots of clients are using it. Pichi can centralize the varies, rather than editing the configuration client by client.
<img src="images/use_case_1.png" alt="Use Case 1" width="1024"/>TCP Tunnel for DNS
TCP tunnel is very useful if you want to use some DNS servers which might be already poisoned or blocked. Pichi provides tunnel ingress to act as a tunnel. Furthermore, the outgoing egress for each destination will be chosen by following the user-defined rules.
<img src="images/use_case_2.png" alt="Use Case 2" width="1024"/>Transparent proxy
The transparent proxies are usually deployed on some internet exit router in the intranet. The difference between the transparent proxy and others is that the clients use no explicit proxy settings. It is engaging for the devices that can't use proxy settings. On the other hand, the con of the transparent proxy is that it usually requires the root privilege of the router. The proxy can also use rule-based routing to forward the requests from the transparent ingress. And it is easy to understand that the domain rules don't make any sense because the transparent ingress can't provide the domain information.
<img src="images/use_case_3.png" alt="Use Case 3" width="1024"/>To enable the transparent proxy, it's necessary to enable the IP packet redirection on the router. When a redirected packet received, the transparent ingress can read its original destination IP address and TCP port from the firewall, if pichi has enough privilege. Pichi supports netfilter/iptables on Linux and PF on macOS/FreeBSD/OpenBSD. For instance, if pichi is running with the transparent ingress configured as below:
# curl -s http://pichi-router/ingresses | jq .example
{
"type": "transparent",
"bind": [
{
"host": "0.0.0.0",
"port": 1726
}
]
}
we can configure the firewall on Linux like:
# iptables -t nat -A PREROUTING -i eth0 -p tcp -j REDIRECT --to-ports 1726
, on macOS/FreeBSD like:
rdr pass on fxp0 inet proto tcp from fxp0:network to any -> 127.0.0.1 port 1726
, on OpenBSD like:
pass in on fxp0 inet proto tcp from fxp0:network to any rdr-to 127.0.0.1 port 1726
BTW, Here's an assumption that pichi is running on the host enabling the packet redirection with the correct privilege.
Supported protocols
Ingress protocols
- Tunnel: TCP tunnel to multiple destinations to be chosen by pre-defined load balance algorithms
- Transparent: Transparent proxy for TCP
- HTTP Proxy: defined by RFC 2068
- HTTP Tunnel: defined by RFC 2616
- SOCKS5: defined by RFC 1928
- Shadowsocks: defined by shadowsocks.org
- Trojan: defined by trojan-gfw and its websocket extension defined by trojan-go
Egress protocols
- Direct: connecting to destination directly
- Reject: rejecting request immediately or after a fixed/random delay
- HTTP Proxy: defined by RFC 2068
- HTTP Tunnel: defined by RFC 2616
- SOCKS5: defined by RFC 1928
- Shadowsocks: defined by shadowsocks.org
- Trojan: defined by trojan-gfw and its websocket extension defined by trojan-go
NOTE: HTTP egress would like to try HTTP CONNECT first. HTTP proxy will be chosen if the previous handshake is failed.
Get started
Installation
Linux
Please use Docker:
$ docker pull ghcr.io/pichi-router/pichi:latest
$ docker run -d ghcr.io/pichi-router/pichi:latest <options>
macOS
Please use Homebrew:
$ brew tap pichi-router/pichi
$ brew install pichi
$ pichi <options>
FreeBSD
Please use FreeBSD ports.
$ pkg install pichi
Windows or others
Please refer to Build section.
Run
$ pichi -h
Allow options:
-h [ --help ] produce help message
-l [ --listen ] arg (=::1) API server address
-p [ --port ] arg API server port
-g [ --geo ] arg GEO file
--json arg Initail configration(JSON format)
-d [ --daemon ] daemonize
-u [ --user ] arg run as user
--group arg run as group
--port and --geo are mandatory. --json option can take a JSON file as an Initial configuration to specify ingresses/egresses/rules/route. The initial configuration format looks like:
{
"ingresses": {
"ingress-0": {/* ingress configuration */},
"ingress-1": {/* ingress configuration */}
},
"egresses": {
"egress-0": {/* egress configuration */},
"egress-1": {/* egress configuration */}
},
"rules": {
"rule-0": {/* rule configuration */},
"rule-1": {/* rule configuration */}
},
"route": {/* route configuration */}
}
Please refer to Using Pichi API section for the details of configurations of ingress/egress/rule/route.
Furthermore, Pichi server reloads JSON configuration on SIGHUP received if OS supports
