x v0.27.1 carries the fix for the net.Transport error swallowing: the
function returned the first result it received, so the direction that
finished first decided the outcome, and a failing direction was hidden
by the successful one.
core stays at v0.6.1, which is already the latest release.
x v0.27.0 carries the QUIC flow control and half-close fixes (#135, #138),
the Pipe fix for data returned together with io.EOF (#134) and the new
auth file formats (#136, #137).
core stays at v0.6.1, which is already the latest release.
Data the peer already sent stays unread in the stream and keeps
occupying the connection level receive window of the quic session. When
the local app aborts a download, that data is never consumed, so the
credit is only returned when the read side of the stream is cancelled.
Without the cancellation the window drains. The initial stream window is
512 KB and the initial connection window is 768 KB, so a few aborted
downloads are enough to exhaust it. Once that happens the peer cannot
send data on any stream of the session: new requests still reach the
server, the server still acknowledges, there is no idle timeout and no
error in the log, and the client waits forever for a response. Only a
new session clears it.
The test aborts three downloads of a body that is much larger than the
flow control window, and then checks that the tunnel still forwards. The
client reads very slowly, so the data piles up in the connection that
carries it.
Verified against go-gost/x#135: with the fix reverted the test fails
with a timeout on the request that follows the aborted downloads, which
is the reported symptom.
Add an e2e case for the parallel selector configured with maxParallel: 1.
With only one node racing per connection the dead node is no longer
masked by the live one, so the requests alternate between success and
failure - that alternation is what proves the limit is applied.
Requires go-gost/x with the parallel selector node limit (gost#916).
gost's go.mod still pins v0.19.5, so this test only goes green once
that release lands and the dependency is bumped.
Covers gost#911 at the wire level: four UDP source sockets send through one
RUDP reverse tunnel bound on a relay server, and every datagram must come
back byte-identical to its own endpoint.
A frame torn by an interleaved writer shows up twice — as a corrupted
payload, and as the torn frame leaving half a header in the stream, which the
far end reads as "unexpected EOF" and answers by rebuilding the whole tunnel.
So the suite asserts both: no endpoint sees a corrupted datagram, and no
endpoint sees a receive gap long enough to be a teardown and rebind.
Verified against a binary built before the fix (4 endpoints, 35% loss, 1.4s
gaps, suite fails) and after it (0% loss, no corruption, 0.2s gaps, passes).
Covers the amd64v3 vs amd64 choice — both packages declare Architecture:
amd64, so the file name is the only way to tell them apart — and the fact
that the packaged systemd service stays inactive until /etc/gost/gost.yml
is created.
systemd-analyze verify warns "Special user nobody configured, this is not
safe!": nobody is a shared account, so any other service running as it can
read and write /run/gost. DynamicUser= gives the unit its own transient
identity, named gost, without adding a static user to the package.
Verified under a real systemd: the unit starts, binds :80 through the
ambient capabilities, runs as the dynamic user, and is skipped rather than
failed when /etc/gost/gost.yml is absent.
CapabilityBoundingSet= was dropped when CAP_NET_ADMIN was added for TUN,
which leaves the bounding set unrestricted. Pin it to the capabilities the
unit actually needs. Restore ~@privileged as well: TUN uses ioctl(TUNSETIFF)
and netlink, neither of which is in that group.
* Add systemd service file
* Add DEB and RPM packages for amd64, amd64v3 and arm64 architectures
* Remove GOMEMLIMIT from systemd service
* Fix packaged systemd service defaults
Add an e2e suite covering go-gost/x#125: a malformed UDP datagram sent
to a cipherKey-enabled QUIC listener must not close the shared transport.
Uses the canonical http-over-quic chaining pattern and verifies the
forward still works after the invalid datagram.
Also bumps go.mod/go.sum (plugin v0.6.1, otel, x/net, etc.).
Reproduce the regression where a domain-only whitelist bypass on a red
(transparent) proxy rejected every connection: the pre-sniffing bypass
check ran against the bare destination IP, which is never in a domain
whitelist, before SNI sniffing could match. A privileged container
redirects outbound TCP to the red service; asserts an allowlisted SNI
is forwarded (hello-gost) and a non-allowlisted SNI is rejected.
ProxyProtoSuite starts gost with metadata.proxyProtocol set and asserts
the HAProxy PROXY header is prepended on outbound connections (v1/v2),
backed by a raw-TCP capture script and configs. Add echo754_repro.py
from the hot-reload EADDRINUSE investigation (gost#754).
Bump github.com/go-gost/core to v0.6.1 and x to v0.16.0.
Adds TestGostTargetPolicyBypass: a service-level bypass blacklists the
echo server; verifies the control request is 403, a checksum-valid
Gost-Target header naming an allowed authority cannot reach the blocked
backend, and a malformed header is fail-closed. Verified to catch the bug
by reverting the fix (exploit returned the backend response).
- Add ExecOutput helper to demultiplex the raw Docker exec stream so test
output assertions see clean stdout+stderr instead of framed bytes.
- Wait for container readiness via exposed port or "listening on" log line
when no ports are exposed.
- Use curl --proxy-* TLS options for the mTLS HTTPS-proxy test.
- Relax the http_cache first-request assertion (shared backend counter).
- Add gost#898 rtcp forwarder filter.host e2e test (multi-service one tunnel).
- Bump x to v0.15.7.
Co-Authored-By: Claude <noreply@anthropic.com>
Verifies dead->alive->dead node transition: a node excluded by a failing cmd
probe resumes carrying traffic once the probe flips healthy, without restart.
Add TestUDPForwardQUICSniffing: sends a real captured QUIC v1 Initial packet
through the UDP forward handler (with sniffing enabled) and verifies the
datagram is echoed back. Covers the QUIC ClientHello/ServerHello sniff path
in x/handler/redirect/udp and x/handler/forward/local.
Add e2e regression test for http.failCodes selector bug —
FIFO selector + failCodes=429 on first node proves
node-429 is excluded after first 429 response and all
subsequent requests go to node-good.