Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ from every push to `main`; this file is the change history. Versions after 1.12
`MAJOR.MINOR.PATCH` (1.12 is followed by 1.12.1 or 1.13.0); the headings below keep the
numbers as released.

## 1.13.0 — 2026-10-17

One binary per platform (#43) and the `MAJOR.MINOR.PATCH` versions (#44).

- The release has one binary per platform, `vtesse-<arch>`, with both backends (lwIP, and
TAP with `--tap`). The TAP-only `vtesse-tap-<arch>` is no longer published: its links
return 404, use `vtesse-<arch> --tap`; the binary name on the device and the command line
stay the same. It costs 72–83 KiB per binary (31–44 KiB compressed on flash); the release
goes from 17 files to 12. `make LWIP=0` still builds a TAP-only binary (CI and the bench
test it).
- Versions are `MAJOR.MINOR.PATCH` from this one on; CI checks that a code or build change
comes with a new version and its section here. The Android `versionCode` is
`MAJOR*10000 + MINOR*100 + PATCH` (11300; 1.12 was 112), so the update installs.
- READMEs: the OpenIPC and OpenWrt install commands fetch `vtesse-$ARCH`.

## 1.12 — 2026-10-15

Fixes from the first Qodo review of the whole codebase (#34, PR #35):
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Static binaries (no dependencies) are on the [releases page](https://github.com/
| 64-bit ARM: Raspberry Pi with a 64-bit OS, Rockchip, other ARM64 boards | `arm64` |
| PCs and servers | `x86_64` |

Two binaries per platform: `vtesse-ARCH` (lwIP and TAP backends: SOCKS5 / port forwards without root, or a kernel interface with `--tap`) and `vtesse-tap-ARCH` (TAP only, about half the size). The TAP backend needs root and the `tun` driver (`/dev/net/tun`), and the hook scripts `vtesse-hook.sh` and `vtesse-udhcpc.script`.
One binary per platform, `vtesse-ARCH`, with both backends: lwIP (SOCKS5 / port forwards without root) and TAP (a kernel interface with `--tap`). The TAP backend needs root and the `tun` driver (`/dev/net/tun`), and the hook scripts `vtesse-hook.sh` and `vtesse-udhcpc.script`. Until 1.12 a TAP-only `vtesse-tap-ARCH` was published too; its links now return 404, use `vtesse-ARCH --tap` instead.

The releases also carry the VTun server for PCs and servers, `vtund-3.0.2-x86_64`: the original VTun 3.0.2 with our patches (a refused login is logged with the device ID and the reason), see [server/README.md](server/README.md). For cameras and routers vtund is built in the OpenIPC environment when needed.

Expand Down Expand Up @@ -65,7 +65,7 @@ ARCH=arm32
URL=https://github.com/OpenIPC/vtesse/releases/download/latest
# directories, then each file straight to its place, executable on success
mkdir -p /usr/bin /usr/share/vtesse /etc/init.d
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-tap-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/share/vtesse/vtesse-hook.sh $URL/vtesse-hook.sh && chmod 755 /usr/share/vtesse/vtesse-hook.sh
curl -fsSL -o /usr/share/vtesse/vtesse-udhcpc.script $URL/vtesse-udhcpc.script && chmod 755 /usr/share/vtesse/vtesse-udhcpc.script
curl -fsSL -o /etc/init.d/S99vtesse $URL/S99vtesse && chmod 755 /etc/init.d/S99vtesse
Expand All @@ -89,7 +89,7 @@ opkg update && opkg install curl kmod-tun # kmod-tun is needed for --tap only;
ARCH=mipsel
URL=https://github.com/OpenIPC/vtesse/releases/download/latest
mkdir -p /usr/bin /usr/share/vtesse /etc/init.d
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-tap-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/share/vtesse/vtesse-hook.sh $URL/vtesse-hook.sh && chmod 755 /usr/share/vtesse/vtesse-hook.sh
curl -fsSL -o /usr/share/vtesse/vtesse-udhcpc.script $URL/vtesse-udhcpc.script && chmod 755 /usr/share/vtesse/vtesse-udhcpc.script
curl -fsSL -o /etc/init.d/vtesse $URL/vtesse.init && chmod 755 /etc/init.d/vtesse
Expand Down
6 changes: 3 additions & 3 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
| 64-битный ARM: Raspberry Pi с 64-битной ОС, Rockchip, другие платы ARM64 | `arm64` |
| ПК и серверы | `x86_64` |

На каждую платформу два бинарника: `vtesse-ARCH` (режимы lwIP и TAP: SOCKS5 / проброс портов без root или интерфейс ядра с `--tap`) и `vtesse-tap-ARCH` (только TAP, примерно вдвое меньше). Режиму TAP нужны root, драйвер `tun` (`/dev/net/tun`) и хук-скрипты `vtesse-hook.sh` и `vtesse-udhcpc.script`.
На каждую платформу один бинарник, `vtesse-ARCH`, с обоими режимами: lwIP (SOCKS5 / проброс портов без root) и TAP (интерфейс ядра с `--tap`). Режиму TAP нужны root, драйвер `tun` (`/dev/net/tun`) и хук-скрипты `vtesse-hook.sh` и `vtesse-udhcpc.script`. До версии 1.12 выкладывался ещё `vtesse-tap-ARCH` (только TAP); его ссылки теперь отдают 404, вместо него — `vtesse-ARCH --tap`.

В релизах также есть сервер VTun для ПК и серверов, `vtund-3.0.2-x86_64`: оригинальный VTun 3.0.2 с нашими патчами (отказ во входе пишется в лог с ID устройства и причиной), см. [server/README.md](server/README.md). Для камер и роутеров vtund при необходимости собирается в среде OpenIPC.

Expand Down Expand Up @@ -65,7 +65,7 @@ ARCH=arm32
URL=https://github.com/OpenIPC/vtesse/releases/download/latest
# каталоги, затем каждый файл сразу на своё место, права — после успешной загрузки
mkdir -p /usr/bin /usr/share/vtesse /etc/init.d
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-tap-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/share/vtesse/vtesse-hook.sh $URL/vtesse-hook.sh && chmod 755 /usr/share/vtesse/vtesse-hook.sh
curl -fsSL -o /usr/share/vtesse/vtesse-udhcpc.script $URL/vtesse-udhcpc.script && chmod 755 /usr/share/vtesse/vtesse-udhcpc.script
curl -fsSL -o /etc/init.d/S99vtesse $URL/S99vtesse && chmod 755 /etc/init.d/S99vtesse
Expand All @@ -89,7 +89,7 @@ opkg update && opkg install curl kmod-tun # kmod-tun нужен только
ARCH=mipsel
URL=https://github.com/OpenIPC/vtesse/releases/download/latest
mkdir -p /usr/bin /usr/share/vtesse /etc/init.d
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-tap-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/share/vtesse/vtesse-hook.sh $URL/vtesse-hook.sh && chmod 755 /usr/share/vtesse/vtesse-hook.sh
curl -fsSL -o /usr/share/vtesse/vtesse-udhcpc.script $URL/vtesse-udhcpc.script && chmod 755 /usr/share/vtesse/vtesse-udhcpc.script
curl -fsSL -o /etc/init.d/vtesse $URL/vtesse.init && chmod 755 /etc/init.d/vtesse
Expand Down
6 changes: 3 additions & 3 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
| 64 位 ARM:运行 64 位系统的树莓派、瑞芯微及其他 ARM64 开发板 | `arm64` |
| PC 与服务器 | `x86_64` |

每个平台提供两个二进制文件:`vtesse-ARCH`(lwIP 与 TAP 两种后端:无需 root 的 SOCKS5 / 端口转发,或使用 `--tap` 的内核接口)和 `vtesse-tap-ARCH`(仅 TAP,体积约为一半)。TAP 后端需要 root、`tun` 驱动(`/dev/net/tun`)以及钩子脚本 `vtesse-hook.sh` 和 `vtesse-udhcpc.script`。
每个平台只提供一个二进制文件 `vtesse-ARCH`,包含两种后端:lwIP(无需 root 的 SOCKS5 / 端口转发)和 TAP(使用 `--tap` 的内核接口)。TAP 后端需要 root、`tun` 驱动(`/dev/net/tun`)以及钩子脚本 `vtesse-hook.sh` 和 `vtesse-udhcpc.script`。在 1.12 及之前还发布仅含 TAP 的 `vtesse-tap-ARCH`;其链接现在返回 404,请改用 `vtesse-ARCH --tap`。

发布页还提供面向 PC 和服务器的 VTun 服务器 `vtund-3.0.2-x86_64`:原版 VTun 3.0.2 加上我们的补丁(登录被拒时日志会记录设备 ID 和原因),详见 [server/README.md](server/README.md)。摄像头和路由器如需 vtund,请在 OpenIPC 环境中构建。

Expand Down Expand Up @@ -65,7 +65,7 @@ ARCH=arm32
URL=https://github.com/OpenIPC/vtesse/releases/download/latest
# 先建目录,再把每个文件直接下载到目标位置,下载成功后设置权限
mkdir -p /usr/bin /usr/share/vtesse /etc/init.d
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-tap-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/share/vtesse/vtesse-hook.sh $URL/vtesse-hook.sh && chmod 755 /usr/share/vtesse/vtesse-hook.sh
curl -fsSL -o /usr/share/vtesse/vtesse-udhcpc.script $URL/vtesse-udhcpc.script && chmod 755 /usr/share/vtesse/vtesse-udhcpc.script
curl -fsSL -o /etc/init.d/S99vtesse $URL/S99vtesse && chmod 755 /etc/init.d/S99vtesse
Expand All @@ -89,7 +89,7 @@ opkg update && opkg install curl kmod-tun # kmod-tun 仅在使用 --tap 时需
ARCH=mipsel
URL=https://github.com/OpenIPC/vtesse/releases/download/latest
mkdir -p /usr/bin /usr/share/vtesse /etc/init.d
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-tap-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/bin/vtesse $URL/vtesse-$ARCH && chmod 755 /usr/bin/vtesse
curl -fsSL -o /usr/share/vtesse/vtesse-hook.sh $URL/vtesse-hook.sh && chmod 755 /usr/share/vtesse/vtesse-hook.sh
curl -fsSL -o /usr/share/vtesse/vtesse-udhcpc.script $URL/vtesse-udhcpc.script && chmod 755 /usr/share/vtesse/vtesse-udhcpc.script
curl -fsSL -o /etc/init.d/vtesse $URL/vtesse.init && chmod 755 /etc/init.d/vtesse
Expand Down
11 changes: 9 additions & 2 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ plugins {
id("org.jetbrains.kotlin.android")
}

// Version from include/vtesse/version.h ("MAJOR.MM" -> versionCode MAJOR*100+MM).
// Version from include/vtesse/version.h, MAJOR.MINOR.PATCH (the MAJOR.MM versions up
// to 1.12 count as MAJOR.MM.0): versionCode MAJOR*10000 + MINOR*100 + PATCH, so it
// keeps growing past the old MAJOR*100+MM (1.12 was 112) and an update installs.
val vtesseVersion: String = Regex("#define VTESSE_VERSION \"([0-9.]+)\"")
.find(rootProject.file("../include/vtesse/version.h").readText())!!.groupValues[1]

Expand All @@ -28,7 +30,12 @@ android {
minSdk = 21
targetSdk = 35
versionName = vtesseVersion
versionCode = vtesseVersion.split(".").let { it[0].toInt() * 100 + it[1].toInt() }
versionCode = vtesseVersion.split(".").map { it.toInt() }.let {
val minor = it[1]
val patch = it.getOrElse(2) { 0 }
require(minor < 100 && patch < 100) { "VTESSE_VERSION $vtesseVersion: MINOR and PATCH must be below 100" }
it[0] * 10000 + minor * 100 + patch
}
ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
}
Expand Down
19 changes: 8 additions & 11 deletions ci/build-musl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
# MediaTek/Atheros routers (MT7620/7621/7628, ath79), whose kernels often
# lack FPU emulation, so hard-float code dies with SIGILL (#30)
# arm64 | x86_64 | armv5 | armv7 Bootlin musl toolchains
# Produces <outdir>/vtesse-<target> (lwIP + TAP) and <outdir>/vtesse-tap-<target>
# (TAP only, LWIP=0), stripped. For x86_64 also <outdir>/vtund-<vtun version>-x86_64:
# Produces <outdir>/vtesse-<target> (lwIP and TAP backends, --tap), stripped; a TAP-only
# build stays a build option (make LWIP=0) and is not published. For x86_64 also <outdir>/vtund-<vtun version>-x86_64:
# the VTun server with our patches (server/build-vtund.sh), a PC/server binary only;
# VTUND=1 builds it for another target too, VTUND=0 skips it. With QEMU=1 the unit tests are run under
# qemu-user as well. musl is used because a static glibc binary cannot resolve
Expand Down Expand Up @@ -100,14 +100,12 @@ esac

mkdir -p "$OUT"
cd "$ROOT"
for variant in full tap; do
if [ $variant = full ]; then lwip=1; bin=vtesse-$TARGET; else lwip=0; bin=vtesse-tap-$TARGET; fi
build=build-$TARGET-$variant
rm -rf "$build" # objects of another toolchain or profile are never rebuilt by make
make -s BUILD="$build" CROSS_COMPILE="$CROSS" STATIC=1 LWIP=$lwip LWIP_PROFILE=$PROFILE CFLAGS=-Os all tests
"${CROSS}strip" --strip-unneeded -o "$OUT/$bin" "$build/vtesse-cli"
echo "$bin: $(wc -c < "$OUT/$bin") bytes (lwIP profile $PROFILE)"
done
build=build-$TARGET-full
bin=vtesse-$TARGET
rm -rf "$build" # objects of another toolchain or profile are never rebuilt by make
make -s BUILD="$build" CROSS_COMPILE="$CROSS" STATIC=1 LWIP=1 LWIP_PROFILE=$PROFILE CFLAGS=-Os all tests
"${CROSS}strip" --strip-unneeded -o "$OUT/$bin" "$build/vtesse-cli"
echo "$bin: $(wc -c < "$OUT/$bin") bytes (lwIP profile $PROFILE)"

# vtund: PC/server only by default; for cameras and routers it is built in the OpenIPC
# environment when needed (server/README.md)
Expand All @@ -126,7 +124,6 @@ if [ "${QEMU:-0}" = 1 ]; then
echo "$out" | tail -1
done
"$QEMU_BIN" "$OUT/vtesse-$TARGET" --version
"$QEMU_BIN" "$OUT/vtesse-tap-$TARGET" --version
# vtund has no --version; -h prints "VTun ver ..." and the usage, exit code 1
[ -z "$VTUND_BIN" ] || "$QEMU_BIN" "$OUT/$VTUND_BIN" -h 2>&1 | grep "^VTun ver"
fi
20 changes: 11 additions & 9 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,27 @@
[`.github/workflows/build.yml`](../.github/workflows/build.yml) runs on every push
and pull request:

| Job | What it does |
|----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `tests` | `make test`, the same under ASan/UBSan, the `LWIP=0` build |
| `build` (arm32, mipsel, arm64, mips, x86_64) | static musl binaries with `ci/build-musl.sh` (`vtesse`, `vtesse-tap`; patched `vtund` in the x86_64 job), unit tests and a `vtund -h` smoke test under qemu-user, artifacts |
| `bench` | the Docker test bench (vtund built with our patches): `selftest`, `cli-test`, `proxy-test`, `tap-test`, `tun-test`, `udp-test`, `fault-test` |
| `android` | the APKs in Docker (`android/build.sh`, `ci/Dockerfile.android`); the release APK is signed with the key from the repository secrets |
| `release` | push to `main`: replaces the `latest` release; binaries, `vtund-<VTun version>-x86_64`, hook scripts, service scripts, `SHA256SUMS` |
| Job | What it does |
|----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `tests` | `make test`, the same under ASan/UBSan, the `LWIP=0` build |
| `build` (arm32, mipsel, arm64, mips, x86_64) | static musl binaries with `ci/build-musl.sh` (`vtesse`; patched `vtund` in the x86_64 job), unit tests and a `vtund -h` smoke test under qemu-user, artifacts |
| `bench` | the Docker test bench (vtund built with our patches): `selftest`, `cli-test`, `proxy-test`, `tap-test`, `tun-test`, `udp-test`, `fault-test` |
| `android` | the APKs in Docker (`android/build.sh`, `ci/Dockerfile.android`); the release APK is signed with the key from the repository secrets |
| `release` | push to `main`: replaces the `latest` release; binaries, `vtund-<VTun version>-x86_64`, hook scripts, service scripts, `SHA256SUMS` |

### Versions and releases

The version lives in one place, `include/vtesse/version.h`:
`#define VTESSE_VERSION "MAJOR.MINOR.PATCH"` (shown by `vtesse-cli --version`). Up to 1.12
it was `MAJOR.MM` (`1.00`, `1.01`, …); 1.12 is followed by 1.12.1 or 1.13.0.
it was `MAJOR.MM` (`1.00`, `1.01`, …); 1.12 is followed by 1.13.0. The Android `versionCode`
is `MAJOR*10000 + MINOR*100 + PATCH` (1.13.0 → 11300), larger than the old `MAJOR*100+MM`
(1.12 → 112), so an update installs over the app.

- There is one release, `latest`: every push to `main` replaces it (tag moved to that
commit). No versioned releases are kept.
- Its title is `VTesse <version>`; the notes are one short line. The change history is
[CHANGELOG.md](../CHANGELOG.md), the patch list [server/README.md](../server/README.md).
- File names are stable: `vtesse-<arch>`, `vtesse-tap-<arch>`, and
- File names are stable: `vtesse-<arch>` (one binary per platform, lwIP and TAP), and
`vtund-<VTun version>-x86_64` (e.g. `vtund-3.0.2-x86_64`) for the VTun server, PCs only.
- PATCH for fixes and small changes, MINOR for a new feature, MAJOR for an incompatible
change or a large update, only when the maintainer decides. A pull request that changes
Expand Down
6 changes: 3 additions & 3 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ Optional modules (#29), `vtesse-cli --version` lists what a binary contains:
| `TAP=0` | TAP/TUN backend (kernel interface) | ~5 KB |

A disabled feature is refused with a clear message (`--socks: built without SOCKS5`).
Release binaries contain everything; `vtesse-tap-<arch>` is the `LWIP=0` build.
Release binaries contain everything, one per platform; the `LWIP=0` build is not published
(build it with `make LWIP=0` when the flash is tight).

Each target gives `vtesse-<target>` (lwIP + TAP) and `vtesse-tap-<target>` (TAP
only); x86_64 also `vtund-3.0.2-x86_64`, the VTun server with our patches
Each target gives `vtesse-<target>` (lwIP and TAP backends, `--tap`); x86_64 also `vtund-3.0.2-x86_64`, the VTun server with our patches
([server/README.md](../server/README.md)). Use musl builds on devices: a static glibc binary cannot resolve host names
without the NSS libraries of the same glibc. Prebuilt binaries are on the
[releases page](https://github.com/OpenIPC/vtesse/releases) (`latest` is rebuilt
Expand Down
6 changes: 3 additions & 3 deletions include/vtesse/version.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#ifndef VTESSE_VERSION_H
#define VTESSE_VERSION_H

/* MAJOR.MM. Shown by --version and in the title of the "latest" release (CI);
* record each bump in CHANGELOG.md. */
#define VTESSE_VERSION "1.12"
/* MAJOR.MINOR.PATCH (up to 1.12 it was MAJOR.MM). Shown by --version and in the
* title of the "latest" release (CI); record each bump in CHANGELOG.md. */
#define VTESSE_VERSION "1.13.0"

#endif
Loading