diff --git a/core/hy2/config.go b/core/hy2/config.go index 066cdee..1363fd4 100644 --- a/core/hy2/config.go +++ b/core/hy2/config.go @@ -284,15 +284,23 @@ func (n *Hysteria2node) getMasqHandler(tlsconfig *server.TLSConfig, conn net.Pac } u, err := url.Parse(c.Masquerade.Proxy.URL) if err != nil { - return nil, fmt.Errorf(fmt.Sprintf("masquerade.proxy.url %s", err)) + return nil, fmt.Errorf("masquerade.proxy.url %s", err) } handler = &httputil.ReverseProxy{ - Rewrite: func(r *httputil.ProxyRequest) { - r.SetURL(u) - // SetURL rewrites the Host header, - // but we don't want that if rewriteHost is false + Director: func(req *http.Request) { + req.URL.Scheme = u.Scheme + req.URL.Host = u.Host + + if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil { + xff := req.Header.Get("X-Forwarded-For") + if xff != "" { + clientIP = xff + ", " + clientIP + } + req.Header.Set("X-Forwarded-For", clientIP) + } + if !c.Masquerade.Proxy.RewriteHost { - r.Out.Host = r.In.Host + req.Host = req.URL.Host } }, ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) { diff --git a/core/hy2/logger.go b/core/hy2/logger.go index 3a40ff0..e5eb2a7 100644 --- a/core/hy2/logger.go +++ b/core/hy2/logger.go @@ -51,7 +51,7 @@ func (l *serverLogger) Connect(addr net.Addr, uuid string, tx uint64) { if err != nil { l.logger.Panic("Get limiter error", zap.String("tag", l.Tag), zap.Error(err)) } - if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp"); r { + if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp", true); r { if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok { userLimit.(*limiter.UserLimitInfo).OverLimit = true } @@ -72,7 +72,7 @@ func (l *serverLogger) TCPRequest(addr net.Addr, uuid, reqAddr string) { if err != nil { l.logger.Panic("Get limiter error", zap.String("tag", l.Tag), zap.Error(err)) } - if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp"); r { + if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp", true); r { if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok { userLimit.(*limiter.UserLimitInfo).OverLimit = true } @@ -97,7 +97,7 @@ func (l *serverLogger) UDPRequest(addr net.Addr, uuid string, sessionId uint32, if err != nil { l.logger.Panic("Get limiter error", zap.String("tag", l.Tag), zap.Error(err)) } - if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp"); r { + if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp", true); r { if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok { userLimit.(*limiter.UserLimitInfo).OverLimit = true } diff --git a/core/sing/hook.go b/core/sing/hook.go index 0b5e537..a68105f 100644 --- a/core/sing/hook.go +++ b/core/sing/hook.go @@ -108,7 +108,7 @@ func (h *HookServer) RoutedConnection(_ context.Context, conn net.Conn, m adapte return conn, t } ip := m.Source.Addr.String() - if b, r := l.CheckLimit(format.UserTag(m.Inbound, m.User), ip, true); r { + if b, r := l.CheckLimit(format.UserTag(m.Inbound, m.User), ip, true, true); r { conn.Close() log.Error("[", m.Inbound, "] ", "Limited ", m.User, " by ip or conn") return conn, t @@ -162,7 +162,7 @@ func (h *HookServer) RoutedPacketConnection(_ context.Context, conn N.PacketConn return conn, t } ip := m.Source.Addr.String() - if b, r := l.CheckLimit(format.UserTag(m.Inbound, m.User), ip, true); r { + if b, r := l.CheckLimit(format.UserTag(m.Inbound, m.User), ip, true, false); r { conn.Close() log.Error("[", m.Inbound, "] ", "Limited ", m.User, " by ip or conn") return conn, t diff --git a/core/xray/app/dispatcher/default.go b/core/xray/app/dispatcher/default.go index bd1afe8..9568891 100644 --- a/core/xray/app/dispatcher/default.go +++ b/core/xray/app/dispatcher/default.go @@ -177,7 +177,8 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network) (* // Speed Limit and Device Limit w, reject := limit.CheckLimit(user.Email, sessionInbound.Source.Address.IP().String(), - network == net.Network_TCP) + network == net.Network_TCP, + sessionInbound.Source.Network == net.Network_TCP) if reject { errors.LogInfo(ctx, "Limited ", user.Email, " by conn or ip") common.Close(outboundLink.Writer) @@ -241,7 +242,7 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu protocolString = resComp.ProtocolForDomainResult() } for _, p := range request.OverrideDestinationForProtocol { - if strings.HasPrefix(protocolString, p) || strings.HasPrefix(protocolString, p) { + if strings.HasPrefix(protocolString, p) || strings.HasPrefix(p, protocolString) { return true } if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" && diff --git a/go.mod b/go.mod index 8feea82..9ef2692 100644 --- a/go.mod +++ b/go.mod @@ -14,8 +14,8 @@ require ( github.com/goccy/go-json v0.10.3 github.com/hashicorp/go-multierror v1.1.1 github.com/juju/ratelimit v1.0.2 - github.com/sagernet/sing v0.5.0-alpha.12.0.20240717075530-332e47007567 - github.com/sagernet/sing-box v1.10.0-alpha.22 + github.com/sagernet/sing v0.5.0-alpha.13 + github.com/sagernet/sing-box v1.10.0-alpha.23 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.15.0 @@ -273,4 +273,5 @@ require ( lukechampine.com/blake3 v1.3.0 // indirect ) -replace github.com/sagernet/sing-box v1.10.0-alpha.22 => github.com/wyx2685/sing-box_mod v1.10.0-alpha.22 +// replace github.com/sagernet/sing-box v1.10.0-alpha.22 => /root/sing-box_mod +replace github.com/sagernet/sing-box v1.10.0-alpha.23 => github.com/wyx2685/sing-box_mod v1.10.0-alpha.23 diff --git a/go.sum b/go.sum index 4d35f64..cd1aa75 100644 --- a/go.sum +++ b/go.sum @@ -777,8 +777,8 @@ github.com/sagernet/quic-go v0.45.1-beta.2/go.mod h1:+N3FqM9DAzOWfe64uxXuBejVJwX github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.5.0-alpha.12.0.20240717075530-332e47007567 h1:Sus0pCYn5KPOQmArXdRTtrml6XccSzV87FkFTDqATtU= -github.com/sagernet/sing v0.5.0-alpha.12.0.20240717075530-332e47007567/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing v0.5.0-alpha.13 h1:fpR4TFZfu/9V3LbHSAnnnwcaXGMF8ijmAAPoY2WHSKw= +github.com/sagernet/sing v0.5.0-alpha.13/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sagernet/sing-dns v0.3.0-beta.10 h1:Js61EjQXVpcu2VDegWEQTH1isCcVwJju8WEHYgG4tQ0= github.com/sagernet/sing-dns v0.3.0-beta.10/go.mod h1:nXE6EYMXahB5DV3AcXYbFfuorqF7tbQ86kxweSxRKM4= github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo= @@ -941,16 +941,14 @@ github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1Y github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= -github.com/wyx2685/sing-box_mod v1.10.0-alpha.22 h1:3i//NYaaut+RecZAr6rVTxqmtYiU8s61kheBIOmYquE= -github.com/wyx2685/sing-box_mod v1.10.0-alpha.22/go.mod h1:tK9s5GiwC01C4Ap7RuKFchVIIa3Qv6KJGrr5pcX2zGo= +github.com/wyx2685/sing-box_mod v1.10.0-alpha.23 h1:DqByg8ldMTMXoUBLJO1fGhmOE7DavSR7Zlr1uYGl1ZY= +github.com/wyx2685/sing-box_mod v1.10.0-alpha.23/go.mod h1:a9BYzpu6AtQHdiIkf2B059xPFd95jh9QKXS2EaX8p7E= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg= github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE= -github.com/xtls/xray-core v1.8.21-0.20240721085503-22535d864399 h1:oKBzkEXI6eGM7e00mGQPl23Khlj3F0XYdzGwxvb0fdY= -github.com/xtls/xray-core v1.8.21-0.20240721085503-22535d864399/go.mod h1:0CwyMPNA5Cs+ukPXHbYQGgne/ug0PuXOSVqBu7zyXOc= github.com/xtls/xray-core v1.8.21 h1:cNdepud+R9PENKzXlSZsq0je4BWI6liXAuep6CD6xvk= github.com/xtls/xray-core v1.8.21/go.mod h1:0CwyMPNA5Cs+ukPXHbYQGgne/ug0PuXOSVqBu7zyXOc= github.com/yandex-cloud/go-genproto v0.0.0-20240318083951-4fe6125f286e h1:jLIqA7M9qY31g/Nw/5htVD0DFbxmLnlFZcHKJiG3osI= diff --git a/limiter/limiter.go b/limiter/limiter.go index e130995..d421500 100644 --- a/limiter/limiter.go +++ b/limiter/limiter.go @@ -3,6 +3,7 @@ package limiter import ( "errors" "regexp" + "strings" "sync" "time" @@ -129,7 +130,10 @@ func (l *Limiter) UpdateDynamicSpeedLimit(tag, uuid string, limit int, expire ti return nil } -func (l *Limiter) CheckLimit(taguuid string, ip string, isTcp bool) (Bucket *ratelimit.Bucket, Reject bool) { +func (l *Limiter) CheckLimit(taguuid string, ip string, isTcp bool, noSSUDP bool) (Bucket *ratelimit.Bucket, Reject bool) { + // check if ipv4 mapped ipv6 + ip = strings.TrimPrefix(ip, "::ffff:") + // ip and conn limiter if l.ConnLimiter.AddConnCount(taguuid, ip, isTcp) { return nil, true @@ -155,23 +159,24 @@ func (l *Limiter) CheckLimit(taguuid string, ip string, isTcp bool) (Bucket *rat userLimit = determineSpeedLimit(u.SpeedLimit, u.DynamicSpeedLimit) } } - - // Store online user for device limit - ipMap := new(sync.Map) - ipMap.Store(ip, uid) - // If any device is online - if v, ok := l.UserOnlineIP.LoadOrStore(taguuid, ipMap); ok { - ipMap := v.(*sync.Map) - // If this is a new ip - if _, ok := ipMap.LoadOrStore(ip, uid); !ok { - counter := 0 - ipMap.Range(func(key, value interface{}) bool { - counter++ - return true - }) - if counter > deviceLimit && deviceLimit > 0 { - ipMap.Delete(ip) - return nil, true + if noSSUDP { + // Store online user for device limit + ipMap := new(sync.Map) + ipMap.Store(ip, uid) + // If any device is online + if v, ok := l.UserOnlineIP.LoadOrStore(taguuid, ipMap); ok { + ipMap := v.(*sync.Map) + // If this is a new ip + if _, ok := ipMap.LoadOrStore(ip, uid); !ok { + counter := 0 + ipMap.Range(func(key, value interface{}) bool { + counter++ + return true + }) + if counter > deviceLimit && deviceLimit > 0 { + ipMap.Delete(ip) + return nil, true + } } } }