Skip to content

[Bug]: Removed, limited or expired users keep their open Xray connections #92

Description

@Free-Guy-IR

Before you submit

  • I searched existing issues and did not find the same problem.
  • I am using the latest available PasarGuard version, or I included the exact version below.

PasarGuard version

Node dev at d44ca8e (0.5.4 plus 8 commits). Xray v26.3.27 (d2758a0), the official release that make install_xray installs.

Installation type

Source / uv

What happened?

When the panel limits, disables, expires or deletes a user, the node removes that user from each Xray inbound with RemoveUserOperation. After that, the user cannot open new connections. But the connections the user already had stay open and keep carrying traffic until the client closes them. A download that was running when the user was limited keeps running at full speed.

A limited user can therefore keep using traffic for as long as their client keeps its tunnel open.

Steps to reproduce

  1. Start the node's Xray backend with one VLESS TCP inbound and one user, 1.alice.
  2. As 1.alice, open a connection that downloads continuously.
  3. Remove the user: call SyncUser with the same user and no inbounds. This is what the panel sends when a user is limited or expires.
  4. Open a new connection as 1.alice. It is refused, as expected.
  5. Keep reading from the connection opened in step 2. It keeps receiving data.

The pull request that follows this issue adds a test that runs these steps against the real core and logs the result of step 5.

Expected behavior

  • Removing a user from an inbound closes the connections that user already has on that inbound.
  • Sending an unchanged user again does not touch their connections. The panel does this, for example, after an admin edits a user's data limit or expiry date.

Logs and error messages

# node dev d44ca8e, official Xray v26.3.27, Linux container limited to 1.5 CPUs, loopback
=== RUN   TestUserSyncKeepsAnUnchangedUsersOpenConnection
    user_session_test.go:175: the connection the removed user had already opened received 532602880 bytes in the next second (err <nil>)
--- PASS: TestUserSyncKeepsAnUnchangedUsersOpenConnection (3.59s)

Neither the node nor Xray logs an error. The removal itself succeeds.

Environment

OS: Linux (Alpine container, linux/amd64); also reproduced on macOS
Database: not involved
Python version: not involved
Node.js version: not involved
Browser: not involved
Reverse proxy / CDN: none, loopback only
Go: 1.26.3
Xray: v26.3.27, official release

Relevant configuration

{
  "inbounds": [{
    "tag": "VLESS TCP SESSION",
    "listen": "127.0.0.1",
    "port": 10000,
    "protocol": "vless",
    "settings": {"clients": [], "decryption": "none"}
  }],
  "outbounds": [{"tag": "direct", "protocol": "freedom"}]
}

Screenshots or videos

No response

Additional context

Root cause, in Xray v26.3.27 (d2758a0)

  • app/proxyman/command/command.go:55-65: RemoveUserOperation.ApplyInbound only calls UserManager.RemoveUser.
  • RemoveUser only deletes the user from the validator:
    • proxy/vless/inbound/inbound.go:245-248
    • proxy/vmess/inbound/inbound.go:176
    • proxy/trojan/server.go:124-126
  • A connection is authenticated once, when it is accepted (proxy/vless/inbound/inbound.go:537). Mux sub-streams reuse that user. Nothing closes the connection when the user is removed later.

The node cannot close these connections by itself, because Xray gives it no handle to a user's connections. The fix has to be in the core. XTLS/Xray-core#5844 makes RemoveUser close the user's connections on that inbound.

A node-side change is needed as well. SyncUser and UpdateUsers remove and re-add a user on every inbound the user stays on, even when nothing about the account changed. With a core that closes connections on RemoveUser, every such sync would disconnect the user. I built the head of XTLS/Xray-core#5844 (f356a34) and ran the same test: a SyncUser that changed nothing cut 1.alice's open connection at once:

    user_session_test.go:159: open connection stopped after SyncUser sent the same user again: received 0 bytes, err EOF
--- FAIL: TestUserSyncKeepsAnUnchangedUsersOpenConnection (1.54s)

The pull request that follows makes the node remove and re-add a user only when their account on that inbound changed.

Impact. This comes from a production deployment of a fork of this node, which runs the same Xray backend code with Xray v26.3.27. After the panel limited a user, the user's open vless-xhttp and trojan-xhttp downloads were never cut. One ran at full speed to the end of a 480 MiB file, while new connections were refused. At that point, 24 users were 0.5 GB or more over their limit, about 50 GB in total.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions