Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vless): IP restriction #2277

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open

feat(vless): IP restriction #2277

wants to merge 10 commits into from

Conversation

amir-devman
Copy link

@amir-devman amir-devman commented Jun 30, 2023

Limits user's connections by number of allowed IP addresses. Simply it closes any other connections if the user exceeds the limit.

The limitation is based on the Email provided for the user

Example config.json:

{
  "policy": {
    "levels": {
      "0": {
        "maxIPs": 0,
        "statsUserUplink": true,
        "statsUserDownlink": true
      },
      "1": {
        "maxIPs": 1,
        "statsUserUplink": true,
        "statsUserDownlink": true
      }
    },
    "system": {
      "statsInboundUplink": true,
      "statsInboundDownlink": true,
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  },
  "inbounds": [
    {
      "listen": "0.0.0.0",
      "tag": "vless-tcp-reality",
      "port": 443,
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "46a9ed35-8c0e-415a-9b5f-12755db8b8cd",
            "email": "limited-user@example.com",
            "level": 1,
            "flow": "xtls-rprx-vision"
          },
          {
            "id": "aaf2d6f0-e3d0-3840-b59f-1027b6ab14e3",
            "email": "unlimited-user@example.com",
            "level": 0,
            "flow": "xtls-rprx-vision"
          }
        ],
        "decryption": "none"
      }
    }
  ]
}

