Skip to content

Commit bb592f7

Browse files
committed
Initial commit: Clew v0.7.0
Windows process-level traffic proxy based on WinDivert. Features: * Per-process TCP/UDP traffic redirection to SOCKS5 backends via WinDivert * Rule-based matching (process name, cmdline, image path) with tree propagation * Multiple SOCKS5 proxy groups with per-rule routing * Built-in DNS forwarder with system DNS auto-config and crash recovery * WebView2 native desktop UI (Vue 3 + shadcn-vue) * Optional API token authentication See README.md for user docs, docs/ARCHITECTURE.md for contributor docs.
0 parents  commit bb592f7

153 files changed

Lines changed: 59313 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Visual Studio / MSBuild
2+
.vs/
3+
*.user
4+
*.suo
5+
*.sdf
6+
*.opensdf
7+
*.VC.db
8+
*.VC.VC.opendb
9+
ipch/
10+
11+
# Build outputs
12+
build/
13+
x64/
14+
x86/
15+
Debug/
16+
Release/
17+
*.obj
18+
*.pdb
19+
*.ilk
20+
*.idb
21+
*.exe
22+
*.dll
23+
*.sys
24+
*.lib
25+
*.exp
26+
*.log
27+
28+
# Misc
29+
*.bak
30+
*.tmp
31+
*.cache
32+
Thumbs.db
33+
.DS_Store
34+
35+
# Node / frontend
36+
node_modules/
37+
frontend/dist/
38+
39+
# Python
40+
__pycache__/
41+
*.pyc
42+
43+
# Claude Code session data (should never happen in public repo, but just in case)
44+
.claude/
45+
.worktrees/
46+
tasks/
47+
48+
# User runtime config (contains personal proxy addresses, tokens)
49+
clew.json
50+
51+
# Keep the icon even though *.ico could match a build artifact pattern elsewhere
52+
!assets/clew.ico

CMakeLists.txt

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
project(Clew VERSION 0.7.0 LANGUAGES CXX)
3+
4+
set(CMAKE_CXX_STANDARD 23)
5+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6+
7+
# Windows-specific settings
8+
if(WIN32)
9+
add_definitions(-DWIN32_LEAN_AND_MEAN -DNOMINMAX -D_WIN32_WINNT=0x0A00)
10+
endif()
11+
12+
# MSVC-specific settings
13+
if(MSVC)
14+
add_compile_options(/utf-8)
15+
endif()
16+
17+
# Option to enable WebView2 GUI support
18+
option(CLEW_ENABLE_WEBVIEW2 "Enable WebView2 GUI support" OFF)
19+
20+
# ============================================================
21+
# Dependencies (vcpkg)
22+
# ============================================================
23+
find_package(quill CONFIG REQUIRED)
24+
find_package(nlohmann_json CONFIG REQUIRED)
25+
find_package(httplib CONFIG REQUIRED)
26+
find_package(asio CONFIG REQUIRED)
27+
28+
# ============================================================
29+
# Clew main executable
30+
# ============================================================
31+
32+
# Include directories
33+
include_directories(
34+
${CMAKE_SOURCE_DIR}/src
35+
${CMAKE_SOURCE_DIR}/WinDivert-2.2.2-A/include
36+
)
37+
38+
# Link directories
39+
link_directories(
40+
${CMAKE_SOURCE_DIR}/WinDivert-2.2.2-A/x64
41+
)
42+
43+
# Source files (header-only architecture, single translation unit)
44+
set(CLEW_SOURCES
45+
src/main.cpp
46+
)
47+
48+
# Embed the Clew icon via a Win32 resource file.
49+
if(WIN32)
50+
list(APPEND CLEW_SOURCES ${CMAKE_SOURCE_DIR}/assets/clew.rc)
51+
endif()
52+
53+
# Executable
54+
if(CLEW_ENABLE_WEBVIEW2)
55+
add_executable(clew WIN32 ${CLEW_SOURCES})
56+
target_compile_definitions(clew PRIVATE CLEW_HAS_WEBVIEW2)
57+
else()
58+
add_executable(clew ${CLEW_SOURCES})
59+
endif()
60+
61+
# UAC elevation: embed manifest requesting administrator privileges
62+
# (WinDivert and SetInterfaceDnsSettings both require elevation)
63+
if(MSVC)
64+
target_link_options(clew PRIVATE
65+
"/MANIFESTUAC:level='requireAdministrator' uiAccess='false'")
66+
endif()
67+
68+
# Base libraries
69+
set(CLEW_LIBRARIES
70+
ws2_32
71+
iphlpapi
72+
WinDivert
73+
quill::quill
74+
nlohmann_json::nlohmann_json
75+
httplib::httplib
76+
asio::asio
77+
)
78+
79+
# WebView2 configuration
80+
if(CLEW_ENABLE_WEBVIEW2)
81+
set(WEBVIEW2_PATH "${CMAKE_SOURCE_DIR}/src/ui/third_party/WebView2" CACHE PATH "Path to WebView2 SDK")
82+
83+
if(EXISTS "${WEBVIEW2_PATH}/build/native/include/WebView2.h")
84+
message(STATUS "Found WebView2 SDK at ${WEBVIEW2_PATH}")
85+
include_directories("${WEBVIEW2_PATH}/build/native/include")
86+
87+
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
88+
set(WEBVIEW2_ARCH "x64")
89+
else()
90+
set(WEBVIEW2_ARCH "x86")
91+
endif()
92+
93+
if(EXISTS "${WEBVIEW2_PATH}/build/native/${WEBVIEW2_ARCH}/WebView2LoaderStatic.lib")
94+
list(APPEND CLEW_LIBRARIES
95+
"${WEBVIEW2_PATH}/build/native/${WEBVIEW2_ARCH}/WebView2LoaderStatic.lib"
96+
)
97+
message(STATUS "Using WebView2LoaderStatic.lib")
98+
elseif(EXISTS "${WEBVIEW2_PATH}/build/native/${WEBVIEW2_ARCH}/WebView2Loader.dll.lib")
99+
list(APPEND CLEW_LIBRARIES
100+
"${WEBVIEW2_PATH}/build/native/${WEBVIEW2_ARCH}/WebView2Loader.dll.lib"
101+
)
102+
add_custom_command(TARGET clew POST_BUILD
103+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
104+
"${WEBVIEW2_PATH}/build/native/${WEBVIEW2_ARCH}/WebView2Loader.dll"
105+
"$<TARGET_FILE_DIR:clew>"
106+
)
107+
message(STATUS "Using WebView2Loader.dll")
108+
else()
109+
message(WARNING "WebView2Loader library not found")
110+
endif()
111+
else()
112+
message(WARNING "WebView2 SDK not found at ${WEBVIEW2_PATH}")
113+
endif()
114+
endif()
115+
116+
# Link libraries
117+
target_link_libraries(clew ${CLEW_LIBRARIES})
118+
119+
# Copy WinDivert DLL to output directory
120+
add_custom_command(TARGET clew POST_BUILD
121+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
122+
"${CMAKE_SOURCE_DIR}/WinDivert-2.2.2-A/x64/WinDivert.dll"
123+
"$<TARGET_FILE_DIR:clew>"
124+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
125+
"${CMAKE_SOURCE_DIR}/WinDivert-2.2.2-A/x64/WinDivert64.sys"
126+
"$<TARGET_FILE_DIR:clew>"
127+
)

CMakePresets.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"version": 3,
3+
"configurePresets": [
4+
{
5+
"name": "windows-vcpkg",
6+
"displayName": "Windows x64 with Vcpkg",
7+
"generator": "Visual Studio 17 2022",
8+
"binaryDir": "${sourceDir}/build",
9+
"cacheVariables": {
10+
"CMAKE_TOOLCHAIN_FILE": "D:/public_library/raw_libs/vcpkg/scripts/buildsystems/vcpkg.cmake",
11+
"VCPKG_TARGET_TRIPLET": "x64-windows",
12+
"CLEW_ENABLE_WEBVIEW2": "ON"
13+
}
14+
}
15+
]
16+
}

LICENSE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
MIT License
2+
3+
Copyright (c) 2026 ymonster
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+
23+
---
24+
25+
Third-party components:
26+
27+
* WinDivert (https://github.com/basil00/Divert) — dynamically loaded at runtime.
28+
Licensed under LGPL v3 (or GPL v2 at the user's choice).
29+
Original license text preserved in WinDivert-2.2.2-A/LICENSE.

README.en.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Clew
2+
3+
> Windows process-level traffic proxy
4+
5+
**Languages**: [简体中文](README.md) · [English](README.en.md)
6+
7+
---
8+
9+
## Overview
10+
11+
Clew is a process-level transparent proxy for Windows. In spirit, it's like Proxifier or SocksCap. The original motivation was that antigravity without TUN mode had various issues, and with TUN mode on it broke other apps — I didn't like hijacking traffic globally, so I built this.
12+
13+
- **Based on WinDivert**: building our own WFP driver needs code signing (annual fee), not worth it for a personal open-source project
14+
- **Process-tree proxying**: match by process name, command line, or image path; the entire child-process tree (including dynamically spawned children) is proxied together
15+
- **Multiple SOCKS5 backends**: configure several proxy groups on one machine, route different rules to different groups
16+
- **UDP support**: per-app-port SOCKS5 UDP ASSOCIATE, strictly RFC 1928 compliant
17+
- **Built-in DNS forwarder**: auto-configures system DNS to a local forwarder that sends queries through SOCKS5 UDP to upstream resolvers (8.8.8.8, etc.), solving DNS pollution and geo-mismatch issues
18+
- **WebView2 native UI**: Vue 3 + shadcn-vue, no browser required
19+
20+
## Install & Run
21+
22+
### Requirements
23+
24+
- Windows 10 (version 2004+) or Windows 11
25+
- Administrator privileges (required for both WinDivert driver and system DNS configuration)
26+
27+
### Download
28+
29+
Grab the latest release from [Releases](https://github.com/ymonster/clew-proxy/releases). You may need to install the VS2022 redistributable (available from Microsoft's site).
30+
31+
## Usage
32+
33+
### 1. Configure proxy backend
34+
35+
Settings → Proxies. A `default` group exists; change host / port to point at your SOCKS5 proxy (e.g., Clash / Shadowsocks at `127.0.0.1:7890`).
36+
37+
### 2. Add an Auto Rule
38+
39+
Auto Rules tab → New:
40+
41+
- **Process name**: glob wildcards supported, e.g., `curl*`, `python.exe`, `*.exe`
42+
- **Cmdline pattern**: keywords that must appear in the command line (space-separated, case-insensitive, order-independent)
43+
- **Hack tree**: on = also proxy all child processes
44+
- **Protocol**: TCP / UDP / Both
45+
- **Proxy group**: which proxy group to route through
46+
47+
Save → launching the matching process triggers the proxy.
48+
49+
### 3. Manually proxy a process
50+
51+
In the **Process Tree**, hovering over a process reveals a small icon on the right; click it to proxy.
52+
53+
### 4. DNS Proxy
54+
55+
Some apps (Spotify, certain geo-sensitive services) have trouble with DNS resolution. Enable Settings → DNS Proxy:
56+
57+
- **Forwarder mode**: auto-reconfigures system DNS to `127.0.0.2` (Clew's built-in forwarder). All DNS queries go through SOCKS5 → upstream.
58+
- On disable / exit, the system DNS is auto-restored. Even if the process is force-killed, the next launch detects and restores the original configuration.
59+
60+
### Why WinDivert
61+
62+
- WinDivert is a mature WFP callout driver with stable Win10/11 support, open source, and actively maintained
63+
- **LGPL v3** licensing lets us dynamically link the `.dll` without forcing our main project license
64+
- Its dual-layer architecture (SOCKET SNIFF + NETWORK reflection) records the `PID → group` mapping at connect time, so the redirection path is zero-lookup
65+
- **WinDivert is free, our code is open source — zero cost**
66+
67+
### Why no Hook mode (DLL injection)
68+
69+
I tried a DLL injection + `GetAddrInfoW` hook path, but two issues came up:
70+
71+
1. **Chromium / Electron apps use their own DNS resolver**: modern Chromium increasingly bypasses `GetAddrInfoW` in favor of an async UDP DNS client. Hooking just `GetAddrInfoW` misses those (Spotify worked in testing, but changing the proxy backend's own DNS config achieves the same thing).
72+
2. **Full-stack hooking is expensive**: reliable proxying needs `getaddrinfo` / `GetAddrInfoW` / `connect` / `WSAConnect` / `ConnectEx` hooked simultaneously, plus dealing with sandbox policies (`ProcessSignaturePolicy`), signature enforcement, anti-injection, etc. (Signing isn't free either!)
73+
74+
### v2: things I might do
75+
76+
1. If enough people actually need it, I might do an in-house WFP callout driver paired with `PsSetCreateProcessNotifyRoutineEx` — more thorough than today, wouldn't miss any event. The blocker is the annual signing cost.
77+
78+
For my personal use, what we have is enough. Full-stack hooking remains an option too.
79+
80+
2. Application-layer protocol identification (http/quic/...)
81+
3. LUA plugin support, so users can mutate upstream/downstream traffic for specific processes and protocols
82+
83+
## Build
84+
85+
### Prerequisites
86+
87+
- Visual Studio 2022
88+
- CMake 3.20+
89+
- vcpkg (`quill`, `nlohmann-json`, `cpp-httplib`, `asio`)
90+
- Node.js 20+ (frontend build)
91+
- WebView2 Runtime (bundled on Win11; download from Microsoft on Win10)
92+
93+
### Steps
94+
95+
```bash
96+
# 1. Configure
97+
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 --preset windows-vcpkg
98+
99+
# 2. Build backend
100+
cmake --build build --config Release
101+
102+
# 3. Build frontend
103+
cd frontend
104+
npm install
105+
npm run build
106+
cd ..
107+
108+
# 4. Run
109+
./build/Release/clew.exe
110+
```
111+
112+
## License
113+
114+
- Clew itself: [MIT](LICENSE)
115+
- [WinDivert](https://github.com/basil00/Divert) dependency: LGPL v3 (dynamically linked; original license kept at `WinDivert-2.2.2-A/LICENSE`)

0 commit comments

Comments
 (0)