Skip to content

Releases: jialiangZ/hkuvpn

hkuvpn v1.2.1

Choose a tag to compare

@github-actions github-actions released this 05 Nov 09:28

hkuvpn v1.2.1 — the field fixes

This release is what v1.2.0 should have been. Every item below was found
by running the client against the live HKU gateway for a whole day, and
every one of them made the client behave in a way that was hard to
diagnose. If you downloaded v1.2.0, take this one instead — the
release workflow that builds the archive did not exist yet when v1.2.0 was
tagged, so that archive carries the unfixed worker.

The fixes

  • The system no longer crawls. The routing script registered the
    gateway's DNS servers on the tunnel adapter even though HKU pushes no
    split routes, so those resolvers were unreachable and the Windows DNS
    client waited on them for every name — opening a folder included. A
    resolver is now registered only when a route actually reaches it.

  • Big transfers do not stall. OpenConnect sizes the tunnel adapter
    from the TCP channel's MTU (1271), which is larger than what the UDP
    channel carries (1246): packets in between were dropped, so a shell
    answered while a file transfer hung forever. The worker now caps the
    adapter at the DTLS MTU, read from the session log.

  • A connect does not hang at "Connecting". The worker was losing a
    quarter of what the tunnel processes printed — the "Password:" and
    "Response:" prompts included — so the code dialog sometimes never
    appeared. The read now copies the bytes out before the next one is
    armed.

  • The window stops claiming a session that is not there. A worker
    waiting for the MFA code beats its heart, so the app used to call that
    "connected", close the dialog and leave the session waiting forever.
    Only a session that reported its tunnel up counts as connected now, and
    a worker found waiting for a code is adopted with the dialog back.

  • The UAC prompt can take as long as it takes. The connect attempt
    gave up after 20 seconds — but that clock started when you pressed
    Connect, and the UAC prompt in front of you may sit there longer. The
    clock now starts when the worker actually appears, and a worker that
    turns up while the app is idle is adopted rather than orphaned.

  • TCP by default. HKU_DTLS shipped with DTLS/UDP on and TCP as the
    escape hatch, which is backwards for most users: cross-border links
    throttle UDP into heavy loss (41 percent on the link this was measured
    on), which stalls the session in confusing ways, while TCP only costs
    latency. Both editions now carry their data over TCP unless you ask for
    DTLS with HKU_DTLS=1 — worth it where the path is clean, inside Hong
    Kong for instance, where it cuts round-trips to about a quarter.

  • Every setting says what it does when the pointer rests on it.

The Windows app

Same download as before: HKUVPN-windows-v1.2.1.zip — the app, the
worker it drives, the routing script and a START-HERE.md (also in
Chinese). Unpack it, run bin\get-tools.ps1 once as administrator, start
HKUVPN.exe.

Upgrade notes

Nothing to do. The Docker edition works exactly as before, and the
Windows launcher gained nothing either — the desktop app is a separate
thing that drives the same worker underneath it.

If you configured HKU_DTLS=0 by hand, it still means the same thing.
If you had no HKU_DTLS line at all, you now get TCP instead of DTLS.

hkuvpn v1.2.0 - the desktop app

Choose a tag to compare

@jialiangZ jialiangZ released this 04 Nov 09:03

hkuvpn v1.2.0 — the desktop app

This release is about making hkuvpn usable on a laptop without a
compiler, a container runtime or a terminal window.

The Windows app (new)

HKUVPN-windows-v1.2.0.zip — 5 MB, no installer.

Unpack it anywhere, run bin\get-tools.ps1 once as administrator (it
installs OpenConnect, which brings the Wintun adapter, and downloads
gost; both downloads are checked against pinned SHA-256 hashes), then
start HKUVPN.exe. Type your HKU account and Portal PIN in the window —
they are saved as you type and never leave the machine — press
Connect, approve the UAC prompt, and type the six-digit code from
Microsoft Authenticator when it asks.

START-HERE.md and START-HERE.zh-CN.md in the archive have the full
steps, in English and in Chinese.

What the window gives you that the launcher does not:

  • a status card — the state, the tunnel address, the uptime, the proxy
    endpoints and the learned routes, in one place
  • a Diagnostics panel — the same checks as hkuvpn.ps1 --check, plus a
    live test of the local proxies and the address the traffic leaves with
  • a Routes panel — the learned routes, added and removed by hand
  • a Settings panel — the advanced options of hku.env, and a switch
    to start the app with Windows
  • a log window — the session log with severity tags, a level filter, a
    search field, and copy / export

Closing the window hides the app in the tray and the tunnel keeps
running. Disconnect needs no UAC, and exiting the app never kills a
session.

中文

HKUVPN-windows-v1.2.0.zip 里有桌面 App:解压后以管理员身份运行一次
bin\get-tools.ps1(装 OpenConnect、下载 gost,都有固定的 SHA-256 校验),
再启动 HKUVPN.exe,在窗口里填账号和 Portal PIN,点 Connect,UAC 点允许,
要码时输入 Authenticator 上的 6 位数字。压缩包里的 START-HERE.zh-CN.md
有完整步骤。

窗口里比启动器多出来的东西:状态卡(状态、隧道地址、时长、代理、
学到的路由)、诊断面板(和 --check 相同的检查,外加本地代理的连通性
测试和出口地址)、路由面板(可手动增删)、设置面板(hku.env 的高级
选项和开机自启)、日志窗口(级别标签、级别筛选、搜索、复制、导出)。

Also in this release

  • The logs have a policy now. One file per connection attempt, three
    generations kept, and a session that runs long can no longer fill the
    disk.
  • The app's own log moved to %LOCALAPPDATA%\HKUVPN\app.log — a
    place Windows does not clear behind your back. It is rolled daily and a
    week is kept.
  • Deleting an autostart entry that is not there is no longer an
    error
    , and the "Start with Windows" switch shows what the registry
    actually says rather than what the app remembers.
  • The MFA dialog became a gate: the code leads on, and closing the
    dialog gives the attempt up — there is no "enter the code later".
  • The panels got windows of their own, the window has one fixed size, and
    no page has a scrollbar.
  • The documentation was brought back in line with the software. The
    design brief describes what the app is now, the READMEs describe the
    log policy and the UAC behaviour that are actually true, and the
    website's links point where they say they do.

Upgrade notes

Nothing to do. The Docker edition works exactly as before, and the
Windows launcher gained nothing — the desktop app is a new, separate
thing that drives the same worker underneath it.

A note on the archive

The .sha256 file next to the archive is the hash of the archive. If it
does not match, do not run it — write an issue instead.

v1.1.4

Choose a tag to compare

@jialiangZ jialiangZ released this 01 Nov 17:44

hkuvpn v1.1.4 - migration guide and docs aligned with field results

Upgrading from v1.0.x

The Docker edition moved into docker/ in v1.1.0, and the shell wrappers
into examples/shells/. An existing shell profile silently broke: it
still sourced examples/hkuvpn.zsh, which no longer exists there.

Was Now
docker build -t local/vpn . docker build -t local/vpn docker/
~/hkuvpn/bin/hkuvpn ~/hkuvpn/docker/bin/hkuvpn
~/hkuvpn/examples/hku.env.example ~/hkuvpn/docker/examples/hku.env.example
source ~/hkuvpn/examples/hkuvpn.zsh source ~/hkuvpn/examples/shells/hkuvpn.zsh
cp ~/hkuvpn/examples/hkuvpn.fish ... cp ~/hkuvpn/examples/shells/hkuvpn.fish ...

Re-run the printf line from
Install the Short hkuvpn Command
once to fix the path in your profile. ~/.vpn/ keeps your credentials, and
HKUVPN_HOME still points at the repository root.

Docs corrected against the field results

  • The native Windows port is no longer described as experimental: a full
    session ran against a real HKU account on Windows 11 with PowerShell 5.1
    (connect, routing, licensed-resource routing, clean shutdown).
  • Its routing model is now described as on-demand routing - HKU's
    gateway pushes no split routes - instead of speaking of campus subnets
    and of a model differing only "slightly" from the container edition.
  • The known-differences tables state what actually goes through HKU, that
    licensed resources are learned even when the first attempt fails, and
    that the NRPT rule is skipped on purpose when the gateway's resolvers
    are not reachable through the tunnel.
  • The MFA sections explain that an Authenticator code is valid for about
    30 seconds and that a rejected one is simply re-prompted.
  • The compatibility tables list the versions the native port pins
    (OpenConnect 9.21, gost 3.3.0).

No code changes in this release.

v1.1.3

Choose a tag to compare

@jialiangZ jialiangZ released this 01 Nov 10:29

hkuvpn v1.1.3 - the native Windows port, working end to end

The Windows port was driven through a complete session against the live
HKU gateway. That found five more problems, all fixed here. After this
release the port establishes a tunnel, installs routes, keeps the host's
default route untouched, and learns routes for licensed resources.