Note that, my main programming language is not Golang (I've written this RnD) and I might have written some codes incorrectly. feel free to help me fix it. because I am a super newbie with Xray-Core coding and also Golang.

@realartin
Copy link

@hiddify1 check this out

@hiddify-com
Copy link
Contributor

hiddify-com commented Jul 3, 2023 via email

@amir-devman
Copy link
Author

That is a great job. However, i think it would be better to have also a gRPC service to retrieve the active IPs. Is it possible to add it?

Well, that's possible. Currently, the real functionality of IP Restriction is important, then other things like API service

@yuhan6665
Copy link
Member

I think, core would not add logic to limit user. Such logic is only useful when tied with user authorization, payment calculation as such.

@amir-devman
Copy link
Author

I think, core would not add logic to limit user. Such logic is only useful when tied with user authorization, payment calculation as such.

@yuhan6665, Why not? it's very useful to avoid sharing configs...
This is a wanted feature from a lot of Iranian users.
Some people implemented this outside of xray-core but it would be great to have it on xray-core, as an option.

@yuhan6665
Copy link
Member

frankly, core is maintained with volunteer time. It is crucial to focus this project.

@amir-devman
Copy link
Author

amir-devman commented Jul 4, 2023

frankly, core is maintained with volunteer time. It is crucial to focus this project.

Is that mean that this PR is never going to be merged?
I did not get your mean by that.

@realartin
Copy link

@SafaSafari @hiddify1 we need your help to implement this

@FranzKafkaYu
Copy link
Contributor

I think, core would not add logic to limit user. Such logic is only useful when tied with user authorization, payment calculation as such.

@yuhan6665, Why not? it's very useful to avoid sharing configs... This is a wanted feature from a lot of Iranian users. Some people implemented this outside of xray-core but it would be great to have it on xray-core, as an option.

Maybe you shouldn't share your configs with others.Many Iranians want this feature because they sell proxies created by xray core, while xray core is not a commercial product.But I also think this feature can be a good option if we wanna share our server with other friends for cost sharing,so any chances to merge this PR? @yuhan6665 also CC @RPRX

@amir-devman
Copy link
Author

The real problem is that when you set up a server with Xray-core and give that vless config to your friend they'll share that with other people and that's a big problem.
But when it's limited by IP, a config cannot be shared with many people and this also helps sharing configs.

Of course, this helps proxy sellers but the main goal of this purpose is to avoid config sharing by limiting users by IP.

@yuhan6665
Copy link
Member

your service provider doesn't charge by number of connecting IPs right? It seems unnecessary to me. But again, I don't want core to get involved with these business logic anyway

@amir-devman
Copy link
Author

@FranzKafkaYu, Not many people knows how to buy a VPS and setup a proxy, there's always someone that creates one and shares with others to help others access free internet

@amir-devman
Copy link
Author

your service provider doesn't charge by number of connecting IPs right? It seems unnecessary to me. But again, I don't want core to get involved with these business logic anyway.

Almost all proxy sellers sell configs as subscriptions rather than single configuration, it's clear that this implementation does not provide limitation across multiple nodes and there's no Redis server involved here to help out proxy sellers.

@RPRX
Copy link
Member

RPRX commented Jul 4, 2023

我觉得你们说的都有些道理

一般来说我们不喜欢加机场专属功能,比如限 IP、限速,虽然 @FranzKafkaYu 找了一个不错的理由,不过我们都心知肚明

总之如果这是个 Feature Request,我肯定是不会去实现的,如果这是个写好的 PR,可以考虑一下,毕竟你们都找了“正当”理由

@FranzKafkaYu
Copy link
Contributor

FranzKafkaYu commented Jul 4, 2023

@FranzKafkaYu, Not many people knows how to buy a VPS and setup a proxy, there's always someone that creates one and shares with others to help others access free internet

it's reasonable,but if you share your configs with your friends,you should tell them do not share with others,or it will be blocked.If they shared,you should kick them out.Add this feature may cause some problems:

  • Not all of us need this feature,but this feature will increase binay size,it's not friendly for some low-end devices such as routers.
  • Need a stable maintainer for this feature,if you are willing to be a stable maintainer,this shouldn't be a problem

In principle,core should be tidy and keep core functions for proxy.User management and control should be achieved by other tools.Here if you want to restrict connected IPs,iptables can do this job for you.

In my opinion,this feature can be a good option if we share a proxy server with some strangers for cost sharing,but we also can use iptables to make some restrictions.

@RPRX
Copy link
Member

RPRX commented Jul 4, 2023

If they shared,you should kick them out.

这也是我想说的

@realartin
Copy link

I think, core would not add logic to limit user. Such logic is only useful when tied with user authorization, payment calculation as such.

@yuhan6665, Why not? it's very useful to avoid sharing configs... This is a wanted feature from a lot of Iranian users. Some people implemented this outside of xray-core but it would be great to have it on xray-core, as an option.

Maybe you shouldn't share your configs with others.Many Iranians want this feature because they sell proxies created by xray core, while xray core is not a commercial product.But I also think this feature can be a good option if we wanna share our server with other friends for cost sharing,so any chances to merge this PR? @yuhan6665 also CC @RPRX

please consider if we make a config for a few people then those people share the config :
1-traffic goes more than we prepared for
2- more user on ip or domain = dpi blocking
3- ....
we need this

@realartin
Copy link

realartin commented Jul 4, 2023

If they shared,you should kick them out.

这也是我想说的

sir at least make it like an extension to the core , if someone needs it make it on if someone doesn't want to use make it off and the default it can be off

tnx a lot ❤️

@realartin
Copy link

@FranzKafkaYu, Not many people knows how to buy a VPS and setup a proxy, there's always someone that creates one and shares with others to help others access free internet

it's reasonable,but if you share your configs with your friends,you should tell them do not share with others,or it will be blocked.If they shared,you should kick them out.Add this feature may cause some problems:

  • Not all of us need this feature,but this feature will increase binay size,it's not friendly for some low-end devices such as routers.
  • Need a stable maintainer for this feature,if you are willing to be a stable maintainer,this shouldn't be a problem

In principle,core should be tidy and keep core functions for proxy.User management and control should be achieved by other tools.Here if you want to restrict connected IPs,iptables can do this job for you.

In my opinion,this feature can be a good option if we share a proxy server with some strangers for cost sharing,but we also can use iptables to make some restrictions.

this is not efficient when we have a lot of user we can't control theme 1 by 1
if we could make it Auto every user can use 2 ip per uuid for example or ... it's very efficient and effective

@realartin
Copy link

realartin commented Jul 4, 2023

If they shared,you should kick them out.

这也是我想说的

for cost sharing :
we pay for good vps for each 1TB 1usd for example if this option could be on and working we can provide 2 users per uuid and give them 1TB usage as fair usage unlimited for fair cost !
but if this option is not , if we give to user 1TB fair usage as unlimited they're going to share it and use more than what we prepared for , also when so many ip connect to 1 vps the bandwidth drops also dpi can easily find us

please consider this as a request for so many people and help us let this be an extension 🫠❤️

@xkjdox
Copy link

xkjdox commented Jul 7, 2023

where's the core that we can test ?

@us254
Copy link

us254 commented Jul 8, 2023

where's the core that we can test ?

The pull request is currently under review and is not yet merged into the main codebase.

@amir-devman amir-devman changed the title (WIP) !feat(vless): IP restriction for vless !feat(vless): IP restriction for vless Jul 19, 2023
@amir-devman amir-devman changed the title !feat(vless): IP restriction for vless (WIP) !feat(vless): IP restriction for vless Jul 19, 2023
@MalinrRuwan
Copy link

@amir-devman Great implementation. Please do it for us with @RPRX because this feature is a must.

@RPRX
Copy link
Member

RPRX commented Aug 26, 2023

@amir-devman 实现了 #2277 (comment) ,这个功能会合并到 v1.9 中

@shakibamoshiri
Copy link

this feature connecting and disconnecting hooks can solve this issue and more like this

@agustyuzu
Copy link

I think the following questions you may consider:

  1. If I connect the server using ipv4 and ipv6, how many IPs I used?
  2. If I open the local port of client machine A for others to use, lots of users will use the IP of A. Is it allowed?
  3. Not all users are using Xray ( especially cellphone users ), there are not the blank of "e-mail option" in some software. Please consider the compatibility of different software.

Thank you for your contribution to this project !

Conflicts:
	common/xudp/xudp.go
	core/core.go
	go.mod
	go.sum
	main/commands/all/x25519.go
	proxy/freedom/config.pb.go
	proxy/wireguard/client.go
	proxy/wireguard/config.pb.go
	transport/internet/reality/config.pb.go
	transport/internet/reality/reality.go
@amir-devman amir-devman changed the title !feat(vless): IP restriction for vless feat(vless): IP restriction Feb 5, 2024
@amir-devman
Copy link
Author

@yuhan6665 @RPRX, I've done what you requested and also fixed a panic error.

@MHSanaei
Copy link

MHSanaei commented Feb 6, 2024

@amir-devman Thank you for your excellent work. Why is Maxips at the policy level? It might be more suitable to place it in the clients section.

@amir-devman
Copy link
Author

@MHSanaei This is what RPRX asked me to do.

@xsadegh
Copy link

xsadegh commented Feb 6, 2024

LGTM. However, needs to pass some tests before merging into the master branch.
Client IP limit is a required feature that prevents unwanted traffic from the majority of users.
Since the connection limitations are applied in the policy section it can reduce complexity in both codebase and end-user configuration as we can define policy for each user individually, Thus placing it in this section is a great idea.

@sailpwnz
Copy link

sailpwnz commented Feb 6, 2024

Great job. I need to create a policy with a level. In the level, specify the number of allowed connections. And in clients indicate the level number. Fabulous. Amir, can you make instructions? I want to test your development!!!

@amir-devman
Copy link
Author

@scriptvpskita
Copy link

please give us example config.json for using limit ip client

@amir-devman
Copy link
Author

@scriptvpskita Example config is in the PR description

@APT-ZERO
Copy link

APT-ZERO commented Feb 8, 2024

Is it useful for proxy panels who give each user multiple type of configs, or when there is multiple proxy nodes available for same user?

I think if there was an API to give a list of users with count and IP of active connections, it was more useful for all type of panels and will need no big changes, they must just add a little script to run each minute
The only challenge would be false positives, but i think there will be none if xray-core give only list of connections that is connected over 1 minute and not disconnected yet
In this method user will not get banned by mistake

@amir-devman
Copy link
Author

amir-devman commented Feb 8, 2024

@APT-ZERO,

No, that's not suited for that purpose, the whole purpose of this is to give people the ability to limit connections per IP to avoid the spread of their config.
People who sell proxies mostly sell subscriptions with multiple locations so this doesn't fit that need as this can't be controlled via API, it just gives the ability to people who have a single server and can share it with people near them without being worried about config getting shared among other people.

Also, no one is getting banned, this only prevents people from having access to config with certain IPs per user within the last 30 seconds. so for example, if someone connected and they changed the IP or ISP they should wait 30 seconds before they can connect again. (You can also set the MaxIPs value to 2 to avoid such problems as waiting 30 seconds).

However, you can have a single server as your upstream and multiple other servers as other locations servers and pass all traffic through your upstream server using Xray-Core's routing system, and this can work perfectly with that too.

@APT-ZERO
Copy link

APT-ZERO commented Feb 8, 2024

So it's not useful for panels who support multi-node
---
what about panels that supports subscription and is multi-protocol? even x-ui is multi-protocols today
MHSanaei/3x-ui#1496
---
what will happen if multiple users connect to different UUIDs with same IP?
---

if someone connected and they changed the IP or ISP they should wait 30 seconds before they can connect again. (You can also set the MaxIPs value to 2 to avoid such problems as waiting 30 seconds).

Do you know if you be on a bus or train and your phone connect to new antenna automatic, ISP will give you new IP?
You may get a new IP depended on bus/train speed

@xsadegh
Copy link

xsadegh commented Feb 8, 2024

@APT-ZERO,

what will happen if multiple users connect to different UUIDs with same IP? ---

I assume there's a map with a key for each user's email (which must be unique and represent the UUID) and if two users connect with the same IP address, the IP limit should work just fine because there are two independent keys!

Do you know if you be on a bus or train and your phone connect to new antenna automatic, ISP will give you new IP? You may get a new IP depended on bus/train speed

If you're on a bus/train/car at high speed, the ISP assigns a new IP address for you. (the period of reassignment depends on the nearest antenna, your speed, the ISP itself, etc... which could be less than 30 seconds), So there might be a small chance that certain IPs trying to connect to the proxy but with this feature, you'll not be able to connect according to the policy limits. This issue comes from the original IP limit idea, not the implementation and there's nothing to do about it.

@APT-ZERO
Copy link

APT-ZERO commented Feb 8, 2024

This issue comes from the original IP limit idea, not the implementation and there's nothing to do about it.

Well just change the Idea of IP limit to a better one that not bother the user?

I think this is the best way, will benefit all, will have no false positive & will not waste much hardware resources :

Xray-core saves connection start time in memory, and continue to count the connection live time (with each keep-alive / new packet)
If connection was alive more than 2x (or 2.5x) of connIdle time, then xray-core will show it as Active Connection (Yes, must not count the connection as active by their first packet)
But the core must delete that connection from Active Connections list if the connIdle time is passed
Now any proxy panel can get the Active Connections list from all nodes using Xray-core API and check if all of UUIDs/Emails of same user have more Active Connections than the Limit or not

In this way user can connect and disconnect to another server, can do Real Delay test in their clients, change IP as many time as they want, and they will not get banned by mistake, but if 2 people use the same config at same time, they will get detected easily

@willstore69
Copy link

This issue comes from the original IP limit idea, not the implementation and there's nothing to do about it.

Well just change the Idea of IP limit to a better one that not bother the user?

I think this is the best way, will benefit all, will have no false positive & will not waste much hardware resources :

Xray-core saves connection start time in memory, and continue to count the connection live time (with each keep-alive / new packet) If connection was alive more than 2x (or 2.5x) of connIdle time, then xray-core will show it as Active Connection (Yes, must not count the connection as active by their first packet) But the core must delete that connection from Active Connections list if the connIdle time is passed Now any proxy panel can get the Active Connections list from all nodes using Xray-core API and check if all of UUIDs/Emails of same user have more Active Connections than the Limit or not

In this way user can connect and disconnect to another server, can do Real Delay test in their clients, change IP as many time as they want, and they will not get banned by mistake, but if 2 people use the same config at same time, they will get detected easily

yep this is more interesting to do

@xsadegh
Copy link

xsadegh commented Feb 16, 2024

Hey there, I've used this fork for a while and noticed the core panics when you send frequent requests for a policy with 1 maxIPs via 2 different IPs, so I thought there might be a data race happening in app/proxyman/inbound/worker.go:

==================
WARNING: DATA RACE
Write at 0x00c000480a20 by goroutine 94:
  runtime.mapassign_fast32()
      runtime/map_fast32.go:93 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:113 +0xf3b
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous read at 0x00c000480a20 by goroutine 93:
  runtime.mapaccess1_fast32()
      runtime/map_fast32.go:13 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0xfde
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 94 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 93 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Write at 0x00c000480a20 by goroutine 94:
  runtime.mapdelete_fast32()
      runtime/map_fast32.go:273 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:124 +0x1304
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous read at 0x00c000480a20 by goroutine 93:
  runtime.mapiterinit()
      runtime/map.go:816 +0x0
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:274 +0x1346
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 94 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 93 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Read at 0x00c000481ef0 by goroutine 250:
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:275 +0x28c6
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous write at 0x00c000481ef0 by goroutine 254:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:113 +0xe6f
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 250 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 254 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Read at 0x00c0003100b8 by goroutine 250:
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:274 +0x28ac
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous write at 0x00c0003100b8 by goroutine 256:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:113 +0xf4a
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 250 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 256 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Write at 0x00c000480a20 by goroutine 250:
  runtime.mapdelete_fast32()
      runtime/map_fast32.go:273 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:124 +0x1304
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous read at 0x00c000480a20 by goroutine 256:
  runtime.mapaccess1_fast32()
      runtime/map_fast32.go:13 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0xfde
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 250 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 256 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Read at 0x00c000480a20 by goroutine 254:
  runtime.mapiterinit()
      runtime/map.go:816 +0x0
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:274 +0x1346
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous write at 0x00c000480a20 by goroutine 259:
  runtime.mapassign_fast32()
      runtime/map_fast32.go:93 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:113 +0xf3b
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 254 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 259 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Read at 0x00c0005f1470 by goroutine 565:
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:275 +0x28c6
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous write at 0x00c0005f1470 by goroutine 566:
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:286 +0x2ed9
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 565 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 566 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Read at 0x00c0005f1480 by goroutine 565:
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:275 +0x2964
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous write at 0x00c0005f1480 by goroutine 566:
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:285 +0x2e2c
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 565 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 566 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Read at 0x00c000160298 by goroutine 2012:
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:275 +0x2a7a
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous write at 0x00c000160298 by goroutine 2005:
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:287 +0x2fb2
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 2012 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 2005 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Write at 0x00c000480a20 by goroutine 3694:
  runtime.mapassign_fast32()
      runtime/map_fast32.go:93 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:113 +0xf3b
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous read at 0x00c000480a20 by goroutine 3683:
  runtime.mapiternext()
      runtime/map.go:862 +0x0
  runtime.mapiterinit()
      runtime/map.go:859 +0x22e
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 3694 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 3683 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Write at 0x00c000480a20 by goroutine 4928:
  runtime.mapdelete_fast32()
      runtime/map_fast32.go:273 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:124 +0x1304
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous read at 0x00c000480a20 by goroutine 4929:
  runtime.mapiternext()
      runtime/map.go:862 +0x0
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:274 +0x2845
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 4928 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 4929 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Read at 0x00c000480a20 by goroutine 4972:
  runtime.mapiternext()
      runtime/map.go:862 +0x0
  runtime.mapiterinit()
      runtime/map.go:859 +0x22e
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous write at 0x00c000480a20 by goroutine 4958:
  runtime.mapdelete_fast32()
      runtime/map_fast32.go:273 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:124 +0x1304
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 4972 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 4958 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================
==================
WARNING: DATA RACE
Write at 0x00c000480a20 by goroutine 5001:
  runtime.mapassign_fast32()
      runtime/map_fast32.go:93 +0x0
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:113 +0xf3b
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Previous read at 0x00c000480a20 by goroutine 4972:
  runtime.mapiternext()
      runtime/map.go:862 +0x0
  github.com/xtls/xray-core/proxy/vmess/inbound.(*Handler).Process()
      github.com/xtls/xray-core/proxy/vmess/inbound/inbound.go:274 +0x2845
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:118 +0x1097
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1.gowrap1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0x4f

Goroutine 5001 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f

Goroutine 4972 (running) created at:
  github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1()
      github.com/xtls/xray-core/app/proxyman/inbound/worker.go:141 +0xe4
  github.com/xtls/xray-core/transport/internet/websocket.(*requestHandler).ServeHTTP()
      github.com/xtls/xray-core/transport/internet/websocket/hub.go:69 +0x947
  net/http.serverHandler.ServeHTTP()
      net/http/server.go:3137 +0x2a1
  net/http.(*conn).serve()
      net/http/server.go:2039 +0x13c4
  net/http.(*Server).Serve.gowrap3()
      net/http/server.go:3285 +0x4f
==================

Locking/Unlocking mutex is so important when you use a map, and the mutex protects the map itself not the items on the map.

@woxie
Copy link

woxie commented Apr 28, 2024

Hello, are there any updates on this matter?

@burjuyz
Copy link

burjuyz commented May 1, 2024

Is it implemented or no?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet