mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-10-11 05:26:14 -08:00
eb32d2a930f1cdd09ff8627fa134673861ffb73c
28
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
728ba94b50 | Link easytier-mini downloads and fix UDP admission test ordering (#2638) | ||
|
|
d3a5ae684a |
fix(peers): keep TCP hole-punched connections alive with 1s pings (#2632)
Disable ping interval backoff for TCP hole-punched connections so idle connections continue to send keepalive traffic every second. Preserve the existing backoff and loss handling for other connections. Keep randomized backoff above zero and cover the one-second schedule and the existing backoff and loss retry behavior with tests. * refactor(peers): model connection origins at admission Record manual, direct, listener, TCP/UDP hole-punch, and attached origins when constructing peer connections. Derive hole-punch state from this origin instead of maintaining separate mutable flags. Choose the one-second TCP hole-punch ping limit in PeerConn and pass only a maximum interval to the pinger. Keep other origins on the existing backoff schedule without inspecting tunnel type strings. Keep origin selection internal and preserve the dedicated attached admission paths. Update public admission callers and cover origin propagation, relay restrictions, and ping interval limits. |
||
|
|
651a8d9e25 |
feat(web): add central network management console (#2622)
Persist central network intent and compile complete per-device configs with secure credentials, ACL policy, and dedicated Gateway runtimes. Expose network, credential, device registry, and runtime observation APIs. Treat central management and external Console as alternative consumers of the upstream ClientManager. Register central devices through a local webhook handler and publish through existing runtime reconciliation. Serialize public mutations with enrollment, reject direct credential changes to managed instances, and retain REST revision invalidation. Keep Gateway lifecycle publication in the central service and remove obsolete incremental result bookkeeping. Restore persisted networks and retire orphan runtimes through the same serialized publisher. Add Core and protocol support for Gateway and WireGuard management, including GUI bindings and serialized GUI config writes. Bootstrap IPv4 for DHCP-only networks and retain assigned addresses without peer IPv4. Cover intent transactions, complete configuration publication, offline recovery, authentication, revocation, Gateway lifecycle, and DHCP. Validate central candidates before persistence using Core URL, config, and portal-client rules. Reject unsupported peer schemes, unconvertible proxy subnets, and invalid portal clients without changing live intent. Expose existing pure Core validators without changing runtime behavior. Gate API-facing credential validation on API-enabled Core builds so minimal WASM targets do not reference omitted management types. Preserve session-backed device views in external Console mode. Bound Gateway admissions without cancelling transport upgrades, and cancel pending peer handshakes before retiring runtimes. Batch registry reads and bound runtime observation concurrency. Randomize DHCP bootstrap and conflict retries, keep an advertised current subnet, and select fallback subnets deterministically. Cover concurrent startup, Gateway admission lifetime, and external Console regressions. Allow DHCP bootstrap with no remote routes. Count network members through one tenant-scoped query without write transactions. Cover zero- peer allocation and tenant/empty-network counts. Preserve direct Web configurations and disabled states in central device snapshots. Remove obsolete central rows atomically with membership changes. Stop online managed instances before deleting or blocking devices, retaining intent when shutdown or deletion fails. Persist automatic IPv4 allocations separately from manual overrides so subnet changes reallocate only automatic members. Normalize mapped proxy routes to their advertised CIDRs when granting temporary credentials. Cover publication, deletion rollback, subnet migration, and grant updates. Read central intent in deferred transactions so polling does not reserve the SQLite writer lock. Test reads with an active writer and assert the temporary-member secret constraint using a valid device fixture. Persist patched WireGuard clients from the saved Web or GUI candidate without a follow-up RPC. Preserve pending settings and ownership, and cover disconnects and failed patches. Resolve named credential and config mutations against the live Core instance before checking central ownership. Forward authorized mutations by UUID on the same session, including while network renames are pending. Cover all mutation methods and preserve direct Console behavior. * feat(web-ui): add central network console and WireGuard management Add network and device views with central membership, credentials, ACL policy, temporary peers, and per-instance runtime details. Update console navigation, styling, theme handling, and API clients. Extend shared configuration and status components for central networks. Add a WireGuard portal dialog for setup and running-device management, with matching translations and network configuration types. Use secure UUID generation on HTTP, discard stale member configuration responses, and stop node-detail polling when the component unmounts. Update frontend workspace dependencies and include component, dashboard, configuration serialization, and central console end-to-end tests. Add isolated real-Core E2E coverage for central data-plane traffic, ACL, DHCP, recovery, device lifecycle, and native WireGuard clients. Record all 59 functional checks with evidence and confirmed validation/UI defects; keep runtime artifacts and test credentials out of Git. Normalize protobuf logger levels and render translated labels correctly. Cover all six levels across setting, reload, and language changes. Add real configuration-rejection E2E checks for database and Core stability and uninterrupted traffic, and record the resolved audit findings. Gate central navigation and registry actions by console mode. Refresh WireGuard settings on mounted status views and preserve explicit portal listener endpoints. Explain the trusted permanent-member ACL boundary. Cover external Console rendering, portal refresh retries and teardown, and explicit IPv4/IPv6 listener exports. Preserve PublicServer discovery when saving its settings, including when its URL matches the Gateway. Cover renaming and endpoint edits in the browser. Display automatic member addresses without converting them to manual overrides during edits. Derive offline address prefixes from the network subnet. Add browser regression coverage and real-Core checks for direct configuration preservation, temporary proxy mappings, automatic subnet migration, and shutdown before device deletion. Build enrollment commands from the configured API hostname, including IPv6 and relative endpoints. Use the PublicServer connector in temporary credential CLI and TOML exports. Add browser regression coverage. Preserve form credentials across repeated normalization and GUI storage reloads. Keep explicit form values authoritative over backend keys and cover JSON persistence, idempotence, replacement, and clearing. |
||
|
|
7223677264 |
cargo: upgrade (#2116)
update dependencies |
||
|
|
5477d4bca2 |
fix(proxy): isolate TCP flows and recover KCP control loss (#2569)
* fix(proxy): distinguish TCP flows sharing source ports Key TCP NAT entries by source and destination so connections sharing a source port can reach different targets independently. Allocate a unique translated source port for each flow and restore the original addresses and ports on the return path. Keep connection identity during accept and cleanup so a replaced flow cannot lose its new mapping. Give each smoltcp proxy mode its own listener port and retain the original destination for mapped subnets. Include regression coverage for SYN retries, concurrent insertion, stale cleanup, translated port wraparound and exhaustion, plus the recorded cross-platform and six-mode traffic validation. * fix(proxy): preserve half-closed streams and pending KCP accepts Propagate EOF to the opposite writer while keeping reverse traffic alive until both directions finish. This allows a server to reply after reading request EOF and a client to send after reading response EOF. Pin kcp-sys to b37ee660 for retained pending accepts, receive-buffer draining before EOF, early FIN handling, atomic state cleanup, and keepalives that start only after the handshake completes. Cover both shutdown directions, empty requests and buffered transfers in gateway tests and the TCP/KCP/QUIC kernel/smoltcp integration matrix. Include the half-close validation record and its remaining loss limits. * fix(proxy): enable backward-compatible KCP control recovery Pin kcp-sys to 26853356 and update both the root and OHOS workspace lockfiles. The dependency negotiates reliable control per connection while preserving legacy behavior when either endpoint lacks support. New peers recover lost handshake and FIN control packets, acknowledge FIN without closing the reverse writer, and retain bounded close state for duplicate packets. Queue saturation cannot block reliable stateless responses. Compatibility tests retain one historical baseline. Include the protocol design and validation records for deterministic loss, real old endpoints, three platforms, the full integration matrix, and proxy traffic. Preserve mixed-version failures and the documented minor scheduling issue rather than claiming legacy loss recovery. Validate the OHOS workspace with --locked: 12 library tests and the binding test build check pass, along with formatting. |
||
|
|
286e0f4a0d |
fix(proxy): do not wrap TCP packets destined to own virtual IP (#2572)
The wrapped TCP proxy (KCP/QUIC) claims every SYN emitted by the local host,
including packets addressed to the node's own virtual IP. Those packets were
marked for the wrapped path and self-delivered, then the wrapped destination
lookup failed ("no peer found for wrapped TCP dst"). This broke local access
to the node's own virtual IP on systems that route own-address traffic through
the tun (macOS), and, with the proxy enabled on both sides, also inbound
wrapped flows to a macOS node, because the receiving side dials its own
virtual IP locally.
Skip the wrapped path when the SYN destination equals the local virtual IPv4.
Feed the NIC filter context the instance virtual IPv4 (snapshot.virtual_ipv4)
instead of the smoltcp fake inet so the check works with smoltcp enabled too;
the net-to-net guard is unaffected because it only runs when smoltcp is off,
where both values are identical.
Add a regression test for the KCP and QUIC transports.
|
||
|
|
a7383114d0 |
fix(core): do not allocate DHCP IP without an assigned peer IPv4 (#2551)
Fixes the DHCP allocator treating its hard-coded fallback subnet as an interface lease when no peer IPv4 has been observed. With DHCP enabled and no devices carrying a virtual IPv4, the allocator now waits instead of pulling 10.126.126.0/24 onto the TUN interface. Behavior preserved when an explicit allocator subnet is supplied or when peers with assigned IPv4 exist. --------- Co-authored-by: 225284228a-droid <225284228a-droid@users.noreply.github.com> Co-authored-by: Codex <codex@users.noreply.github.com> |
||
|
|
38e2a621bb |
refactor(ohos): 拆分 OHRS 包并按 socket 精细保护 VPN 流量 (#2543)
* refactor(ohos): split facade feature and kernel crates * feat(ohos): protect transport sockets individually * fix(ohos): keep local proxy subnets off tun * fix(ohos): expose valid config enum values * refactor(ohos): finalize reusable core boundary * test(ohos): verify split package contracts * fix(port-forward): support wildcard userspace listeners Keep the existing Host listener intact while adding a DataPlane listener for force-smoltcp IPv4 wildcard rules. Keep literal loopback destinations on the local Host path instead of exporting them through an exit node. * chore(ohos): refresh split workspace lockfile * fix(socket): normalize Windows raw socket handles * refactor(socket): carry VPN protection through host bind options * refactor(socket): simplify protection defaults and TUN ingress * refactor(socket): consolidate native protection and socket creation * fix(socket): protect outbound UDP paths * fix(socket): preserve VPN routing for RPC listeners --------- Co-authored-by: FrankHan <frankhan@FrankHans-Mac-mini.local> Co-authored-by: KKRainbow <443152178@qq.com> |
||
|
|
f26c2aa147 |
feat(wasi): run EasyTier core on Cloudflare Workers and browsers (#2548)
* fix(core): normalize secure keys for TOML instances
* feat(wasi): run core behind Cloudflare WebSockets
Introduce the Cloudflare Worker WASI host that runs the EasyTier core
behind host-upgraded WebSockets.
- Worker package scaffold (wrangler Durable Object, build-wasm script,
vitest config) and core-runtime/websocket-host/data-plane runtime.
- WASI host WebSocket tunnel ABI (imports, adapter, runtime exports)
with bounded receive memory and bounded admission queue.
- Route host sockets through the portable listener plan
(HostListenerRegistration, listener queue, admission handler split).
- Build the WASM guest with the aes-gcm feature so secure peer
sessions have their cipher available.
* feat(wasi): add outbound browser client runtime
Add the outbound-only WASI runtime and browser connector host so
browser pages can dial EasyTier peers through WebSocket relays.
- CoreConnectivityMode::{OutboundOnly, InboundOnly} gating for
listeners, discovery, and direct connectivity modules.
- ExternalTunnelConnector plumbing through composite/connector_host/
manual for browser WebSocket dials.
- Browser/Node smoke entries with shared helpers
(smoke-shared.ts).
* feat(wasi): extend browser data plane with TCP half-close
Add the data-plane pieces the browser runtime needs for full-duplex
TCP streams behind host WebSockets:
- Guest TCP shutdown_write operation with submit/take ABI pair
(DATA_PLANE_ABI_VERSION 3 -> 4) and smoltcp half-close support.
- Worker data-plane TCP listener/stream plumbing and core-runtime
listener registration.
- Unit coverage for the new session ops and listener wiring.
* refactor(wasi): make host tunnel ABI transport-neutral
Replace WebSocket-specific core and WASI boundaries with a
message-oriented Host Tunnel interface. Keep WebSocket framing and text
rejection in the Cloudflare host while preserving payload boundaries,
ownership, cancellation, backpressure, and EOF behavior.
Rename feature flags and guest imports and exports to the Host Tunnel
ABI. Update both Worker profiles, tests, and architecture documentation.
* feat(web): split WASI hosts into publishable npm packages
Extract the shared JSPI, WASI, Host Tunnel, and data-plane runtime
into @easytier/runtime. Keep ABI handles, guest memory, TOML, and
operation broker details behind its adapter entry point.
Add typed, auto-starting @easytier/browser and factory-based
@easytier/cloudflare packages. Ship a matching Wasm profile with
each platform package and validate its capabilities before packing.
Persist Cloudflare instance identity in Durable Object storage,
centralize WebSocket admission ownership, and add package-level
coverage for the public interfaces.
* fix(web): make public packages portable
Embed the browser Wasm artifact in the published JavaScript entry
point. This lets esbuild consumers bundle the package without an asset
loader or a copied file.
Return Cloudflare's nominal Durable Object base type and document the
named subclass export required by generated Wrangler bindings.
* docs(web): add public package walkthrough
Expand both package READMEs with installation, configuration, local
validation, health checks, and deployment instructions.
Add a standalone Vite and Wrangler example that imports only the
public Browser and Cloudflare entries. Generate Worker bindings from
configuration and keep local secrets outside version control.
* chore(go): import EasyTier Go host
Add the standalone Go host runtime as a monorepo subtree without
carrying its development branch ancestry.
Preserve its API, tests, examples, generated protobuf bindings, and
embedded WASI artifacts.
* refactor(hosts): colocate Go and JavaScript runtimes
Move the browser, Cloudflare, shared runtime, and web example into
the easytier-js subtree. Update workspace metadata, build paths, and
documentation for the new layout.
Adopt github.com/EasyTier/EasyTier/easytier-go as the Go module path.
Resolve artifact and protobuf generation from the enclosing monorepo.
* build(web): isolate JavaScript host workspace
Keep public browser and Cloudflare packages outside the legacy frontend
workspace so root installs and cross-platform builds do not pull workerd.
Make each package build generate its required WASI artifact from a clean
checkout. Add a dedicated workflow that runs the same install and check
commands documented for contributors.
Move JavaScript dependencies into a scoped lockfile and restore the root
workspace lockfile to its pre-host state.
|
||
|
|
164e2db6ae |
feat(core): expose WireGuard client traffic metrics (#2537)
* feat(core): expose WireGuard client traffic metrics Count successfully accepted upload and delivered download packets per VPN portal client. Keep counters stable across session reconnects and export them through the existing Prometheus statistics endpoint. If a client is removed by a concurrent config update while one of its sessions is still starting, drop that session instead of panicking: the release profile aborts the whole process on panic. * ci(core): pin cargo-zigbuild to 0.23.2 cargo-zigbuild 0.23.3 (released today) passes -mcpu=generic+v6+strict_align to zig cc when building jemalloc for arm-unknown-linux-musleabi; zig 0.16.0 rejects that mcpu value, so the linux-arm job fails and fail-fast cancels the rest of the build matrix. Pin the tool to the last working version until zig is bumped. |
||
|
|
25f6e2dc5e | feat: stabilize mobile runtime and VPN portal (#2536) | ||
|
|
4a10d1c2b9 |
feat(mobile): add embedded runtime and managed network updates (#2532)
* feat(mobile): add embedded iOS runtime API Add a thin panic-safe C ABI crate for embedding no-TUN instances on iOS. Expose lifecycle, status, JSON-RPC, string ownership, and error handling. Build device and simulator XCFramework static libraries on macOS. Add exact named-instance deletion to the iOS and Android wrappers. Cover wrapper lifecycle and the port-forward patch flow on host targets. * fix(gateway): recover TCP port-forward listeners Release an unusable TCP port-forward listener after an accept failure. Retry binding until the forward is cancelled. Keep the old listener released while rebinding so mobile sockets can recover. Expose opt-in iOS diagnostics for listener and connection events. Trace configuration removal and adapter shutdown. Add tests for recovery, release-before-rebind, and cancellation. * feat(web): persist incremental managed config patches Add a revision-CAS PATCH contract for managed configs while keeping the existing Full PUT path for compatibility and recovery. Apply Full and Patch mutations with their revision in one SQLite transaction. Reject ownership conflicts and invalidate revisions on alternate web-owned writes. Document limits, failure semantics, rollout order, and verification. Cover delta updates, conflicts, idempotency, and transaction rollback. * feat(web): apply managed config patches to live sessions Carry Patch fences and touched instance IDs into live sessions. Reconcile only those instances when the applied revision matches the Patch base. Fall back to Full reconciliation for gaps and restarts. Invalidate the applied revision around every direct runtime mutation. Fence revision advancement with the runtime cache epoch so stale reconcile rounds cannot overwrite a newer invalidation. Require deletion responses to confirm each requested instance before advancing the revision. Raise the managed PUT and PATCH body limit to 32 MiB and return typed conflicts for publisher recovery. * fix(core): retry transient accepted TCP errors Keep TCP tunnel listeners alive when an accepted socket fails during upgrade with a retryable connection-state error. Share the retryable I/O classifier with the socket listener. Cover a rejected connection followed by success and propagation of permanent errors. * feat(core): add internal Peer Relay edge projection Derive the local advertised OSPF row from physical adjacency and transport-authenticated credential relay coverage. Keep full local adjacency only in the temporary SPF snapshot so direct destinations retain a fallback route. Leave Peer Relay disabled at the public configuration seam. A follow-up change can expose the preference without coupling route projection to credential reauthorization. feat(config): expose Peer Relay routing preference Add prefer_peer_relay to public protobuf, TOML, management patch, and hosted runtime surfaces. Read the preference from live peer context so runtime config updates take effect. Refresh authenticated peer metadata when the option is enabled. Cover dynamic enable and disable in a five-node, dual-admin credential topology, including forwarded relay coverage and local fallback. |
||
|
|
4304b065cb |
core: allocate smoltcp listener sockets per SYN (#2519)
A half-open handshake consumed the only smoltcp listener socket, so other clients were rejected until its timeout. Closed listener sockets could also remain unusable after a network interruption. Register logical TCP listeners with the reactor without preallocating socket slots. Allocate one temporary smoltcp socket for each new SYN; repeated SYNs reuse the existing connection. Limit each listener to sixteen pending handshakes or completed connections. Batch ordinary ingress packets through smoltcp and scan listener state once per batch. Before admitting a SYN, advance timers, reclaim stale pending sockets, and flush queued packets. Process only a newly allocated socket's SYN separately to preserve packet order. Keep the global tuple lookup off unmatched and full-listener rejection paths. Promote established connections to the normal timeout, reclaim closed connections, and transfer accepted sockets to streams. Keep one long-lived logical listener in SmolTcpStack and cover concurrency, retransmission, timeout recovery, capacity, and cleanup in tests. |
||
|
|
3fe427bc99 |
feat(credentials): manage declarative credentials through TOML (#2515)
* feat(credentials): manage declarative credentials through TOML Make managed credentials part of the canonical TOML configuration and load them before peers can authenticate. Reuse ConfigRpc hot patches to durably replace the configured credential set without restarting the instance. Serialize credential mutations so base, managed, and ephemeral keys cannot race into conflicts. Remove the managed overlay file format, digest protocol, capability negotiation, force reconciliation, and database CAS machinery. Redact credential secrets from debug output and management events. Write credential-bearing files atomically with private permissions. * fix(core): release JoinSet reapers with their owners Pass weak task-set references into background reapers so they cannot retain the JoinSet they are meant to collect. This lets stale smoltcp bridge tasks terminate when an IPv4 generation is replaced. Add ownership and TCP generation-replacement regressions covering the production port-forward failure. |
||
|
|
8794e12a26 |
feat(vpn): hot add/remove WireGuard portal clients without restart (#2514)
* feat(vpn): hot add/remove WireGuard portal clients without restart WireGuard portal clients were frozen at instance construction: the engine slot maps, host key table, and PortalModule state were all immutable after startup, so any client change required recreating the whole instance and dropping every established session. Wire dynamic client management through the existing config-patch channel (ConfigRpc.patch_config -> apply_config_patch), following the same pattern as connectors, port forwards, and proxy networks: - proto: InstanceConfigPatch gains repeated VpnPortalClientPatch (Add/Remove/Clear by client name) - engine: slot maps move under an RwLock with a free-index allocator; add_client/remove_client recycle indices, mark removed slots retired, and expire active sessions so Core tears down the attached peer via the regular channel-close path (credential revocation and disconnect events included); untouched clients keep their sessions intact. The retired flag is re-checked under the session lock so a datagram that races with removal cannot resurrect a session - host: WireGuardPortalHost derives keys deterministically per name (HKDF), keeps a mutable client table for render_client_config, and forwards updates to the live engine; changed clients are re-added so they re-handshake into a fresh generation with the new virtual IP or groups - PortalModule: client set, statuses, and session locks become shared mutable state; run_session resolves clients from the shared map at accept time; update_clients() validates against a caller-supplied runtime snapshot. An empty client set is legal in every lifecycle stage, so clearing all clients never produces a configuration that fails instance recreation - config_patch: apply_vpn_portal_client_patches mutates the candidate TOML; the sub-patch runs last and is deep-validated and hot-applied before the candidate commits, so a rejected client set leaves neither the shared model nor the live portal changed, and validation sees the fully patched state including routes and node IPv4 from the same request. Rejects patches when no portal is configured or a removed client does not exist - cli: vpn-portal add-client/remove-client/clear-clients subcommands Tests: engine index recycling, module update validation/state/host notification, TOML patch application, and a three-node integration test that adds a second WireGuard client live, removes the first while the second stays online, and asserts rejected patches leave the shared model unchanged. * feat(web): reconcile WireGuard portal client edits as hot patches The web console reconciles desired network config against the running instance and patches it in place when possible. VPN portal changes were not part of that: any client edit made the base configs differ, so every save recreated the instance and dropped all established sessions. Exclude vpn_portal_config from the base comparison and diff its clients by name instead. Client add/remove/change now produces VpnPortalClientPatch entries (removals first, changed clients as remove+add) applied through the existing PatchConfig channel. Listener identity changes (address or private key) and enabling or disabling the portal still fall back to a full instance recreate, since those change the listener lifecycle. * feat(web/gui): map portal client patches to frontend RPC backends Extend the RemoteClient seam with add/remove/clear VPN portal client operations so frontend hosts can drive the same PatchConfig channel as the CLI. There is deliberately no dedicated editing UI: the config form stays the single editing surface (aligned with port forwards), and these methods exist for programmatic and future use. - web console: JSON proxy-rpc to ConfigRpcService.patch_config with VpnPortalClientPatch entries (pbjson string enum actions) - desktop GUI: patch_vpn_portal_clients tauri command forwarding the same patch through the typed ConfigRpc client |
||
|
|
62e4fd15e9 |
feat(vpn): multi-client WireGuard portal with attached peers (#2502)
* feat(peer): support protocol-agnostic attached peers Add locally attached peers backed by independent, peer-level portable managers and authenticated in-process ring connections. Carry trusted connection provenance through packet admission so attached relay privileges cannot be forged through packet headers. Let every peer manager own ACL loading, sanitized policy updates, route refresh, and runtime cleanup. In Secure Mode, grant attached identities ephemeral credentials instead of sharing administrator and group secrets. * feat(vpn): add reusable attached-peer portal runtime Add a protocol-neutral portal runtime that converts authenticated client sessions into attached EasyTier peers. Own per-client generations, status, packet forwarding, address translation, and peer cleanup without knowing the transport protocol. Add transactional IPv4 source and destination rewriting with correct IPv4, TCP, UDP, ICMP, and quoted-packet checksum updates. Keep the old production portal path temporarily active until the WireGuard adapter is migrated in the next change. * feat(wireguard): attach named clients through peer portal Replace the monolithic WireGuard portal with a native adapter that owns key derivation, UDP demultiplexing, reauthentication, roaming, and bounded per-client packet queues. Hand authenticated sessions to the generic portal runtime for peer lifecycle and IPv4 translation. Move portal configuration into the core instance model, require a dedicated server key, and preserve existing listener, CLI, and runtime configuration behavior. Reject runtime address conflicts before publishing shared configuration. * feat(vpn): expose per-client portal status Project configured clients and their runtime state through the portal RPC, including generated client configuration, listener, peer identity, endpoint, tunnel address, ACL groups, and errors. Keep private client configuration out of the broad instance-info response and expose the explicit RPC through the CLI and Tauri bridge. * feat(vpn): add portal configuration to web clients Expose WireGuard portal listener, key, client, ACL group, and runtime status fields in the shared frontend library, Web dashboard, and Tauri client. Preserve UUID and uint64 values across protobuf JSON boundaries, keep dynamic client editor rows stable, and document the portal workflow. * test(vpn): cover multi-client and roaming WireGuard portals Add two three-node integration tests for the WireGuard VPN portal. The multi-client test connects two kernel WireGuard clients from separate network namespaces, verifies per-client connectivity to mesh nodes, and exercises cross-client traffic that runs the IPv4 source and destination translation in both directions. A TCP echo exchange through the portal additionally covers the TCP pseudo-header checksum rewrite path that ICMP-only ping tests miss, and portal status snapshots must report both clients online with distinct peer ids and correctly learned tunnel addresses. The roaming test swaps the client namespace address (delete the old address, then add the new one) so the kernel WireGuard source cache is invalidated and the client keeps sending under the same session from the new source, exactly like a real network change. The portal must update the client endpoint on the same peer id via the data path (same generation, no re-handshake, no detach/reconnect) while connectivity to mesh nodes is preserved. Supporting changes: run_wireguard_client now takes an interface name, and the shared namespace topology gains net_f (10.1.2.5) on the portal bridge for the second client. |
||
|
|
1e40350c89 |
feat(wasi): expose protobuf RPC request ABI (#2477)
* feat(wasi): expose protobuf RPC request ABI Add an instance-scoped asynchronous RPC session backed by the shared operation broker. Reuse the existing dispatcher and management handlers. WASI hosts can call PeerManageRpc and ConnectorManageRpc with the same protobuf payloads as easytier-cli. Export ABI version, submit, take, and free functions. Bind selectors to the WASM instance handle and keep method errors in RpcResponse. Enable management RPC explicitly in the Go-host WASM build. * fix(gateway): serialize UDP client eviction Serialize UDP client admission across forwarding rules so only one eviction can claim and wait for a released semaphore permit. Retry when cleanup concurrently removes the selected client. Add a multithreaded regression test for the permit handoff while the evicted client is still referenced. * fix(gateway): publish UDP client admission atomically Hold the admission guard through client and response-task publication so a concurrent eviction cannot leave an orphan task holding the slot permit. Open the data-plane flow before entering the critical section and extend the multithreaded regression test across the publication window. |
||
|
|
afbba5d928 |
refactor(core): migrate packet processing from pnet to smoltcp (#2456)
Replace pnet_packet parsing and mutation across gateway packet paths with the existing smoltcp wire APIs. Preserve length validation, fragmentation classification, TCP flags, and checksum behavior while removing the core pnet_packet feature dependency. Reject stale non-initiator OSPF sync sessions: only initiator requests may create missing sessions, and a rejection clears the old initiator role only when the remote session generation is unchanged. This fixes an unbounded RPC storm caused by a delayed route sync recreating a session after both peers relinquished the initiator role, with regression tests for session creation and response reordering. |
||
|
|
d55e63b88e |
perf(wasi): optimize data plane and extend host ABI to v3 (#2455)
Overhaul the WASI guest data plane for throughput and add the host capabilities it relies on. The externally driven Tokio runtime now runs its timer pre-turn only when a tracked deadline has expired, and all WASI-reachable timers (STUN, port mapping, WebClient, UDP flow cleanup) go through the portable time facade so conditional timer driving cannot starve them. Data plane: - Move read/write deadlines onto TCP and UDP resources with one ABI setter per direction, reuse a single expiration timer per resource, and drop timeout arguments from the four hot data-plane submissions (ABI v3). Checked absolute instants treat unrepresentable finite timeouts as unbounded instead of panicking. - Batch host traffic: vectored TCP frame writes combine queued slices into one host operation, and reads request a bounded 64 KiB while retaining excess bytes in the stream buffer. - Complete TCP writes inside the guest with cancellation-safe writes, reporting the completed prefix before honoring cancellation or timeout so hosts never replay bytes. - Repoll smoltcp egress immediately on zero poll delay, enlarge virtual UDP receive queues to 128 KiB payload with 128 metadata slots, and bound UDP session receive buffers to 8 KiB plus one byte while keeping oversized-datagram detection. Host integration: - Add optional algorithm-neutral AEAD seal/open imports with the ring backend as fallback, and pin the ring AES-128-GCM wire vector so the Go host stays interoperable. - Forward instance events to hosts through one best-effort, synchronous, non-blocking import. - Add a repository-owned build entry point for the Go host artifact: Binaryen 131 at -O4 with cached, SHA-256-verified official archives. |
||
|
|
7fb42c3b73 |
perf(data-plane): restore native throughput after host portability (#2452)
* perf(core): make data-plane idle check constant time Avoid scanning every DashMap shard for each peer packet when no data-plane flows are active. Publish the flow count before insertion and release it after removal so an Acquire load is a safe O(1) idle signal. Reject count overflow and underflow instead of silently saturating. * test(perf): add repeatable two-node netns benchmark Create isolated underlay namespaces, pin both EasyTier cores and iperf3 endpoints, and measure a single TCP flow in both directions over either UDP or TCP peer transport. Keep every iperf3 JSON result and emit directional medians while cleaning up processes and namespaces on every exit path. * perf(tcp): preserve native owned stream halves Let each VirtualTcpSocket adapter consume itself into independent read and write halves. Portable adapters retain the generic shared split as a default. Use lock-free Tokio owned halves for native TCP and Unix streams so tunnel I/O no longer takes the generic split mutex on every poll. Cover full-duplex traffic and write-half shutdown. * perf(packet): preserve ownership across the Host seam Introduce an opaque, move-only HostPacket that retains core packet storage while exposing only the raw IP payload. Clear private headers before handing storage back to a native TUN adapter. Use an ownership-preserving bounded channel for native ingress and egress. Keep explicit copy adapters for Vec and WASI boundaries, and verify allocation identity, backpressure, shutdown, and end-to-end delivery. * perf(udp): preserve packet ownership through sessions Carry EasyTier tunnel packets through UDP session queues as owned values. Reuse the existing tunnel header for session framing instead of copying payloads into a second packet and rebuilding them on receive. Keep completion delivery for the public datagram socket API while removing the unused completion channel from streaming tunnel sends. Avoid the unconditional receive-side clone before QUIC routing is known. * perf(peer): publish packet filters as immutable snapshots Replace per-packet async and synchronous registry locks with ArcSwap snapshots. Permanent filters now need no activity checks, while managed registrations retain explicit acquire/release visibility. Closing a managed registration marks it inactive before atomically removing it. Existing snapshots keep in-flight filters alive, and registration mutations prune inactive entries while preserving newest-first order. * perf(instance): give native hosts direct packet egress Let the core create one bounded HostPacket channel and transfer its receiver directly to a PacketEgressHost during startup. Native TUN runtimes now consume that receiver without the intermediate PacketSink channel and forwarding task. Keep PacketSinkEgress as the compatibility adapter for callback and test hosts, and make receiver installation one-shot across desktop, mobile, and disabled runtimes. * perf(crypto): restore accelerated native AEAD backends Move Ring and OpenSSL implementations behind the core Encryptor seam. Portable builds continue selecting only supported backends. Restore historical precedence: OpenSSL, Ring, then RustCrypto. Keep backend availability consistent across secure transports and cover fixed-nonce wire compatibility between implementations. * perf(udp): receive native datagrams into owned buffers Extend the portable UDP socket seam with an owned-datagram receive path. Keep a compatible default for portable hosts. Native Unix sockets write recvmsg output directly into the final BytesMut allocation. This removes the per-packet stack-to-heap copy introduced by the portable socket boundary without exposing native socket resources to core. * perf(data-plane): remove portable hot-path overhead Restore native throughput lost while generalizing the host and UDP session layers. Read packet policy once per send, update traffic counters through registry guards, and preserve packet ownership while UDP dispatch borrows stable session state. Move UDP shutdown monitoring into a control task so forwarding avoids a select future per packet. Bound native datagram storage to 8 KiB, reject oversized sends, and drop truncated Unix receives. Keep accelerated AEAD selection warning-free when portable crypto features are also built. Cover session bounds, truncation, and idle shutdown with regression tests. * fix(udp): preserve portable datagram receive semantics Keep the public portable receive capacity at the theoretical UDP maximum instead of silently shrinking it to the native fast-path limit. Apply the 8 KiB session boundary after a complete portable receive, so Windows cannot turn an oversized datagram into a fatal listener error and other adapters cannot dispatch a truncated prefix. Cover dropping an oversized packet while the same portable socket continues to deliver the following valid datagram. * fix(ci): align feature gating with backend selection Compile the Ring implementation in production only when OpenSSL is not selected, while retaining it for cross-backend unit tests. Remove stale test imports and assert UDP dispatch results so the strict workspace Clippy job passes without suppressing diagnostics. |
||
|
|
021f523431 |
refactor(core): separate portable core from native runtime (#2451)
Create easytier-core as the portable owner of configuration, connectivity, tunnels, peer and routing state, gateways, management, the data plane, and instance lifecycle. Keep operating-system integration, native protocol engines, process startup, and presentation in easytier behind explicit Host capability adapters. Create easytier-proto to own schemas, generated RPC types, descriptors, and feature-scoped protocol slices. Remove runtime protobuf reflection from core while preserving unknown route-peer fields across forwarding. Normalize instance construction through CoreInstance, CoreHostAdapters, CoreProcessRuntime, and InstanceManager. Make the runtime config store the only authoritative mutable configuration after startup. Move the portable TCP/UDP data plane into core and extract a generic OperationBroker for completion, cancellation, disposal, and capacity accounting. Expose the session-based FFI v2 completion API and keep the WASI guest ABI, wire schemas, and adapters with core. Migrate CLI, GUI, web, FFI, Android JNI, OHOS, uptime, and mobile consumers to the shared manager and core state. Add explicit user/web config ownership and revision-aware web reconciliation. Preserve configuration, wire, and management behavior while fixing regressions discovered by the full platform and integration matrix: - inherit advertised relay capabilities in foreign networks; - refresh OSPF peer state immediately after runtime config changes; - restore CLI GlobalCtx event output without forcing GUI logging; - retain legacy encryption names and standalone RPC tunnel metadata; - restore ICMP host composition and fragmented UDP handling; - use portable 64-bit atomics on 32-bit MIPS targets; and - retain discarded operations until late cancellation completes. Validate the refactor across 45 GitHub checks, including Linux, macOS, Windows, FreeBSD, web, GUI, Android, OHOS, feature profiles, and three-node and subnet-proxy integration tests. BREAKING CHANGE: internal Rust module paths are not preserved. Legacy native data-plane APIs are replaced by the session-based FFI v2 API. The dedicated Android data-plane wrapper is removed. |
||
|
|
5273f4dcca | do not use workspace | ||
|
|
d70d085553 |
do some refactor
1. Route must impl PeerPacketFilter trait. 2. Use postcard lib to serial msg instead of bincode. 3. Fix cycle ref in peer_mgr & peer_rpc |
||
|
|
ecb385a82c | optimize packet def (#31) | ||
|
|
b0494687b5 | simplify packet definition (#30) | ||
|
|
0053666dfb | use uint32 as peer id (#29) | ||
|
|
c6c505f9d7 | support udp proxy gateway (#22) | ||
|
|
9779923b87 | Initial Version |