feat: add native HTTP and HTTPS proxy - #64
Conversation
|
Thank you for submitting this PR. However, I do not think this feature is suitable for inclusion in this project. The primary purpose of this project is to manage and run
Therefore, the main use cases implemented by this PR can already be covered using native frp configurations, without maintaining another proxy server inside the application. In addition, this PR would introduce an NDK/CMake/JNI/C++ implementation independent of frp. The project would need to maintain its own HTTP request parsing, DNS resolution, socket forwarding, concurrent connection handling, and HTTPS The current implementation also has several limitations:
The following compares this PR with three native frp configurations. There are four deployment modes in total. Mode 1 can replace the functionality of this PR, while Modes 2 and 3 cover two additional deployment scenarios. This PR: native proxy on AndroidTraffic flowThe connection to the destination website is created directly by the Android device: This implementation does not use Mode 1: frps and frpc + http_proxy both running on AndroidThis mode is suitable when:
Traffic flowAndroid:
|
| Mode | Client connects to | HTTP proxy actually runs on | Exit IP | Proxy authentication |
|---|---|---|---|---|
| This PR | Android:8080 | Native C++ service on Android | Android | Not supported |
| Android frps + Android frpc plugin | Android:8080 | Android | Android | Supported |
| Remote frps + Android frpc plugin | Remote server:6000 | Android | Android | Supported |
| Android STCP visitor + remote frpc plugin | Android:8080 | Remote server | Remote server | Supported |
The three native frp configurations already cover:
- Providing a local or LAN proxy endpoint on Android with Android as the exit;
- Exposing an Android-hosted proxy through a remote
frps, while retaining Android as the exit; - Providing a local or LAN proxy endpoint on Android while using a remote server as the exit.
The one-click experience provided by this PR is useful. However, I believe the more appropriate implementation would be to help users generate and manage the corresponding frp configurations through the application UI, rather than adding and maintaining another proxy server implementation.
For these reasons, I will not merge this PR. Thank you again for the contribution and for exploring this use case.
中文
感谢你提交这个 PR,但是我认为这个功能不适合合并到本项目中。
本项目的主要定位是管理和运行 frpc、frps,而 frp 本身已经提供了内置的 http_proxy 客户端插件,支持:
- HTTP 正向代理;
- HTTPS
CONNECT隧道; - HTTP 代理用户名和密码认证;
- 与 TCP、STCP visitor 等 frp 功能组合使用。
因此,本 PR 实现的主要使用场景已经可以通过 frp 原生配置完成,不需要在应用中另外维护一套代理服务器。
此外,本 PR 会给项目增加一套独立于 frp 的 NDK/CMake/JNI/C++ 实现,需要自行维护 HTTP 请求解析、DNS、套接字转发、并发连接和 HTTPS CONNECT 等逻辑。
当前实现还存在以下限制:
- 端口固定为
8080; - 固定监听所有网络接口;
- 没有代理认证;
- 没有 SOCKS5 支持;
- 在不可信网络中可能成为未认证的开放代理;
- 与 frp 上游已经维护的功能存在较大重复。
下面对本 PR 与三种 frp 原生方案进行比较,共四种实现方式。
方式一即可替代本 PR 的功能,方式二和方式三则覆盖了另外两种使用场景。
本 PR:Android 原生代理
流量路径
客户端
→ Android:8080
→ Android 上的原生 C++ HTTP 代理
→ 目标网站
最终访问目标网站的连接由 Android 设备直接发起:
出口 IP = Android 设备的公网 IP
这个实现不经过 frpc 或 frps,也不能将流量出口切换到远程服务器。
方式一:Android 同时运行 frps 和 frpc + http_proxy
这个方案适合:
- 客户端直接连接 Android 的代理端口;
- 实际 HTTP 代理运行在 Android;
- 使用 Android 的网络作为出口。
流量路径
客户端
→ Android:8080
→ frps
→ 同一 Android 设备上的 frpc/http_proxy
→ 目标网站
Android:frps.toml
# 仅接收本机 frpc 的控制连接。
bindAddr = "127.0.0.1"
bindPort = 7000
# 向局域网开放代理端口。
proxyBindAddr = "0.0.0.0"
auth.method = "token"
auth.token = "replace-with-a-strong-frp-token"Android:frpc.toml
serverAddr = "127.0.0.1"
serverPort = 7000
auth.method = "token"
auth.token = "replace-with-a-strong-frp-token"
[[proxies]]
name = "android-http-proxy"
type = "tcp"
remotePort = 8080
[proxies.plugin]
type = "http_proxy"
httpUser = "proxyuser"
httpPassword = "replace-with-a-strong-proxy-password"客户端配置
HTTP 代理地址:Android 设备的局域网 IP
端口:8080
用户名:proxyuser
密码:replace-with-a-strong-proxy-password
因为 http_proxy 插件运行在 Android 设备:
出口 IP = Android 设备的公网 IP
该配置可以提供与本 PR 相同的核心功能,同时复用 frp 已有的代理实现和认证能力。
方式二:远程运行 frps,Android 运行 frpc + http_proxy
这个方案适合:
- 客户端连接远程服务器的代理端口;
- 实际 HTTP 代理运行在 Android;
- 使用 Android 的网络作为出口。
流量路径
客户端
→ 远程服务器:6000
→ frps
→ frp 隧道
→ Android frpc 的 http_proxy 插件
→ 目标网站
远程服务器:frps.toml
bindAddr = "0.0.0.0"
bindPort = 7000
auth.method = "token"
auth.token = "replace-with-a-strong-frp-token"Android:frpc.toml
serverAddr = "VPS_PUBLIC_IP"
serverPort = 7000
auth.method = "token"
auth.token = "replace-with-a-strong-frp-token"
[[proxies]]
name = "android-http-proxy"
type = "tcp"
remotePort = 6000
[proxies.plugin]
type = "http_proxy"
httpUser = "proxyuser"
httpPassword = "replace-with-a-strong-proxy-password"客户端配置
HTTP 代理地址:VPS_PUBLIC_IP
端口:6000
用户名:proxyuser
密码:replace-with-a-strong-proxy-password
虽然客户端连接的是远程服务器,但 http_proxy 插件实际运行在 Android:
出口 IP = Android 设备的公网 IP
方式三:Android 提供本地代理入口,远程服务器作为出口
这个方案适合:
- 局域网客户端连接
ANDROID_IP:8080; - 流量通过 frp 隧道发送到远程服务器;
- 远程服务器负责访问目标网站;
- 最终出口为远程服务器 IP。
流量路径
局域网客户端
→ Android:8080
→ Android frpc 的 STCP visitor
→ 远程 frps
→ 远程 frpc 的 http_proxy 插件
→ 目标网站
远程服务器:frps.toml
bindAddr = "0.0.0.0"
bindPort = 7000
auth.method = "token"
auth.token = "replace-with-a-strong-frp-token"远程服务器:出口端 frpc.toml
user = "proxy-exit"
serverAddr = "127.0.0.1"
serverPort = 7000
auth.method = "token"
auth.token = "replace-with-a-strong-frp-token"
[[proxies]]
name = "vps-http-exit"
type = "stcp"
secretKey = "replace-with-a-strong-stcp-secret"
[proxies.plugin]
type = "http_proxy"
httpUser = "proxyuser"
httpPassword = "replace-with-a-strong-proxy-password"Android:访问端 frpc.toml
user = "proxy-exit"
serverAddr = "VPS_PUBLIC_IP"
serverPort = 7000
auth.method = "token"
auth.token = "replace-with-a-strong-frp-token"
[[visitors]]
name = "vps-http-exit-visitor"
type = "stcp"
serverName = "vps-http-exit"
secretKey = "replace-with-a-strong-stcp-secret"
bindAddr = "0.0.0.0"
bindPort = 8080局域网客户端配置
HTTP 代理地址:Android 设备的局域网 IP
端口:8080
用户名:proxyuser
密码:replace-with-a-strong-proxy-password
因为真正的 http_proxy 插件运行在远程服务器:
出口 IP = 远程服务器的公网 IP
如果代理只允许 Android 设备本机使用,可以将 visitor 改为:
bindAddr = "127.0.0.1"四种方式对比
| 方式 | 客户端连接地址 | HTTP 代理实际运行位置 | 出口 IP | 代理认证 |
|---|---|---|---|---|
| 本 PR | Android:8080 | Android 原生 C++ 服务 | Android | 不支持 |
| Android frps + Android frpc 插件 | Android:8080 | Android | Android | 支持 |
| 远程 frps + Android frpc 插件 | 远程服务器:6000 | Android | Android | 支持 |
| Android STCP visitor + 远程 frpc 插件 | Android:8080 | 远程服务器 | 远程服务器 | 支持 |
由此可见,frp 原生的三种组合已经覆盖了:
- 在 Android 上提供本地或局域网代理入口,并使用 Android 作为出口;
- 通过远程
frps暴露 Android 上的代理,并继续使用 Android 作为出口; - 在 Android 上提供本地或局域网代理入口,同时使用远程服务器作为出口。
本 PR 的一键开关体验确实比较方便,但我认为更合适的实现方式是在应用界面中帮助用户生成和管理上述 frp 配置,而不是在项目中增加并长期维护另一套代理服务器。
基于以上原因,我不会合并这个 PR。再次感谢你的贡献和对这个使用场景的探索。
Add http and https proxy service in settings.