Fixed

  • The worker stalled right after starting OpenConnect. Read-AvailableChars
    drained a child's stream with while ($Reader.Peek() -ge 0), and on a
    redirected pipe Peek() blocks again as soon as the buffered data is
    consumed - so the call never returned. The worker never got to read
    stderr, where OpenConnect prints its prompts, so the Portal PIN was
    never sent. All four streams are now polled with ReadAsync.
  • The IPv4 mask arithmetic threw. PowerShell parses 0xFFFFFFFF as
    [int]-1, and casting a negative value to [uint32] throws.
    Get-PrefixMaskDotted and Get-NetPrefixBase threw for every prefix
    below /32 (the first learned destination killed the session), and
    Test-IpInPrefix swallowed the exception and always answered false (the
    NRPT rule was never installed). All three use 64-bit arithmetic now.
  • gost died silently when it could not bind 1080/1088. The worker now
    checks gost right after starting it and on every iteration.
  • A rejected MFA code was invisible. A stale Authenticator code comes
    back as a second form, which looked like a first prompt. The worker now
    reports the rejection (HKUVPN_MFA_RETRY) and tells the user to enter
    the current code; the log is flushed while waiting, so --logs is
    current.
  • Prompts were matched anywhere in the output. OpenConnect writes its
    prompts without a trailing newline, so a real prompt ends the buffer.
    The old search also matched the log line ... Enter Your Microsoft verification code Response: and asked for another code after the
    tunnel was already up.

Learned routes now cover failed connections

gost runs in debug mode, which logs dial <target>/tcp before the
connection is attempted - the only place a destination appears when the
connection never completes. That is exactly the case of a resource that
is only reachable through the campus exit; without it such a resource
could never work. Host names are resolved by the launcher itself (cached
per session).

What HKU's gateway actually does

Documented after measuring it: it is a full-tunnel gateway that pushes
no split routes
(connect done: 0 v4 route(s) is normal) and it only
carries public destinations through the tunnel. The native port therefore
routes on demand, and the NRPT rule is skipped on purpose when the
gateway's resolvers are not reachable through the tunnel - a rule
pointing at an unreachable resolver would only black-hole the lookups.

Verified on real hardware

Tunnel up (CSTP connected, DTLS, MTU 1255), split routes applied by the
vpnc script, learned routes installed through the tunnel
(140.248.167.0/24, 203.0.113.0/24 - the latter learned from a
connection that never succeeded), the default route still on the physical
adapter, the e2e proxy check green, and the certificate pin byte-identical
to the openssl value.

v1.1.2

Choose a tag to compare

@jialiangZ jialiangZ released this 01 Nov 09:58

hkuvpn v1.1.2 - the native Windows port, fixed after field testing

The Windows port was exercised on a real machine (Windows 11 build 26300,
PowerShell 5.1). That found four bugs that no amount of static checking
would have caught. All are fixed here.

Fixed

  • IPv4 mask arithmetic (Get-PrefixMaskDotted, Get-NetPrefixBase,
    Test-IpInPrefix)
    - PowerShell parses 0xFFFFFFFF as [int]-1, and
    casting a negative value to [uint32] throws. The first two threw for
    every prefix below /32, so the first external destination reaching the
    auto-route learner raised inside the tunnel worker and killed the
    session. Test-IpInPrefix swallowed the same exception and always
    answered false, so the NRPT rule for campus-only DNS was never
    installed. All three now use 64-bit arithmetic.
  • Tools directory - get-tools.ps1 created <repo>\tools while
    hkuvpn.ps1 looked in <repo>\windows\tools, so gost was installed
    where the launcher never checked. Both agree now, and the launcher also
    accepts the old location.
  • OpenConnect installer - the URL pointed at the moving GitLab CI
    master artifacts, which expire after a week (it 404s now). The script
    now downloads the official v9.21 tag build, whose artifacts never
    expire, and verifies it against a pinned SHA-256 - the same version the
    Docker image builds.
  • Pre-flight session check - Get-Process -Id 0 returns the Windows
    System Idle process, and a missing pid file reads as 0, so the pre-flight
    always claimed a session was running and skipped the port check.

Also

  • The Windows scripts are pure ASCII now: PowerShell 5.1 and cscript.exe
    read BOM-less files as ANSI and would mangle non-ASCII characters.
  • .gitattributes normalises line endings (CRLF for the scripts Windows
    executes, LF for everything else).
  • windows/tools/ is git-ignored (downloaded binaries).
  • A field validation checklist
    (English / 简体中文) walks through every step with the expected output.

