83 Commits
Author SHA1 Message Date
ILIKEFUTANARI 6d6c1c117f feat: separate DNS service and interception modes 2026-10-09 17:43:48 +08:00
Mikhail Levin 324351f78d Add RoutingA rule import and scheduled updates from URL 2026-10-01 03:54:50 +03:00
RocketDev 0104fa8405 feat: display geosite date if gfwlist absent
Currently, if system /usr/share/v2raya/geosite.dat is used, v2raya will
not post error, but will display "none" for local GFWList date.
Since v2rayA reads this compatible file, we should display a date for
it, so that user is not confused.

Assisted-by: GPT-5.6-terra
2026-09-21 03:29:57 +08:00
Zakk c1e65ca44a fix(dns): refuse DoH and DoQ upstreams on save instead of failing every query
The DNS form's placeholder offered https://dns.google/dns-query, the
service turned https:// into protocol "https" and quic:// into "quic",
and the DNS module handed those to a miekg/dns client, which speaks udp,
tcp and tcp-tls only. Saving succeeded and every query on that rule then
failed, visible only in the log.

CheckDnsUpstream in kernel/v2ray accepts an address, tcp://, udp:// and
tls:// (DNS over TLS, which the module does support) and rejects https://
and quic:// with a message that names the alternatives; PutDnsRules
returns it as a 400 before anything is stored. The placeholder in the six
locales shows the supported forms and the docs say which schemes work.

Verified on the VM: https:// and quic:// rules come back BAD_REQUEST with
the message, tls://1.1.1.1 saves and the module logs
addr=1.1.1.1:853 protocol=tcp-tls; the previous rules restore unchanged.
2026-09-20 18:44:58 +10:00
Zakk 3364953513 feat(gui): documentation inside the app
The documentation site's domain has expired and its pages described a
2021 v2rayA. The page now carries its own docs, written against the
current code and shipped with the build, so what a user reads matches the
binary they run: quick start, transparent proxy, routing rules, inbounds
and sharing, flags and environment, troubleshooting. English and
Simplified Chinese; the other locales read the English text and say so.

The sections are Markdown under gui/src/docs/<locale>/, compiled to HTML
at build time by a small vite plugin around marked (a devDependency; the
bundle carries no parser) and loaded on demand, so the first load does not
grow. Headings get ids from their text. The flag table is not written by
hand: GET /api/params reads conf.Params' struct tags (id, short, default,
desc) through reflection, the same tags gonfig parses, and the page renders
it, so a new flag documents itself.

"#docs" and "#docs/<section>" open the page; the RoutingA dialog's help
button, the About page and small book icons in the settings sections and
the inbound dialogs point there instead of at the dead site or the wiki.
The navigation gains a fifth destination.
2026-09-20 14:45:55 +10:00
Zakk 2d16a92bbb fix(service): the findings of a cold read of the refactor and the scan fixes
Deleting nodes stored the renumbered connections, the subscriptions and
the servers in three commits; they are one transaction. Without a
catch-all DNS rule the module keeps its own fallback, as every earlier
release did. The login body is capped at 4 KiB, since it is now read
before the one-at-a-time semaphore. The apply-config error names a
failed restore, so every handler's message says whether the previous
value came back. The Windows system proxy reuses a snapshot pending
from an earlier run instead of refusing to start.
2026-09-20 09:59:29 +10:00
Zakk b1ca0c6edc fix(service): every state-changing handler takes the mutation turn; a truncated link cannot panic the parser
PostImport, PutPorts, PutDnsRules, PutRoutingA, PutGFWList,
DeleteGFWList, PutDomainsExcluded, PutTproxyWhiteIpGroups, PostOutbound
and PutOutbound wrote the store and regenerated the core outside the
mutation turn, so two of them could interleave core restarts with each
other or with a latency test. They take it like the rest.

ParseSSURL and ParseVmessURL sliced past the end of a link shorter than
its scheme prefix ("ss:", "vmess:x"), a panic reachable from a
subscription line.
2026-09-20 09:59:29 +10:00
Zakk ad509ce51b fix(service): the confirmed findings of four independent backend scans
A custom latency test URL that http.NewRequest rejects made a spawned
goroutine dereference nil and exit the process; the URL is validated
before any goroutine starts and the request error is handled. A
Shadowsocks link whose plugin field has no ";" panicked the parser, and
from the automatic subscription update that goroutine was unrecovered;
the parser accepts it and each updater recovers and logs.

The DNS module took the last non-bootstrap upstream as the fallback
while the template emitted upstreams in rule order with deduplication,
so a catch-all rule anywhere but last, or one whose upstream was
deduplicated, was not the fallback. The template names the fallback in
a new default_upstream field and the module honours it.

PUT /routingA stored the rules without regenerating the running core.
It goes through ApplyCoreConfig like the other config writers, with
restore on failure. UpdateSubscription logged a failed core reload and
answered success; it returns the error. PATCH /subscription joins the
mutation turn.

Subscription fetching retried through a direct connection when the
selected proxy failed, leaking the subscription URL; it returns the
error. Subscription documents are capped at 32 MiB and downloaded
assets at 256 MiB. PUT /gfwList validates the downloaded file as a
geosite list before replacing the working one.

The login handler took its one-at-a-time semaphore before reading the
body, so a client sending headers and no body blocked every login; the
body is read first and the HTTP server has header and idle timeouts.

Share links: a VLESS or VMess link without a numeric port is rejected
at parse time instead of producing port 0; an SSR link with a password
that is not base64 is rejected instead of importing empty; the SIP003
path gets its leading slash prepended, not a trailing one appended.

The macOS system proxy quoted shell arguments with strconv.Quote,
which leaves $(...) live; values are single-quoted. The Windows system
proxy snapshot includes AutoConfigURL, which teardown deleted and never
restored. Latency test responses with a non-2xx status are closed. The
version response carries the docker flag the GUI's port hints read.
2026-09-20 09:59:29 +10:00
Zakk ccfc5ca096 refactor(service): one apply-config path, NodeRef as a node's identity, typed SQLite stores
Three structural changes that share files, so one commit:

Settings, ports, DNS rules and custom inbounds each carried their own
copy of "store the new value, regenerate the core config, put the old
value back when that fails", and the outbound setting path had no
restore at all. ApplyCoreConfig takes a snapshot function and a store
function and does the sequence once for all five callers; the outbound
setting path restores like the others, and the error names which of
the three steps failed.

configure.Which was the persisted discriminator, the key that locates a
node, and the response row with its latency, link and selected flag at
once. NodeRef {type, id, sub, outbound} is the identity used by the
locator, EqualTo, the connected lists and the group operations; Which
embeds it and keeps the status fields. The JSON stays byte for byte
what it was (a test marshals a fixture before and after), stored
connected lists decode unchanged, and deduplication keys by identity
instead of by the whole row.

db.List* dispatched on "bucket/key" string literals to reach the
servers and subscriptions tables. The bodies are now Servers* and
Subscriptions* functions that configure calls directly; the List*
wrappers remain for the migration.
2026-09-20 09:59:29 +10:00
Zakk ae8e5a5047 chore: drop what nothing reaches
Three service packages outside the executable's dependency graph
(common/antiPollution, pkg/util/gopeed, kernel/vmessInfo), a blank
import of miekg/dns the core already imports, the --core-type flag no
code read, the PutAccount handler whose route was commented out, two GUI
API wrappers without a caller, two .SRCINFO files the release regenerates
and an unreferenced runit sample. The workflow path filters watched a
root go.mod that does not exist and the PR build skipped core/.
2026-09-20 09:17:11 +10:00
Zakk 90825094f8 fix(service): hook deadline, gated inbound writes, cleanup on a failed bind, atomic resolv backup
The core hooks ran under exec.Command with no deadline while Start held
the manager's lock, so a hook that never returned left the proxy stopped
and every status read blocked. They now run with the startup timeout as
their deadline in their own process group.

The custom-inbound POST and DELETE handlers did not take the mutation
turn; two concurrent additions read the same list and the last write
won. They take it like every other state-changing handler.

A failed HTTP bind ended in log.Fatal before the deferred cleanup, so
the core and the transparent-proxy rules stayed behind; run() now
returns the error through the same cleanup the shutdown path uses.

The resolv.conf backup was written in place; a crash mid-write left a
truncated file that the next start restored as the original. It is
written to a temporary file, synced and renamed, and an empty backup is
ignored on restore.
2026-09-20 09:17:11 +10:00
Zakk 6e6a7deed9 fix(controller): reads no longer wait for a mutation, writes wait for their turn
One `updating` flag guarded thirteen handlers, reads included: while a
subscription update or a latency test ran, GET /touch answered
REQUEST_IN_PROGRESS, so refreshing the page during a test failed at
random. A touch is a database read and needs no turn.

The flag becomes a turn that only the state-changing handlers take, and
a handler that finds it taken waits up to five seconds before answering
REQUEST_IN_PROGRESS instead of refusing at once; a client that leaves
while waiting is not answered.
2026-09-20 04:47:30 +10:00
Zakk d41ebec2d6 feat(service): /version reports the core's own version 2026-09-19 23:17:05 +10:00
Zakk 868497a0e9 feat(service): a group may route through one selected member
An outbound group with several members is balanced by the observatory
(least ping). The group's setting now also names one member's share
link as Selected: the core template then keeps only that member, the
touch flags it on the connected entry, and PUT /outboundSelection sets
or clears it. A selection that matches no member is ignored, so a node
removed or renamed by a subscription update returns the group to
balancing instead of breaking it.
2026-09-19 23:17:05 +10:00
Zakk d66c3927a5 fix(server): requests that change state apply or restore; requests that fetch have deadlines
PUT /dnsRules regenerates the running core's config and restores the
previous rules when that fails; SetPorts restores the previous ports
when the restart fails. The HTTP latency test drops subscription
entries as intended. The remote GFWList version request has a deadline
and its cache a one-hour TTL. CheckUpdate picks the index of the running
architecture and closes the body on every path.
2026-09-19 22:04:11 +10:00
Zakk 1dd2bf28ad feat(service): the tun transparent proxy is the core's own device
transparentType=tun no longer starts the TinyTun process. The template
emits a tun-mips inbound tagged transparent — device name, address, MTU,
the DNS module's address as the relay target, the user's exclusion list
plus v2rayA and the core by name and v2rayA by PID — and the service does
what the operating system needs once the core has the device up.

On Linux that is one table and four policy rules: table 2020 holds the
default route into tun0; marked packets (0x80: the core's sockets, the
direct outbound, the DNS module's upstreams) look up main in full and
leave through the physical interface, or fail with ENETUNREACH when main
has no route for their family rather than fall into the TUN; unmarked
packets take main with its default route suppressed, so LAN and static
routes stay physical, and everything else goes to table 2020. The main
table is never edited, so stopping restores egress by itself. A rule in
our preference range or a route in our table that is not ours is reported
and left alone; our own leftovers from a crash are removed first. Every
command that succeeded is recorded and undone in reverse on stop.

Three things the TinyTun path never hit are now on tun's path, so they
are fixed here: the DNS module is generated in tun mode (TinyTun did DNS
itself); its 127.2.0.17:53 listener is only added when port 53 is free,
instead of making the core exit on a host running another resolver; its
primary listener stays on loopback unless port sharing is on or the user
chose an address, and the DNS REDIRECT rules and their cleanup follow the
module's port instead of a hard-coded 52353, and a ::1 listener is added
when IPv6 is supported, because ip6tables REDIRECT delivers an
application's IPv6 query to ::1 which the IPv4 listener never saw. The
tun branch no longer
skips those rules: they are what catches queries to a LAN resolver, which
the routing keeps off the TUN.

The connectivity monitor probes the core's API port; the TinyTun socks
loop-back port it used is gone. Removed with TinyTun: --tinytun-bin, the
tunProcessBackend (eBPF) and tunBypassInterfaces settings (connected and
static routes bypass the TUN unconditionally now), the /networkInterfaces
endpoint that only served the latter, and the build tag. The version
endpoint reports tunSupported instead of tinytunSupported.

Tests cover the generated inbound and DNS module, the listen-address
rules, the redirect port, and — with V2RAYA_CORE_BIN set — that the
generated document loads in the real core. Windows and macOS route
handling follows in a separate commit; until then those builds report
the TUN as unsupported.
2026-09-19 10:34:55 +10:00
Zakk 15c727e1e1 fix(log): show the log in the web viewer without --log-file, keep the footer on screen
Without --log-file the viewer said "log printed to console, please see log in
console", which the Windows service, the launchd job and every "log to
console" setup cannot do. The logger now also keeps its last 4 MiB in memory
and the viewer reads that tail when there is no file; the lines carry the
same timestamp and level prefix as the file adapter's.

The log area also gave way to nothing: at 50vh a short window pushed the
filters and the export button below the fold with only a scrollbar to hint at
them. It now shrinks so the footer stays visible.
2026-09-18 15:29:18 +10:00
Zakk bb1f79bb87 fix(api): stop reporting results as failures
Three endpoints answered FAIL for something the caller asked for and got:

- an up-to-date GFWList came back as "could not update GFWList: latest version
  is …. GFWList is up to date", because the check returned an error;
- deleting the GFWList when it was already gone returned the raw
  "remove …: no such file or directory";
- the update check said "failed to get latest version from Package file: 1".

The up-to-date case is now a sentinel error the controller turns into a
success carrying alreadyUpToDate, deleting what is already gone succeeds, and
the two package-index messages say what was missing. "which can not be nil"
also became a sentence about the request.
2026-09-18 06:38:52 +10:00
Zakk 86e01d6176 feat(inbound): let a custom inbound require a username and password
A custom inbound port was open to anyone who could reach it, and older v2rayA
versions did offer authenticated inbounds, so users who relied on them had no
replacement (v2rayA/v2rayA discussions #1894, #1907).

CustomInbound carries optional credentials, which become the inbound's account
list. Half a credential pair is rejected: it would silently leave the port open.
2026-09-18 05:57:08 +10:00
Zakk 280710a319 fix(service): roll back custom inbounds, ip forwarding and report what was restored
Three gaps the settings rollback left open:

- adding or deleting a custom inbound stored the new list and then reloaded the
  core; a core that refused the list stayed stopped with the rejected inbound
  stored, so every later start failed too;
- a settings save that flipped ip forwarding left the kernel flag on the new
  value after the setting itself was rolled back, so the stored setting and the
  host disagreed;
- the rollback reported "the previous ones are back" even when restoring the
  setting or restarting the core had failed as well.

The session secret now retries persistence instead of accepting a failed store
for the life of the process, and an unreadable secret row is no longer
overwritten with a fresh one, which would have signed out every session.
2026-09-18 05:09:36 +10:00
Zakk 0005649661 fix(setting): keep the working setting and the core when a save is rejected
UpdateSetting stored the new setting before asking the core to reload it. When
the core refused the new config, the controller stopped the core and left the
rejected setting in the database, so the proxy was down and the next save
reported success while nothing was running.

Snapshot the setting before storing it, and on a reload failure put it back and
restart the core with it. The response now carries INVALID_CONFIG and the
reason the core gave.
2026-09-18 04:54:19 +10:00
Zakk aaeeb9307b feat(api): attach a machine-readable errorCode and params to FAIL responses
The GUI shows backend error text as is, so errors were never localized.
common.Coded wraps an error with a stable code and scalar parameters;
ResponseError adds "errorCode" and "params" next to the unchanged English
"message" when the chain carries one. Thirty-two user-facing errors are
coded (no server selected, core start failure, port occupied, malformed
link with protocol and detail, subscription fetch failure with host,
server/subscription not found with ids, bad request with the field,
credentials, session, admin, request in progress, GFW list missing,
invalid config, asset download, transparent setup, mux range, custom
inbound fields). logError now keeps the error chain instead of
flattening it. Messages, status codes and control flow are unchanged; the
two strings the GUI matches on stay as they are.

tools_test.go becomes an external test package so the common tests
compile again; its FillEmpty equality assertion, which never ran before,
is skipped with the reason.
2026-09-18 03:52:59 +10:00
Zakk ac79c92d6c fix(service): make API error messages say what was rejected and why
Errors that reach the GUI were written for the log: "ResolveURL failed:
invalid parameters", "httpGetUsingSpecificClient: response is nil",
"LocateServerRaw: invalid TYPE", "bad request", "illegal base64 data at
input byte 18". Reword the messages that can reach a user so each names
the input that was rejected (link scheme, missing password, port, server
id, request field), states the expected form for malformed input, drops
Go function names, keeps the %w chain so errors.Is/As still work, and
never echoes passwords, tokens or full share links (hosts only).
Messages the GUI string-matches ("invalid config", "the last request is
being processed") are unchanged.
2026-09-18 02:53:32 +10:00
Zakk ea21c45bae fix(controller): validate custom inbound ports and reload the core after changes
Adding or deleting a custom inbound only wrote the database: the running
core kept its old inbounds until the next unrelated restart, and a port
that collided with the configured socks5/http/pac/vmess/api ports was
accepted and broke the next core start. Reject out-of-range and colliding
ports with a message naming the port, and regenerate the config when the
core is running.
2026-09-18 02:53:31 +10:00
Zakk 5991e557fd fix(setting): keep stored values for fields the client omits
PutSetting decoded the request into a zero Setting and persisted the whole
struct, so the fields the settings dialog never sends (dnsCacheEnabled,
dnsPrefetch, dnsNegativeCache, the per-protocol backends) were saved as
false or empty on the first Save and the DNS cache silently switched off
with no control in the GUI to switch it back. Decode over the stored
setting so absent fields keep their value.
2026-09-18 02:53:31 +10:00
Zakk 262c56009e fix(service): guard crashes and silent data loss found in the sweep
- time.Ticker.Reset panics on a non-positive duration; a stored auto-update
  interval of 0 crashed every start (pre_update.go) and every settings
  save. Route both tickers through configure.IntervalHours, which falls
  back to one hour.
- The auto-updater indexes a startup snapshot; a subscription deleted
  while it runs panicked out of range in a goroutine and took the daemon
  down. UpdateSubscription now refuses an index that no longer exists.
- ResolveSubscriptionWithClient applied its 30 s timeout floor to a copy
  it never used, accepted HTTP error pages as an empty node list, and
  returned zero nodes without error, so UpdateSubscription replaced the
  stored list with nothing on a provider 403/5xx. Use the copy, reject
  status >= 400 and empty results.
- PutOutbound wrote an error response and then fell through to the
  success response, producing two JSON bodies.
- TestHttpLatency passed nil entries (servers it could not locate) to
  addHosts, which dereferenced them; skip them.
- ReqCache read the per-request mutex map after releasing the lock that
  guards writes to it (a fatal concurrent map access under load).
- The websocket writer ran one goroutine per message box on a single
  gorilla connection, which forbids concurrent writes; serialize them.
2026-09-18 02:53:31 +10:00
Zakk 9bb5ffbaef feat(import): let the client say whether it imports a server or a subscription
Import guessed from the URL scheme. Commit 3fd0e882 added http and https
to the server prefixes so that http proxy nodes were not stored as
subscriptions, and from then on every http(s) subscription address was
parsed as a proxy node and failed with "ResolveURL failed: invalid
parameters".

POST /api/import now takes "kind": "server" or "subscription". Import is
split into ImportServer and ImportSubscription; the old scheme-guessing
Import remains for requests without kind, with http and https back on
the subscription side as before 3fd0e882. The v4 migration calls the
explicit functions since it knows which list each address came from.
The GUI side (a server link / subscription address toggle that sends
kind) is in the gui branch.
2026-09-18 02:53:30 +10:00
Markson Joe Hon eef675f5f9 fix: persist kernel exit status across restarts and fix geosite DNS resolution
core: fix geosite.dat parsing in DNS resolver
- Replace broken GeoSiteList unmarshal with correct varint-length-delimited
  stream parser matching xray-core's format
- Add result caching to avoid re-reading the file per tag expansion

service: persist kernel exit status for proper state restoration
- Add LastKernelExitStatus (running/stopped/crashed) to DB
- Set 'running' on graceful shutdown while kernel is active so it
  is automatically restored on next startup
- Set 'stopped' when user explicitly stops the kernel via API
- Set 'crashed' when the kernel exits unexpectedly
- Check saved status at startup and log appropriate messages
- Expose lastKernelExit field via GET /api/version for the frontend
2026-07-02 13:51:44 +08:00
Markson Joe Hon 47f1462baf feat: init a new for v2raya core and fix a firewall mistake 2026-07-02 13:10:12 +08:00
Markson Pigeonzilla Plus bf8aa12ace service: drop ngui and drop v2ray/xray check 2026-06-26 10:07:43 +08:00
Markson Pigeonzilla Plus ff6bf0a43d Remove v2ray/xray core version detection and comparison logic
Since v2rayA now exclusively uses the v2raya_core binary, simplify or
remove all logic that detected, compared, or branched on different
core types (v2ray, xray, merged).

- Remove CheckCoreVersion, CoreVersionMismatchError, and the
  CoreVersion check in StartCoreProcess — core v2raya version
  comparison is no longer needed.

- Remove DetectCoreTypeByBinaryName and the Unknown/V2ray/Xray/Merged
  variant aliases. The only remaining Variant constant is V2rayaCore.

- Simplify GetV2rayServiceVersion: drop all CoreType/env-config
  detection and variant mismatch verification. The function always
  returns V2rayaCore and the version string from the binary.

- Simplify CheckV5 / isVersionSatisfied to return only an error,
  dropping the unused Variant return value.

- Remove variant-branching in Shadowsocks and Trojan Configuration
  methods — both always use the MT (Xray-compatible) path.

- Remove the CheckCoreVersion call from version.go and hardcode
  coreVersionValid/ variant in the API response.

- Drop the now-unused where import from shadowsocks.go and trojan.go.
2026-06-26 09:44:14 +08:00
Markson Hon 72dad35557 feat(service): pause transparent proxy on network loss and report state 2026-05-11 23:38:32 +08:00
Markson Hon 5a3a44b65b feat: add custom inbound-to-outbound binding with per-inbound routing rules 2026-05-11 23:38:32 +08:00
Markson Hon fd7162e88f feat(service): add custom inbound APIs and strengthen outbound/account flows 2026-05-04 19:07:22 +08:00
Markson Hon 56c1f8fbfd try to mix cores 2026-05-02 11:58:21 +08:00
ed00d75423 feat(server): finish TinyTun rollout and backend selection
Squashed from:
- c3e8b07f feat: add GET /api/networkInterfaces controller
- 10a5dc38 try to fix null pointer
- 4fa3e6c7 Merge branch 'v2rayA:main' into main
- 5e0457e7 tun: use tinytun v0.0.1-beta.4
- ce4bfa34 shadowsocks and trojan backend choosen

Co-authored-by: Markson Pigeonzilla <marksonpigeonzilla@bugdows.cn>
Co-authored-by: Markson Hon <50002150+MarksonHon@users.noreply.github.com>
2026-03-21 15:02:13 +08:00
89aca5911c feat(tun): migrate transparent proxy from Sing-Tun to TinyTun
Squashed from:
- bc2e2215 Remove all Sing-Tun related code, frontend and build tags
- 51c11701 Add TinyTun support for TUN-based transparent proxy
- d203a9e9 Add TinyTun auto_route toggle and custom route script dialog
- 4c67a319 Improve UI consistency and add tinytun build tag
- 6e411be6 use TinyTun instead of SIng-Tun

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Markson Hon <50002150+MarksonHon@users.noreply.github.com>
2026-03-21 15:01:17 +08:00
Markson HonandMarkson Pigeonzilla fe54c20e54 refactor(tun): modernize legacy route handling and DNS plumbing
Squashed from:
- ede4275e tun: better OS command
- 6a30c17c Tun: better route command
- 4b0f8e94 dns: rewrite DNS module

Co-authored-by: Markson Pigeonzilla <marksonpigeonzilla@bugdows.cn>
2026-03-21 14:59:01 +08:00
Markson Pigeonzilla 4eb2807de7 service: better user account check under Windows 2026-02-12 20:19:07 +08:00
Markson Pigeonzilla ba2c2fb0c1 Add xray mutli-server support 2026-02-05 18:10:05 +08:00
Markson Hon 6c9737f334 fix UDP based connections 2026-02-04 21:29:07 +08:00
Markson Hon aad7e17195 update daeuniverse/outbound 2026-02-04 21:11:26 +08:00
unknown-o afef751c18 feat: support custom tproxy direct ip 2025-11-05 20:08:10 +00:00
unknown-o 99bd664827 feat(backend): support setting tproxy white ip group 2025-11-05 16:30:24 +00:00
unknown-o bbc7e1c0ee feat(backend): suport download gfwlist form custom link 2025-02-09 01:54:15 +00:00
unknown-o 6cf02e4afb feat(backend): add delete gfwlist func 2025-02-09 00:51:44 +00:00
unknown-o a0c88bb57f feat(backend): add domain excluded setting 2025-02-07 06:00:23 +00:00
陈鼫RWHTYFZ 0459bad0f0 feat: 'testUrl' queryparam for api/httpLatency (#1193) 2023-12-02 15:20:24 +08:00
mzz 5c224d3674 fix: port occupation when latency test (#1058) 2023-08-31 23:36:08 +08:00
mzz2017 1b57d55739 fix: flow and xtls 2023-05-11 21:55:45 +08:00