Verified on real hardware

Tool installation with pinned hashes, the certificate pin (byte-identical
to the openssl value), the gost proxy with both listeners, the auto-route
learner against real connection logs, the vpnc script (including its
refusal of a /0 route), the NRPT rule, and route add/delete.

v1.1.1

Choose a tag to compare

@jialiangZ jialiangZ released this 01 Nov 09:33

hkuvpn v1.1.1 — MIT License

The project is now released under the MIT License.

  • LICENSE — the canonical MIT text, so GitHub detects the license correctly
  • NOTICE — upstream attribution and third-party notices:
    • derived from ethack/docker-vpn
      via the HKU edition by
      rqhu1995/docker-vpn (both
      published without an explicit license)
    • docker/etc/vpnc-script is vendored verbatim from openconnect/vpnc-scripts
      and stays under GPL-2.0, as its header states
    • OpenConnect, gost, and the other packaged dependencies keep their own
      licenses
    • the HKU VPN server is operated by the University of Hong Kong; this is an
      unofficial client
  • a license badge and updated footers in both READMEs, both guides, and the
    project site

v1.1.0

Choose a tag to compare

@jialiangZ jialiangZ released this 01 Nov 09:31

hkuvpn v1.1.0 — repository reorganized

The repository now has two self-contained editions with the same shape,
instead of the Docker edition being scattered across the repository root.

hkuvpn/
├── docker/                    # Docker edition (Linux / macOS / Windows-WSL)
│   ├── Dockerfile
│   ├── bin/hkuvpn
│   ├── etc/vpnc-script
│   ├── examples/hku.env.example
│   ├── hku-connect.exp
│   └── keys/openconnect-release-key.asc
├── windows/                   # Native Windows edition (no WSL, no Docker)
│   ├── bin/hkuvpn.ps1
│   ├── bin/get-tools.ps1
│   ├── etc/vpnc-script-win.js
│   └── examples/hku.env.example
├── examples/                  # Shared integration examples
│   ├── clients/               # Clash Verge Rev, Surge, SSH config
│   └── shells/                # Zsh / Bash / Fish / PowerShell wrappers
└── docs/                      # Guides and diagrams

Migration (command paths changed)

Before Now
docker build -t local/vpn . docker build -t local/vpn docker/
~/hkuvpn/bin/hkuvpn ~/hkuvpn/docker/bin/hkuvpn
~/hkuvpn/examples/hku.env.example ~/hkuvpn/docker/examples/hku.env.example
~/hkuvpn/examples/hkuvpn.zsh ~/hkuvpn/examples/shells/hkuvpn.zsh

Existing clones keep working: the launcher and the shell wrappers fall back
to the old layout when it is detected, and HKUVPN_HOME (legacy name
DOCKER_VPN_HOME) still points at the repository root. When the variable is
unset, the launcher now derives the root from its own location instead of
assuming ~/hkuvpn.

Also in this release

  • Readme.md renamed to README.md (consistent casing)
  • poc/ removed — prototype leftovers referencing a non-existent image and
    hard-coding a personal account
  • Repository layout documented in both READMEs and both guides

v1.0.0

Choose a tag to compare

@jialiangZ jialiangZ released this 01 Nov 09:12

hkuvpn v1.0.0

HKU campus VPN client: OpenConnect + Microsoft Authenticator MFA behind local
SOCKS5/HTTP proxies, while the host default route stays untouched.

Docker edition (Linux / macOS / Windows via WSL2)

  • OpenConnect 9.21 built from verified source; MFA form automation via expect
  • gost proxy (SOCKS5 1080 / HTTP 1088), DoH-pinned control endpoints,
    certificate pin cache, layered --status with scriptable exit codes
  • Rules-client examples for Clash Verge Rev / Mihomo and Surge

Native Windows port (experimental) - windows/

  • Official OpenConnect Windows CLI (Wintun) + gost: no WSL, no Docker
  • PowerShell launcher: smart / foreground / detached, interactive or
    --mfa <code> delivery, self-elevation, layered --status
  • vpnc-script-win.js: split-tunnel-only routing that never touches the host
    default route, plus an NRPT rule for campus-only DNS
  • Auto-learned routes for HKU-licensed external resources (learned from the
    proxy connection log, persisted across sessions with TTL and a cap)

Credits

Derived from ethack/docker-vpn via the
HKU edition by rqhu1995/docker-vpn.