Compare commits

...

36 Commits
ax ... v1.5.3

Author SHA1 Message Date
yuhan6665
d51db9469e Update version 1.5.3 2022-01-28 18:13:15 -05:00
yuhan6665
aa554871ef Update dependencies 2022-01-28 18:13:15 -05:00
yuhan6665
578d903a9e Quic related improvements (#915)
* DialSystem for Quic

DialSystem() is needed in case of Android client,
where the raw conn is protected for vpn service

* Fix client dialer log

Log such as:
tunneling request to tcp:www.google.com:80 via tcp:x.x.x.x:443
the second "tcp" is misleading when using mKcp or quic transport

Remove the second "tcp" and add the correct logging for transport dialer:
- transport/internet/tcp: dialing TCP to tcp:x.x.x.x:443
- transport/internet/quic: dialing quic to udp:x.x.x.x:443

* Quic new stream allocation mode

Currently this is how Quic works: client muxing all tcp and udp traffic through a single session, when there are more than 32 running streams in the session,
the next stream request will fail and open with a new session (port). Imagine lineup the session from left to right:
 |
 |  |
 |  |  |

As the streams finishes, we still open stream from the left, original session. So the base session will always be there and new sessions on the right come and go.
However, either due to QOS or bugs in Quic implementation, the traffic "wear out" the base session. It will become slower and in the end not receiving any data from server side.
I couldn't figure out a solution for this problem at the moment, as a workaround:
       |  |
    |  |  |
 |  |  |

I came up with this new stream allocation mode, that it will never open new streams in the old sessions, but only from current or new session from right.
The keeplive config is turned off from server and client side. This way old sessions will natually close and new sessions keep generating.
Note the frequency of new session is still controlled by the server side. Server can assign a large max stream limit. In this case the new allocation mode will be similar to the current mode.
2022-01-28 18:11:30 -05:00
dependabot[bot]
30a40aa6f1 Bump google.golang.org/grpc from 1.43.0 to 1.44.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.43.0 to 1.44.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.43.0...v1.44.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-25 20:56:13 -05:00
dependabot[bot]
dfcfecf7d8 Bump github.com/google/go-cmp from 0.5.6 to 0.5.7
Bumps [github.com/google/go-cmp](https://github.com/google/go-cmp) from 0.5.6 to 0.5.7.
- [Release notes](https://github.com/google/go-cmp/releases)
- [Commits](https://github.com/google/go-cmp/compare/v0.5.6...v0.5.7)

---
updated-dependencies:
- dependency-name: github.com/google/go-cmp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-20 09:54:41 -05:00
dependabot[bot]
68d37adf88 Bump github.com/lucas-clemente/quic-go from 0.24.0 to 0.25.0
Bumps [github.com/lucas-clemente/quic-go](https://github.com/lucas-clemente/quic-go) from 0.24.0 to 0.25.0.
- [Release notes](https://github.com/lucas-clemente/quic-go/releases)
- [Changelog](https://github.com/lucas-clemente/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/lucas-clemente/quic-go/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: github.com/lucas-clemente/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-19 09:32:01 -05:00
Machtergreifung
e96e5994d0 Update Vmess Warning Errors 2022-01-19 09:30:28 -05:00
yuhan6665
b4cdb6075b Remove a missed alterId in test 2022-01-14 17:52:12 -05:00
Machtergreifung
dde033ca1f go 1.17.6 (#900)
* go 1.17.6
2022-01-14 17:49:46 -05:00
Machtergreifung
9ad26fa049 chore fixed (#897)
* chore fixed
2022-01-12 21:51:47 -05:00
Machtergreifung
800b3bd3fe chore fixed (#895)
* chore fixed
2022-01-10 23:39:58 -05:00
dependabot[bot]
1447615f3a Bump github.com/miekg/dns from 1.1.43 to 1.1.45
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.43 to 1.1.45.
- [Release notes](https://github.com/miekg/dns/releases)
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.43...v1.1.45)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-10 23:38:33 -05:00
yuhan6665
980b35b3fe Update version 1.5.2 2021-12-24 09:19:17 -05:00
yuhan6665
9ea1bf7c1d Fix shadowsocks xchacha cipher nonce size 2021-12-19 21:18:35 -05:00
hmol233
63da3a5481 grpc: add initial_windows_size option 2021-12-19 21:14:14 -05:00
rf2892jfdsajf
3057a7c999 doc: add contributing section to readme and update build instruction style (#863)
* doc: add bash style

* doc: add code of conduct to readme

Co-authored-by: Your Name <you@example.com>
2021-12-19 19:10:00 -05:00
xqzr
c8e2a99e68 fix unsupported cipher method: xChaCha20-IETF-Poly1305 2021-12-16 18:57:06 -05:00
tritu
756bac7fa4 go 1.17.5 2021-12-15 21:12:00 -05:00
yuhan6665
b0a08d3ed3 Update version 1.5.1 2021-12-14 20:34:07 -05:00
yuhan6665
0d292e0dcd Update dependencies 2021-12-14 20:33:15 -05:00
yuhan6665
dd9da23a59 Add statistics in conn testing
Occasional error is observed when we execute long test
Print time and memory for better troubleshooting in the future

Co-authored-by: Jebbs <qjebbs@gmail.com>
2021-12-14 20:15:05 -05:00
yuhan6665
4e88a369c4 Fix vmess test with portList 2021-12-14 20:01:53 -05:00
yuhan6665
e93da4bd02 Fix some tests and format code (#830)
* Increase some tls test timeout

* Fix TestUserValidator

* Change all tests to VMessAEAD

Old VMess MD5 tests will be rejected and fail in 2022

* Chore: auto format code
2021-12-14 19:28:47 -05:00
yuhan6665
d5a7901601 Unified drain support for vmess and shadowsocks (#791)
* Added test for no terminate signal

* unified drain support for vmess and shadowsockets

* drain: add generated file

Co-authored-by: Shelikhoo <xiaokangwang@outlook.com>
2021-12-14 19:27:31 -05:00
Shelikhoo
6fb5c887b2 Fix DoS attack vulnerability in CommandSwitchAccountFactory 2021-12-11 20:14:57 -05:00
yaotthaha-vscode
4fc284a8e9 Try to fix UDP error 2021-12-01 12:02:27 -05:00
yuhan6665
7c240e8630 Fix null pointer exception for observatory
Core setup router object first, when InjectContext() is called, observatory object is still null,
so observatory need to be injected after InjectContext()
2021-11-20 00:48:02 -05:00
lucifer9
d6ae4e9ba2 Make it easier to configure multiple listening ports 2021-11-17 23:13:15 -05:00
dependabot[bot]
c3298c38a0 Bump google.golang.org/grpc from 1.41.0 to 1.42.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.41.0 to 1.42.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.41.0...v1.42.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-04 21:09:16 -04:00
dev_0x1
eb6ced79e7 Add .vscode to ignored directories 2021-11-04 21:08:26 -04:00
秋のかえで
63d0cb1bd6 Refactor: new Shadowsocks validator (#629)
* Refactor: new Shadowsocks validator

* Fix NoneCliper cannot work

* Feat: refine the size of drain

* fix: fix validator after merge 'main'

* fix: UDP user logic

* style: refine code style
2021-10-31 22:10:26 -04:00
roc
dd6769954c hotRelodaInterval --> hotReloadInterval 2021-10-26 21:45:31 -04:00
Zhu Sheng Li
28b17b529d Add concurrency option for outbound observation
Add `enableConcurrency` option, false by default.

If it's set as `true`, start probing outbounds concurrently in every
circle of observation. Wait `probeInterval` between observation circles.
2021-10-26 13:09:03 +08:00
yuhan6665
abb8ba8b0e Observatory related fixes (#788)
* fix:observatory not supported by multi-json

* Fix: observatory starts with empty config & fails to close (#957)

* Update strategy_leastping.go (#1019)

* add custom probe URL support for observatory

* add custom probe interval for observer

* apply coding style

* Fix: observatory log & JSON config(#1211)

Co-authored-by: ihotte <ihotte@yeah.net>

* Change default probe url from api.v2fly.org to www.google.com

* Cherry-pick missing code from branch 'dev-advloadblancer-2'

Co-authored-by: Shelikhoo <xiaokangwang@outlook.com>
Co-authored-by: Loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com>
Co-authored-by: fanyiguan <52657276+fanyiguang@users.noreply.github.com>
Co-authored-by: ihotte <3087168217@qq.com>
Co-authored-by: ihotte <ihotte@yeah.net>
2021-10-26 13:00:31 +08:00
Shelikhoo
7038bded7b Added experiment to avoid sending the termination signal
(cherry picked from commit c5357e1f000054ba5836468922cae52a830c8019)
2021-10-22 18:34:57 +08:00
Shelikhoo
ff35118af5 VMess AEAD based packet length
(cherry picked from commit 08221600082a79376bdc262f2ffec1a3129ae98d)
2021-10-22 18:34:57 +08:00
147 changed files with 2188 additions and 1019 deletions

View File

@@ -123,7 +123,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: ^1.17.2 go-version: ^1.17.6
- name: Get project dependencies - name: Get project dependencies
run: go mod download run: go mod download

View File

@@ -28,7 +28,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: ^1.17.2 go-version: ^1.17.6
- name: Checkout codebase - name: Checkout codebase
uses: actions/checkout@v2 uses: actions/checkout@v2

1
.gitignore vendored
View File

@@ -26,3 +26,4 @@ vprotogen
errorgen errorgen
!common/errors/errorgen/ !common/errors/errorgen/
*.dat *.dat
.vscode

View File

@@ -27,6 +27,9 @@
- [(Tap) Repository 0](https://github.com/N4FA/homebrew-xray) - [(Tap) Repository 0](https://github.com/N4FA/homebrew-xray)
- [(Tap) Repository 1](https://github.com/xiruizhao/homebrew-xray) - [(Tap) Repository 1](https://github.com/xiruizhao/homebrew-xray)
## Contributing
[Code Of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)
## Usage ## Usage
[Xray-examples](https://github.com/XTLS/Xray-examples) / [VLESS-TCP-XTLS-WHATEVER](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-WHATEVER) [Xray-examples](https://github.com/XTLS/Xray-examples) / [VLESS-TCP-XTLS-WHATEVER](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-WHATEVER)
@@ -71,13 +74,13 @@ This repo relies on the following third-party projects:
### Windows ### Windows
``` ```bash
go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main
``` ```
### Linux / macOS ### Linux / macOS
``` ```bash
go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
``` ```

View File

@@ -37,7 +37,7 @@ func (l *OutboundListener) Accept() (net.Conn, error) {
} }
} }
// Close implement net.Listener. // Close implements net.Listener.
func (l *OutboundListener) Close() error { func (l *OutboundListener) Close() error {
common.Must(l.done.Close()) common.Must(l.done.Close())
L: L:

View File

@@ -4,7 +4,6 @@ package dispatcher
import ( import (
"context" "context"
"github.com/xtls/xray-core/features/dns"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -16,6 +15,7 @@ import (
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"

View File

@@ -11,7 +11,7 @@ import (
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
// newFakeDNSSniffer Create a Fake DNS metadata sniffer // newFakeDNSSniffer Creates a Fake DNS metadata sniffer
func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) { func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) {
var fakeDNSEngine dns.FakeDNSEngine var fakeDNSEngine dns.FakeDNSEngine
err := core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { err := core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {

View File

@@ -6,6 +6,7 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/miekg/dns" "github.com/miekg/dns"
"github.com/xtls/xray-core/app/dispatcher" "github.com/xtls/xray-core/app/dispatcher"
. "github.com/xtls/xray-core/app/dns" . "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/app/policy" "github.com/xtls/xray-core/app/policy"

View File

@@ -13,7 +13,7 @@ import (
dns_feature "github.com/xtls/xray-core/features/dns" dns_feature "github.com/xtls/xray-core/features/dns"
) )
// Fqdn normalize domain make sure it ends with '.' // Fqdn normalizes domain make sure it ends with '.'
func Fqdn(domain string) string { func Fqdn(domain string) string {
if len(domain) > 0 && strings.HasSuffix(domain, ".") { if len(domain) > 0 && strings.HasSuffix(domain, ".") {
return domain return domain
@@ -163,7 +163,7 @@ func buildReqMsgs(domain string, option dns_feature.IPOption, reqIDGen func() ui
return reqs return reqs
} }
// parseResponse parse DNS answers from the returned payload // parseResponse parses DNS answers from the returned payload
func parseResponse(payload []byte) (*IPRecord, error) { func parseResponse(payload []byte) (*IPRecord, error) {
var parser dnsmessage.Parser var parser dnsmessage.Parser
h, err := parser.Start(payload) h, err := parser.Start(payload)

View File

@@ -92,7 +92,7 @@ func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
return nil return nil
} }
// GetFakeIPForDomain check and generate a fake IP for a domain name // GetFakeIPForDomain checks and generates a fake IP for a domain name
func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address { func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
if v, ok := fkdns.domainToIP.Get(domain); ok { if v, ok := fkdns.domainToIP.Get(domain); ok {
return []net.Address{v.(net.Address)} return []net.Address{v.(net.Address)}
@@ -123,7 +123,7 @@ func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
return []net.Address{ip} return []net.Address{ip}
} }
// GetDomainFromFakeDNS check if an IP is a fake IP and have corresponding domain name // GetDomainFromFakeDNS checks if an IP is a fake IP and have corresponding domain name
func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string { func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string {
if !ip.Family().IsIP() || !fkdns.ipRange.Contains(ip.IP()) { if !ip.Family().IsIP() || !fkdns.ipRange.Contains(ip.IP()) {
return "" return ""

View File

@@ -1,9 +1,8 @@
package fakedns package fakedns
import ( import (
"testing"
gonet "net" gonet "net"
"testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"

View File

@@ -4,6 +4,7 @@ import (
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
. "github.com/xtls/xray-core/app/dns" . "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"

View File

@@ -186,7 +186,7 @@ func (c *Client) Name() string {
return c.server.Name() return c.server.Name()
} }
// QueryIP send DNS query to the name server with the client's IP. // QueryIP sends DNS query to the name server with the client's IP.
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, disableCache bool) ([]net.IP, error) { func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, disableCache bool) ([]net.IP, error) {
ctx, cancel := context.WithTimeout(ctx, 4*time.Second) ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, disableCache) ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, disableCache)

View File

@@ -4,9 +4,8 @@ import (
"context" "context"
"strings" "strings"
"github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/dns/localdns" "github.com/xtls/xray-core/features/dns/localdns"
) )

View File

@@ -5,10 +5,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/xtls/xray-core/common/net"
. "github.com/xtls/xray-core/app/dns" . "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )

View File

@@ -8,6 +8,9 @@ import (
"time" "time"
"github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go"
"golang.org/x/net/dns/dnsmessage"
"golang.org/x/net/http2"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -17,8 +20,6 @@ import (
"github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/common/task"
dns_feature "github.com/xtls/xray-core/features/dns" dns_feature "github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"golang.org/x/net/dns/dnsmessage"
"golang.org/x/net/http2"
) )
// NextProtoDQ - During connection establishment, DNS/QUIC support is indicated // NextProtoDQ - During connection establishment, DNS/QUIC support is indicated

View File

@@ -6,13 +6,12 @@ import (
"testing" "testing"
"time" "time"
"github.com/xtls/xray-core/features/dns"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
. "github.com/xtls/xray-core/app/dns" . "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/dns"
) )
func TestQUICNameServer(t *testing.T) { func TestQUICNameServer(t *testing.T) {

View File

@@ -2,7 +2,7 @@ package log
import ( import (
"sync" "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
) )

View File

@@ -0,0 +1,51 @@
//go:build !confonly
// +build !confonly
package command
import (
"context"
"google.golang.org/grpc"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common"
core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension"
)
type service struct {
UnimplementedObservatoryServiceServer
v *core.Instance
observatory extension.Observatory
}
func (s *service) GetOutboundStatus(ctx context.Context, request *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) {
resp, err := s.observatory.GetObservation(ctx)
if err != nil {
return nil, err
}
retdata := resp.(*observatory.ObservationResult)
return &GetOutboundStatusResponse{
Status: retdata,
}, nil
}
func (s *service) Register(server *grpc.Server) {
RegisterObservatoryServiceServer(server, s)
}
func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
s := core.MustFromContext(ctx)
sv := &service{v: s}
err := s.RequireFeatures(func(Observatory extension.Observatory) {
sv.observatory = Observatory
})
if err != nil {
return nil, err
}
return sv, nil
}))
}

View File

@@ -0,0 +1,278 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.18.0
// source: app/observatory/command/command.proto
package command
import (
observatory "github.com/xtls/xray-core/app/observatory"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type GetOutboundStatusRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *GetOutboundStatusRequest) Reset() {
*x = GetOutboundStatusRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_command_command_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetOutboundStatusRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetOutboundStatusRequest) ProtoMessage() {}
func (x *GetOutboundStatusRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_command_command_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetOutboundStatusRequest.ProtoReflect.Descriptor instead.
func (*GetOutboundStatusRequest) Descriptor() ([]byte, []int) {
return file_app_observatory_command_command_proto_rawDescGZIP(), []int{0}
}
type GetOutboundStatusResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Status *observatory.ObservationResult `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
}
func (x *GetOutboundStatusResponse) Reset() {
*x = GetOutboundStatusResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_command_command_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetOutboundStatusResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetOutboundStatusResponse) ProtoMessage() {}
func (x *GetOutboundStatusResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_command_command_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetOutboundStatusResponse.ProtoReflect.Descriptor instead.
func (*GetOutboundStatusResponse) Descriptor() ([]byte, []int) {
return file_app_observatory_command_command_proto_rawDescGZIP(), []int{1}
}
func (x *GetOutboundStatusResponse) GetStatus() *observatory.ObservationResult {
if x != nil {
return x.Status
}
return nil
}
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Config) Reset() {
*x = Config{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_command_command_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Config) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_command_command_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_app_observatory_command_command_proto_rawDescGZIP(), []int{2}
}
var File_app_observatory_command_command_proto protoreflect.FileDescriptor
var file_app_observatory_command_command_proto_rawDesc = []byte{
0x0a, 0x25, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
0x79, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
0x72, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x1c, 0x61, 0x70, 0x70, 0x2f,
0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x4f,
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x22, 0x61, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x44, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x4f, 0x62,
0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52,
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x32, 0xa7, 0x01, 0x0a, 0x12, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x90, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74,
0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3b,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f,
0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65,
0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x80, 0x01, 0x0a, 0x25,
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
0x72, 0x79, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x21, 0x58, 0x72, 0x61,
0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72,
0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_app_observatory_command_command_proto_rawDescOnce sync.Once
file_app_observatory_command_command_proto_rawDescData = file_app_observatory_command_command_proto_rawDesc
)
func file_app_observatory_command_command_proto_rawDescGZIP() []byte {
file_app_observatory_command_command_proto_rawDescOnce.Do(func() {
file_app_observatory_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_observatory_command_command_proto_rawDescData)
})
return file_app_observatory_command_command_proto_rawDescData
}
var file_app_observatory_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_app_observatory_command_command_proto_goTypes = []interface{}{
(*GetOutboundStatusRequest)(nil), // 0: xray.core.app.observatory.command.GetOutboundStatusRequest
(*GetOutboundStatusResponse)(nil), // 1: xray.core.app.observatory.command.GetOutboundStatusResponse
(*Config)(nil), // 2: xray.core.app.observatory.command.Config
(*observatory.ObservationResult)(nil), // 3: xray.core.app.observatory.ObservationResult
}
var file_app_observatory_command_command_proto_depIdxs = []int32{
3, // 0: xray.core.app.observatory.command.GetOutboundStatusResponse.status:type_name -> xray.core.app.observatory.ObservationResult
0, // 1: xray.core.app.observatory.command.ObservatoryService.GetOutboundStatus:input_type -> xray.core.app.observatory.command.GetOutboundStatusRequest
1, // 2: xray.core.app.observatory.command.ObservatoryService.GetOutboundStatus:output_type -> xray.core.app.observatory.command.GetOutboundStatusResponse
2, // [2:3] is the sub-list for method output_type
1, // [1:2] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_app_observatory_command_command_proto_init() }
func file_app_observatory_command_command_proto_init() {
if File_app_observatory_command_command_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_app_observatory_command_command_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetOutboundStatusRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_command_command_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetOutboundStatusResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_command_command_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_observatory_command_command_proto_rawDesc,
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_app_observatory_command_command_proto_goTypes,
DependencyIndexes: file_app_observatory_command_command_proto_depIdxs,
MessageInfos: file_app_observatory_command_command_proto_msgTypes,
}.Build()
File_app_observatory_command_command_proto = out.File
file_app_observatory_command_command_proto_rawDesc = nil
file_app_observatory_command_command_proto_goTypes = nil
file_app_observatory_command_command_proto_depIdxs = nil
}

View File

@@ -0,0 +1,24 @@
syntax = "proto3";
package xray.core.app.observatory.command;
option csharp_namespace = "Xray.Core.App.Observatory.Command";
option go_package = "github.com/xtls/xray-core/app/observatory/command";
option java_package = "com.xray.core.app.observatory.command";
option java_multiple_files = true;
import "app/observatory/config.proto";
message GetOutboundStatusRequest {
}
message GetOutboundStatusResponse {
xray.core.app.observatory.ObservationResult status = 1;
}
service ObservatoryService {
rpc GetOutboundStatus(GetOutboundStatusRequest)
returns (GetOutboundStatusResponse) {}
}
message Config {}

View File

@@ -0,0 +1,101 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package command
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// ObservatoryServiceClient is the client API for ObservatoryService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type ObservatoryServiceClient interface {
GetOutboundStatus(ctx context.Context, in *GetOutboundStatusRequest, opts ...grpc.CallOption) (*GetOutboundStatusResponse, error)
}
type observatoryServiceClient struct {
cc grpc.ClientConnInterface
}
func NewObservatoryServiceClient(cc grpc.ClientConnInterface) ObservatoryServiceClient {
return &observatoryServiceClient{cc}
}
func (c *observatoryServiceClient) GetOutboundStatus(ctx context.Context, in *GetOutboundStatusRequest, opts ...grpc.CallOption) (*GetOutboundStatusResponse, error) {
out := new(GetOutboundStatusResponse)
err := c.cc.Invoke(ctx, "/xray.core.app.observatory.command.ObservatoryService/GetOutboundStatus", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ObservatoryServiceServer is the server API for ObservatoryService service.
// All implementations must embed UnimplementedObservatoryServiceServer
// for forward compatibility
type ObservatoryServiceServer interface {
GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error)
mustEmbedUnimplementedObservatoryServiceServer()
}
// UnimplementedObservatoryServiceServer must be embedded to have forward compatible implementations.
type UnimplementedObservatoryServiceServer struct {
}
func (UnimplementedObservatoryServiceServer) GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOutboundStatus not implemented")
}
func (UnimplementedObservatoryServiceServer) mustEmbedUnimplementedObservatoryServiceServer() {}
// UnsafeObservatoryServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ObservatoryServiceServer will
// result in compilation errors.
type UnsafeObservatoryServiceServer interface {
mustEmbedUnimplementedObservatoryServiceServer()
}
func RegisterObservatoryServiceServer(s grpc.ServiceRegistrar, srv ObservatoryServiceServer) {
s.RegisterService(&ObservatoryService_ServiceDesc, srv)
}
func _ObservatoryService_GetOutboundStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetOutboundStatusRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ObservatoryServiceServer).GetOutboundStatus(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/xray.core.app.observatory.command.ObservatoryService/GetOutboundStatus",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ObservatoryServiceServer).GetOutboundStatus(ctx, req.(*GetOutboundStatusRequest))
}
return interceptor(ctx, in, info, handler)
}
// ObservatoryService_ServiceDesc is the grpc.ServiceDesc for ObservatoryService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ObservatoryService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "xray.core.app.observatory.command.ObservatoryService",
HandlerType: (*ObservatoryServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetOutboundStatus",
Handler: _ObservatoryService_GetOutboundStatus_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "app/observatory/command/command.proto",
}

View File

@@ -2,7 +2,6 @@ package observatory
import ( import (
"context" "context"
"github.com/xtls/xray-core/core"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
@@ -17,6 +16,7 @@ import (
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
"github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/common/task"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/transport/internet/tagged" "github.com/xtls/xray-core/transport/internet/tagged"
@@ -66,22 +66,45 @@ func (o *Observer) background() {
} }
outbounds := hs.Select(o.config.SubjectSelector) outbounds := hs.Select(o.config.SubjectSelector)
sort.Strings(outbounds)
o.updateStatus(outbounds) o.updateStatus(outbounds)
sleepTime := time.Second * 10
if o.config.ProbeInterval != 0 {
sleepTime = time.Duration(o.config.ProbeInterval)
}
if !o.config.EnableConcurrency {
sort.Strings(outbounds)
for _, v := range outbounds {
result := o.probe(v)
o.updateStatusForResult(v, &result)
if o.finished.Done() {
return
}
time.Sleep(sleepTime)
}
continue
}
ch := make(chan struct{}, len(outbounds))
for _, v := range outbounds { for _, v := range outbounds {
result := o.probe(v) go func(v string) {
o.updateStatusForResult(v, &result) result := o.probe(v)
if o.finished.Done() { o.updateStatusForResult(v, &result)
ch <- struct{}{}
}(v)
}
for range outbounds {
select {
case <-ch:
case <-o.finished.Wait():
return return
} }
sleepTime := time.Second * 10
if o.config.ProbeInterval != 0 {
sleepTime = time.Duration(o.config.ProbeInterval)
}
time.Sleep(sleepTime)
} }
time.Sleep(sleepTime)
} }
} }
@@ -102,7 +125,7 @@ func (o *Observer) probe(outbound string) ProbeResult {
DialContext: func(ctx context.Context, network string, addr string) (net.Conn, error) { DialContext: func(ctx context.Context, network string, addr string) (net.Conn, error) {
var connection net.Conn var connection net.Conn
taskErr := task.Run(ctx, func() error { taskErr := task.Run(ctx, func() error {
// MUST use V2Fly's built in context system // MUST use Xray's built in context system
dest, err := v2net.ParseDestination(network + ":" + addr) dest, err := v2net.ParseDestination(network + ":" + addr)
if err != nil { if err != nil {
return newError("cannot understand address").Base(err) return newError("cannot understand address").Base(err)
@@ -133,7 +156,7 @@ func (o *Observer) probe(outbound string) ProbeResult {
var GETTime time.Duration var GETTime time.Duration
err := task.Run(o.ctx, func() error { err := task.Run(o.ctx, func() error {
startTime := time.Now() startTime := time.Now()
probeURL := "https://api.v2fly.org/checkConnection.svgz" probeURL := "https://www.google.com/generate_204"
if o.config.ProbeUrl != "" { if o.config.ProbeUrl != "" {
probeURL = o.config.ProbeUrl probeURL = o.config.ProbeUrl
} }

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.27.1 // protoc-gen-go v1.27.1
// protoc v3.18.0 // protoc v3.19.1
// source: app/proxyman/config.proto // source: app/proxyman/config.proto
package proxyman package proxyman
@@ -238,7 +238,8 @@ type SniffingConfig struct {
DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"` DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
DomainsExcluded []string `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"` DomainsExcluded []string `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"`
// Whether should only try to sniff metadata without waiting for client input. // Whether should only try to sniff metadata without waiting for client input.
// Can be used to support SMTP like protocol where server send the first message. // Can be used to support SMTP like protocol where server send the first
// message.
MetadataOnly bool `protobuf:"varint,4,opt,name=metadata_only,json=metadataOnly,proto3" json:"metadata_only,omitempty"` MetadataOnly bool `protobuf:"varint,4,opt,name=metadata_only,json=metadataOnly,proto3" json:"metadata_only,omitempty"`
RouteOnly bool `protobuf:"varint,5,opt,name=route_only,json=routeOnly,proto3" json:"route_only,omitempty"` RouteOnly bool `protobuf:"varint,5,opt,name=route_only,json=routeOnly,proto3" json:"route_only,omitempty"`
} }
@@ -315,8 +316,8 @@ type ReceiverConfig struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// PortRange specifies the ports which the Receiver should listen on. // PortList specifies the ports which the Receiver should listen on.
PortRange *net.PortRange `protobuf:"bytes,1,opt,name=port_range,json=portRange,proto3" json:"port_range,omitempty"` PortList *net.PortList `protobuf:"bytes,1,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
// Listen specifies the IP address that the Receiver should listen on. // Listen specifies the IP address that the Receiver should listen on.
Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"` Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"` AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"`
@@ -362,9 +363,9 @@ func (*ReceiverConfig) Descriptor() ([]byte, []int) {
return file_app_proxyman_config_proto_rawDescGZIP(), []int{3} return file_app_proxyman_config_proto_rawDescGZIP(), []int{3}
} }
func (x *ReceiverConfig) GetPortRange() *net.PortRange { func (x *ReceiverConfig) GetPortList() *net.PortList {
if x != nil { if x != nil {
return x.PortRange return x.PortList
} }
return nil return nil
} }
@@ -790,86 +791,86 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f, 0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f,
0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65,
0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x8d, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f,
0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61,
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72,
0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12,
0x67, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69,
0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f,
0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4e, 0x0a, 0x0f,
0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69,
0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72,
0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72,
0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b,
0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18,
0x01, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
0x65, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65,
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73,
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69,
0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52,
0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54,
0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75,
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a,
0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a,
0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f,
0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f,
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74,
0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c,
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69,
0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e,
0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b, 0x6e, 0x6f, 0x77,
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e,
0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4e,
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
0x50, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e,
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e,
0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a,
0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12,
0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61,
0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e,
0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65,
0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47,
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
0x72, 0x6f, 0x74, 0x6f, 0x33, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65,
0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53,
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a, 0x0c, 0x53, 0x65,
0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69,
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f,
0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61,
0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78,
0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65,
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78,
0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69,
0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x50, 0x0a, 0x12,
0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b,
0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2a, 0x23,
0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73,
0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x4c,
0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72,
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
} }
var ( var (
@@ -899,7 +900,7 @@ var file_app_proxyman_config_proto_goTypes = []interface{}{
(*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig (*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency (*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh (*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
(*net.PortRange)(nil), // 12: xray.common.net.PortRange (*net.PortList)(nil), // 12: xray.common.net.PortList
(*net.IPOrDomain)(nil), // 13: xray.common.net.IPOrDomain (*net.IPOrDomain)(nil), // 13: xray.common.net.IPOrDomain
(*internet.StreamConfig)(nil), // 14: xray.transport.internet.StreamConfig (*internet.StreamConfig)(nil), // 14: xray.transport.internet.StreamConfig
(*serial.TypedMessage)(nil), // 15: xray.common.serial.TypedMessage (*serial.TypedMessage)(nil), // 15: xray.common.serial.TypedMessage
@@ -909,7 +910,7 @@ var file_app_proxyman_config_proto_depIdxs = []int32{
1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type 1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency 10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh 11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
12, // 3: xray.app.proxyman.ReceiverConfig.port_range:type_name -> xray.common.net.PortRange 12, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain 13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
3, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy 3, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig 14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig

View File

@@ -27,17 +27,13 @@ message AllocationStrategy {
Type type = 1; Type type = 1;
message AllocationStrategyConcurrency { message AllocationStrategyConcurrency { uint32 value = 1; }
uint32 value = 1;
}
// Number of handlers (ports) running in parallel. // Number of handlers (ports) running in parallel.
// Default value is 3 if unset. // Default value is 3 if unset.
AllocationStrategyConcurrency concurrency = 2; AllocationStrategyConcurrency concurrency = 2;
message AllocationStrategyRefresh { message AllocationStrategyRefresh { uint32 value = 1; }
uint32 value = 1;
}
// Number of minutes before a handler is regenerated. // Number of minutes before a handler is regenerated.
// Default value is 5 if unset. // Default value is 5 if unset.
@@ -59,15 +55,16 @@ message SniffingConfig {
repeated string domains_excluded = 3; repeated string domains_excluded = 3;
// Whether should only try to sniff metadata without waiting for client input. // Whether should only try to sniff metadata without waiting for client input.
// Can be used to support SMTP like protocol where server send the first message. // Can be used to support SMTP like protocol where server send the first
// message.
bool metadata_only = 4; bool metadata_only = 4;
bool route_only = 5; bool route_only = 5;
} }
message ReceiverConfig { message ReceiverConfig {
// PortRange specifies the ports which the Receiver should listen on. // PortList specifies the ports which the Receiver should listen on.
xray.common.net.PortRange port_range = 1; xray.common.net.PortList port_list = 1;
// Listen specifies the IP address that the Receiver should listen on. // Listen specifies the IP address that the Receiver should listen on.
xray.common.net.IPOrDomain listen = 2; xray.common.net.IPOrDomain listen = 2;
AllocationStrategy allocation_strategy = 3; AllocationStrategy allocation_strategy = 3;
@@ -76,7 +73,7 @@ message ReceiverConfig {
reserved 6; reserved 6;
// Override domains for the given protocol. // Override domains for the given protocol.
// Deprecated. Use sniffing_settings. // Deprecated. Use sniffing_settings.
repeated KnownProtocols domain_override = 7 [deprecated = true]; repeated KnownProtocols domain_override = 7 [ deprecated = true ];
SniffingConfig sniffing_settings = 8; SniffingConfig sniffing_settings = 8;
} }

View File

@@ -67,7 +67,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag) uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag)
nl := p.Network() nl := p.Network()
pr := receiverConfig.PortRange pl := receiverConfig.PortList
address := receiverConfig.Listen.AsAddress() address := receiverConfig.Listen.AsAddress()
if address == nil { if address == nil {
address = net.AnyIP address = net.AnyIP
@@ -87,7 +87,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
} }
mss.SocketSettings.ReceiveOriginalDestAddress = true mss.SocketSettings.ReceiveOriginalDestAddress = true
} }
if pr == nil { if pl == nil {
if net.HasNetwork(nl, net.Network_UNIX) { if net.HasNetwork(nl, net.Network_UNIX) {
newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog() newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog()
@@ -105,43 +105,46 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
h.workers = append(h.workers, worker) h.workers = append(h.workers, worker)
} }
} }
if pr != nil { if pl != nil {
for port := pr.From; port <= pr.To; port++ { for _, pr := range pl.Range {
if net.HasNetwork(nl, net.Network_TCP) { for port := pr.From; port <= pr.To; port++ {
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog() if net.HasNetwork(nl, net.Network_TCP) {
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
worker := &tcpWorker{ worker := &tcpWorker{
address: address, address: address,
port: net.Port(port), port: net.Port(port),
proxy: p, proxy: p,
stream: mss, stream: mss,
recvOrigDest: receiverConfig.ReceiveOriginalDestination, recvOrigDest: receiverConfig.ReceiveOriginalDestination,
tag: tag, tag: tag,
dispatcher: h.mux, dispatcher: h.mux,
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(), sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
uplinkCounter: uplinkCounter, uplinkCounter: uplinkCounter,
downlinkCounter: downlinkCounter, downlinkCounter: downlinkCounter,
ctx: ctx, ctx: ctx,
}
h.workers = append(h.workers, worker)
} }
h.workers = append(h.workers, worker)
}
if net.HasNetwork(nl, net.Network_UDP) { if net.HasNetwork(nl, net.Network_UDP) {
worker := &udpWorker{ worker := &udpWorker{
tag: tag, tag: tag,
proxy: p, proxy: p,
address: address, address: address,
port: net.Port(port), port: net.Port(port),
dispatcher: h.mux, dispatcher: h.mux,
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(), sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
uplinkCounter: uplinkCounter, uplinkCounter: uplinkCounter,
downlinkCounter: downlinkCounter, downlinkCounter: downlinkCounter,
stream: mss, stream: mss,
ctx: ctx, ctx: ctx,
}
h.workers = append(h.workers, worker)
} }
h.workers = append(h.workers, worker)
} }
} }
} }
return h, nil return h, nil

View File

@@ -69,21 +69,25 @@ func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *p
} }
func (h *DynamicInboundHandler) allocatePort() net.Port { func (h *DynamicInboundHandler) allocatePort() net.Port {
from := int(h.receiverConfig.PortRange.From) allPorts := []int32{}
delta := int(h.receiverConfig.PortRange.To) - from + 1 for _, pr := range h.receiverConfig.PortList.Range {
for i := pr.From; i <= pr.To; i++ {
allPorts = append(allPorts, int32(i))
}
}
h.portMutex.Lock() h.portMutex.Lock()
defer h.portMutex.Unlock() defer h.portMutex.Unlock()
for { for {
r := dice.Roll(delta) r := dice.Roll(len(allPorts))
port := net.Port(from + r) port := net.Port(allPorts[r])
_, used := h.portsInUse[port] _, used := h.portsInUse[port]
if !used { if !used {
h.portsInUse[port] = true h.portsInUse[port] = true
return port return port
} }
} }
} }
func (h *DynamicInboundHandler) closeWorkers(workers []worker) { func (h *DynamicInboundHandler) closeWorkers(workers []worker) {

View File

@@ -6,8 +6,6 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
@@ -20,6 +18,7 @@ import (
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/proxy" "github.com/xtls/xray-core/proxy"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tcp" "github.com/xtls/xray-core/transport/internet/tcp"
"github.com/xtls/xray-core/transport/internet/udp" "github.com/xtls/xray-core/transport/internet/udp"
"github.com/xtls/xray-core/transport/pipe" "github.com/xtls/xray-core/transport/pipe"

View File

@@ -3,8 +3,6 @@ package outbound
import ( import (
"context" "context"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/mux" "github.com/xtls/xray-core/common/mux"
@@ -18,6 +16,7 @@ import (
"github.com/xtls/xray-core/proxy" "github.com/xtls/xray-core/proxy"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/pipe" "github.com/xtls/xray-core/transport/pipe"
) )
@@ -59,7 +58,7 @@ type Handler struct {
downlinkCounter stats.Counter downlinkCounter stats.Counter
} }
// NewHandler create a new Handler based on the given configuration. // NewHandler creates a new Handler based on the given configuration.
func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbound.Handler, error) { func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbound.Handler, error) {
v := core.MustFromContext(ctx) v := core.MustFromContext(ctx)
uplinkCounter, downlinkCounter := getStatCounter(v, config.Tag) uplinkCounter, downlinkCounter := getStatCounter(v, config.Tag)
@@ -136,13 +135,17 @@ func (h *Handler) Tag() string {
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) { func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
if h.mux != nil && (h.mux.Enabled || session.MuxPreferedFromContext(ctx)) { if h.mux != nil && (h.mux.Enabled || session.MuxPreferedFromContext(ctx)) {
if err := h.mux.Dispatch(ctx, link); err != nil { if err := h.mux.Dispatch(ctx, link); err != nil {
newError("failed to process mux outbound traffic").Base(err).WriteToLog(session.ExportIDToError(ctx)) err := newError("failed to process mux outbound traffic").Base(err)
session.SubmitOutboundErrorToOriginator(ctx, err)
err.WriteToLog(session.ExportIDToError(ctx))
common.Interrupt(link.Writer) common.Interrupt(link.Writer)
} }
} else { } else {
if err := h.proxy.Process(ctx, link, h); err != nil { if err := h.proxy.Process(ctx, link, h); err != nil {
// Ensure outbound ray is properly closed. // Ensure outbound ray is properly closed.
newError("failed to process outbound traffic").Base(err).WriteToLog(session.ExportIDToError(ctx)) err := newError("failed to process outbound traffic").Base(err)
session.SubmitOutboundErrorToOriginator(ctx, err)
err.WriteToLog(session.ExportIDToError(ctx))
common.Interrupt(link.Writer) common.Interrupt(link.Writer)
} else { } else {
common.Must(common.Close(link.Writer)) common.Must(common.Close(link.Writer))

View File

@@ -4,8 +4,6 @@ import (
"context" "context"
"testing" "testing"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/app/policy" "github.com/xtls/xray-core/app/policy"
. "github.com/xtls/xray-core/app/proxyman/outbound" . "github.com/xtls/xray-core/app/proxyman/outbound"
"github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/app/stats"
@@ -14,6 +12,7 @@ import (
core "github.com/xtls/xray-core/core" core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/proxy/freedom" "github.com/xtls/xray-core/proxy/freedom"
"github.com/xtls/xray-core/transport/internet/stat"
) )
func TestInterfaces(t *testing.T) { func TestInterfaces(t *testing.T) {

View File

@@ -284,7 +284,7 @@ func TestSerivceTestRoute(t *testing.T) {
r := new(router.Router) r := new(router.Router)
mockCtl := gomock.NewController(t) mockCtl := gomock.NewController(t)
defer mockCtl.Finish() defer mockCtl.Finish()
common.Must(r.Init(&router.Config{ common.Must(r.Init(context.TODO(), &router.Config{
Rule: []*router.RoutingRule{ Rule: []*router.RoutingRule{
{ {
InboundTag: []string{"in"}, InboundTag: []string{"in"},

View File

@@ -158,9 +158,21 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
} }
func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) { func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) {
return &Balancer{ switch br.Strategy {
selectors: br.OutboundSelector, case "leastPing":
strategy: &RandomStrategy{}, return &Balancer{
ohm: ohm, selectors: br.OutboundSelector,
}, nil strategy: &LeastPingStrategy{},
ohm: ohm,
}, nil
case "random":
fallthrough
default:
return &Balancer{
selectors: br.OutboundSelector,
strategy: &RandomStrategy{},
ohm: ohm,
}, nil
}
} }

View File

@@ -29,7 +29,7 @@ type Route struct {
} }
// Init initializes the Router. // Init initializes the Router.
func (r *Router) Init(config *Config, d dns.Client, ohm outbound.Manager) error { func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm outbound.Manager) error {
r.domainStrategy = config.DomainStrategy r.domainStrategy = config.DomainStrategy
r.dns = d r.dns = d
@@ -39,6 +39,7 @@ func (r *Router) Init(config *Config, d dns.Client, ohm outbound.Manager) error
if err != nil { if err != nil {
return err return err
} }
balancer.InjectContext(ctx)
r.balancers[rule.Tag] = balancer r.balancers[rule.Tag] = balancer
} }
@@ -121,7 +122,7 @@ func (*Router) Close() error {
return nil return nil
} }
// Type implement common.HasType. // Type implements common.HasType.
func (*Router) Type() interface{} { func (*Router) Type() interface{} {
return routing.RouterType() return routing.RouterType()
} }
@@ -140,7 +141,7 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
r := new(Router) r := new(Router)
if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager) error { if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager) error {
return r.Init(config.(*Config), d, ohm) return r.Init(ctx, config.(*Config), d, ohm)
}); err != nil { }); err != nil {
return nil, err return nil, err
} }

View File

@@ -4,14 +4,13 @@ import (
"context" "context"
"testing" "testing"
"github.com/xtls/xray-core/features/dns"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
. "github.com/xtls/xray-core/app/router" . "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
routing_session "github.com/xtls/xray-core/features/routing/session" routing_session "github.com/xtls/xray-core/features/routing/session"
"github.com/xtls/xray-core/testing/mocks" "github.com/xtls/xray-core/testing/mocks"
@@ -42,7 +41,7 @@ func TestSimpleRouter(t *testing.T) {
mockHs := mocks.NewOutboundHandlerSelector(mockCtl) mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
r := new(Router) r := new(Router)
common.Must(r.Init(config, mockDNS, &mockOutboundManager{ common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
Manager: mockOhm, Manager: mockOhm,
HandlerSelector: mockHs, HandlerSelector: mockHs,
})) }))
@@ -83,7 +82,7 @@ func TestSimpleBalancer(t *testing.T) {
mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test"}) mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test"})
r := new(Router) r := new(Router)
common.Must(r.Init(config, mockDNS, &mockOutboundManager{ common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
Manager: mockOhm, Manager: mockOhm,
HandlerSelector: mockHs, HandlerSelector: mockHs,
})) }))
@@ -125,7 +124,7 @@ func TestIPOnDemand(t *testing.T) {
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes() }).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
r := new(Router) r := new(Router)
common.Must(r.Init(config, mockDNS, nil)) common.Must(r.Init(context.TODO(), config, mockDNS, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)}) ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
@@ -164,7 +163,7 @@ func TestIPIfNonMatchDomain(t *testing.T) {
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes() }).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
r := new(Router) r := new(Router)
common.Must(r.Init(config, mockDNS, nil)) common.Must(r.Init(context.TODO(), config, mockDNS, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)}) ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
@@ -198,7 +197,7 @@ func TestIPIfNonMatchIP(t *testing.T) {
mockDNS := mocks.NewDNSClient(mockCtl) mockDNS := mocks.NewDNSClient(mockCtl)
r := new(Router) r := new(Router)
common.Must(r.Init(config, mockDNS, nil)) common.Must(r.Init(context.TODO(), config, mockDNS, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.LocalHostIP, 80)}) ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.LocalHostIP, 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))

View File

@@ -2,10 +2,10 @@ package router
import ( import (
"context" "context"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
) )
@@ -15,14 +15,17 @@ type LeastPingStrategy struct {
} }
func (l *LeastPingStrategy) InjectContext(ctx context.Context) { func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
common.Must(core.RequireFeatures(ctx, func(observatory extension.Observatory) error {
l.observatory = observatory
return nil
}))
l.ctx = ctx l.ctx = ctx
} }
func (l *LeastPingStrategy) PickOutbound(strings []string) string { func (l *LeastPingStrategy) PickOutbound(strings []string) string {
if l.observatory == nil {
common.Must(core.RequireFeatures(l.ctx, func(observatory extension.Observatory) error {
l.observatory = observatory
return nil
}))
}
observeReport, err := l.observatory.GetObservation(l.ctx) observeReport, err := l.observatory.GetObservation(l.ctx)
if err != nil { if err != nil {
newError("cannot get observe report").Base(err).WriteToLog() newError("cannot get observe report").Base(err).WriteToLog()
@@ -36,6 +39,7 @@ func (l *LeastPingStrategy) PickOutbound(strings []string) string {
for _, v := range status { for _, v := range status {
if outboundsList.contains(v.OutboundTag) && v.Alive && v.Delay < leastPing { if outboundsList.contains(v.OutboundTag) && v.Alive && v.Delay < leastPing {
selectedOutboundName = v.OutboundTag selectedOutboundName = v.OutboundTag
leastPing = v.Delay
} }
} }
return selectedOutboundName return selectedOutboundName

View File

@@ -9,7 +9,7 @@ import (
const replayFilterCapacity = 100000 const replayFilterCapacity = 100000
// ReplayFilter check for replay attacks. // ReplayFilter checks for replay attacks.
type ReplayFilter struct { type ReplayFilter struct {
lock sync.Mutex lock sync.Mutex
poolA *cuckoo.Filter poolA *cuckoo.Filter
@@ -31,7 +31,7 @@ func (filter *ReplayFilter) Interval() int64 {
return filter.interval return filter.interval
} }
// Check determine if there are duplicate records. // Check determines if there are duplicate records.
func (filter *ReplayFilter) Check(sum []byte) bool { func (filter *ReplayFilter) Check(sum []byte) bool {
filter.lock.Lock() filter.lock.Lock()
defer filter.lock.Unlock() defer filter.lock.Unlock()

View File

@@ -53,7 +53,7 @@ func MergeBytes(dest MultiBuffer, src []byte) MultiBuffer {
return dest return dest
} }
// ReleaseMulti release all content of the MultiBuffer, and returns an empty MultiBuffer. // ReleaseMulti releases all content of the MultiBuffer, and returns an empty MultiBuffer.
func ReleaseMulti(mb MultiBuffer) MultiBuffer { func ReleaseMulti(mb MultiBuffer) MultiBuffer {
for i := range mb { for i := range mb {
mb[i].Release() mb[i].Release()
@@ -235,7 +235,7 @@ func (mb MultiBuffer) Len() int32 {
return size return size
} }
// IsEmpty return true if the MultiBuffer has no content. // IsEmpty returns true if the MultiBuffer has no content.
func (mb MultiBuffer) IsEmpty() bool { func (mb MultiBuffer) IsEmpty() bool {
for _, b := range mb { for _, b := range mb {
if !b.IsEmpty() { if !b.IsEmpty() {
@@ -283,14 +283,14 @@ func (c *MultiBufferContainer) Write(b []byte) (int, error) {
return len(b), nil return len(b), nil
} }
// WriteMultiBuffer implement Writer. // WriteMultiBuffer implements Writer.
func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error { func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error {
mb, _ := MergeMulti(c.MultiBuffer, b) mb, _ := MergeMulti(c.MultiBuffer, b)
c.MultiBuffer = mb c.MultiBuffer = mb
return nil return nil
} }
// Close implement io.Closer. // Close implements io.Closer.
func (c *MultiBufferContainer) Close() error { func (c *MultiBufferContainer) Close() error {
c.MultiBuffer = ReleaseMulti(c.MultiBuffer) c.MultiBuffer = ReleaseMulti(c.MultiBuffer)
return nil return nil

View File

@@ -7,9 +7,8 @@ import (
"io" "io"
"syscall" "syscall"
"github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/common/platform" "github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/features/stats"
) )
type allocStrategy struct { type allocStrategy struct {

View File

@@ -9,7 +9,6 @@ import (
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"

View File

@@ -5,10 +5,9 @@ import (
"net" "net"
"sync" "sync"
"github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/features/stats"
) )
// BufferToBytesWriter is a Writer that writes alloc.Buffer into underlying writer. // BufferToBytesWriter is a Writer that writes alloc.Buffer into underlying writer.

2
common/cache/lru.go vendored
View File

@@ -26,7 +26,7 @@ type lruElement struct {
value interface{} value interface{}
} }
// NewLru init a lru cache // NewLru initializes a lru cache
func NewLru(cap int) Lru { func NewLru(cap int) Lru {
return &lru{ return &lru{
capacity: cap, capacity: cap,

View File

@@ -39,10 +39,6 @@ func GenerateIncreasingNonce(nonce []byte) BytesGenerator {
} }
} }
func GenerateInitialAEADNonce() BytesGenerator {
return GenerateIncreasingNonce([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
}
func GenerateAEADNonceWithSize(nonceSize int) BytesGenerator { func GenerateAEADNonceWithSize(nonceSize int) BytesGenerator {
c := make([]byte, nonceSize) c := make([]byte, nonceSize)
for i := 0; i < nonceSize; i++ { for i := 0; i < nonceSize; i++ {

10
common/drain/drain.go Normal file
View File

@@ -0,0 +1,10 @@
package drain
import "io"
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
type Drainer interface {
AcknowledgeReceive(size int)
Drain(reader io.Reader) error
}

62
common/drain/drainer.go Normal file
View File

@@ -0,0 +1,62 @@
package drain
import (
"io"
"io/ioutil"
"github.com/xtls/xray-core/common/dice"
)
type BehaviorSeedLimitedDrainer struct {
DrainSize int
}
func NewBehaviorSeedLimitedDrainer(behaviorSeed int64, drainFoundation, maxBaseDrainSize, maxRandDrain int) (Drainer, error) {
behaviorRand := dice.NewDeterministicDice(behaviorSeed)
BaseDrainSize := behaviorRand.Roll(maxBaseDrainSize)
RandDrainMax := behaviorRand.Roll(maxRandDrain) + 1
RandDrainRolled := dice.Roll(RandDrainMax)
DrainSize := drainFoundation + BaseDrainSize + RandDrainRolled
return &BehaviorSeedLimitedDrainer{DrainSize: DrainSize}, nil
}
func (d *BehaviorSeedLimitedDrainer) AcknowledgeReceive(size int) {
d.DrainSize -= size
}
func (d *BehaviorSeedLimitedDrainer) Drain(reader io.Reader) error {
if d.DrainSize > 0 {
err := drainReadN(reader, d.DrainSize)
if err == nil {
return newError("drained connection")
}
return newError("unable to drain connection").Base(err)
}
return nil
}
func drainReadN(reader io.Reader, n int) error {
_, err := io.CopyN(ioutil.Discard, reader, int64(n))
return err
}
func WithError(drainer Drainer, reader io.Reader, err error) error {
drainErr := drainer.Drain(reader)
if drainErr == nil {
return err
}
return newError(drainErr).Base(err)
}
type NopDrainer struct{}
func (n NopDrainer) AcknowledgeReceive(size int) {
}
func (n NopDrainer) Drain(reader io.Reader) error {
return nil
}
func NewNopDrainer() Drainer {
return &NopDrainer{}
}

View File

@@ -0,0 +1,9 @@
package drain
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View File

@@ -34,7 +34,7 @@ func Record(msg Message) {
var logHandler syncHandler var logHandler syncHandler
// RegisterHandler register a new handler as current log handler. Previous registered handler will be discarded. // RegisterHandler registers a new handler as current log handler. Previous registered handler will be discarded.
func RegisterHandler(handler Handler) { func RegisterHandler(handler Handler) {
if handler == nil { if handler == nil {
panic("Log handler is nil") panic("Log handler is nil")

View File

@@ -22,7 +22,7 @@ func GetToolLocation(file string) string {
return filepath.Join(toolPath, file) return filepath.Join(toolPath, file)
} }
// GetAssetLocation search for `file` in certain locations // GetAssetLocation searches for `file` in certain locations
func GetAssetLocation(file string) string { func GetAssetLocation(file string) string {
const name = "xray.location.asset" const name = "xray.location.asset"
assetPath := NewEnvFlag(name).GetValue(getExecutableDir) assetPath := NewEnvFlag(name).GetValue(getExecutableDir)

View File

@@ -20,7 +20,7 @@ func GetToolLocation(file string) string {
return filepath.Join(toolPath, file+".exe") return filepath.Join(toolPath, file+".exe")
} }
// GetAssetLocation search for `file` in the excutable dir // GetAssetLocation searches for `file` in the excutable dir
func GetAssetLocation(file string) string { func GetAssetLocation(file string) string {
const name = "xray.location.asset" const name = "xray.location.asset"
assetPath := NewEnvFlag(name).GetValue(getExecutableDir) assetPath := NewEnvFlag(name).GetValue(getExecutableDir)

View File

@@ -38,6 +38,8 @@ const (
RequestOptionChunkMasking bitmask.Byte = 0x04 RequestOptionChunkMasking bitmask.Byte = 0x04
RequestOptionGlobalPadding bitmask.Byte = 0x08 RequestOptionGlobalPadding bitmask.Byte = 0x08
RequestOptionAuthenticatedLength bitmask.Byte = 0x10
) )
type RequestHeader struct { type RequestHeader struct {

View File

@@ -22,7 +22,7 @@ func ParseXForwardedFor(header http.Header) []net.Address {
return addrs return addrs
} }
// RemoveHopByHopHeaders remove hop by hop headers in http header list. // RemoveHopByHopHeaders removes hop by hop headers in http header list.
func RemoveHopByHopHeaders(header http.Header) { func RemoveHopByHopHeaders(header http.Header) {
// Strip hop-by-hop header based on RFC: // Strip hop-by-hop header based on RFC:
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1

View File

@@ -17,7 +17,7 @@ type pkcs8 struct {
Version int Version int
Algo pkix.AlgorithmIdentifier Algo pkix.AlgorithmIdentifier
PrivateKey []byte PrivateKey []byte
// optional attributes omitted. // Optional attributes omitted.
} }
type pkcs1AdditionalRSAPrime struct { type pkcs1AdditionalRSAPrime struct {

100
common/units/bytesize.go Normal file
View File

@@ -0,0 +1,100 @@
package units
import (
"errors"
"strconv"
"strings"
"unicode"
)
var (
errInvalidSize = errors.New("invalid size")
errInvalidUnit = errors.New("invalid or unsupported unit")
)
// ByteSize is the size of bytes
type ByteSize uint64
const (
_ = iota
// KB = 1KB
KB ByteSize = 1 << (10 * iota)
// MB = 1MB
MB
// GB = 1GB
GB
// TB = 1TB
TB
// PB = 1PB
PB
// EB = 1EB
EB
)
func (b ByteSize) String() string {
unit := ""
value := float64(0)
switch {
case b == 0:
return "0"
case b < KB:
unit = "B"
value = float64(b)
case b < MB:
unit = "KB"
value = float64(b) / float64(KB)
case b < GB:
unit = "MB"
value = float64(b) / float64(MB)
case b < TB:
unit = "GB"
value = float64(b) / float64(GB)
case b < PB:
unit = "TB"
value = float64(b) / float64(TB)
case b < EB:
unit = "PB"
value = float64(b) / float64(PB)
default:
unit = "EB"
value = float64(b) / float64(EB)
}
result := strconv.FormatFloat(value, 'f', 2, 64)
result = strings.TrimSuffix(result, ".0")
return result + unit
}
// Parse parses ByteSize from string
func (b *ByteSize) Parse(s string) error {
s = strings.TrimSpace(s)
s = strings.ToUpper(s)
i := strings.IndexFunc(s, unicode.IsLetter)
if i == -1 {
return errInvalidUnit
}
bytesString, multiple := s[:i], s[i:]
bytes, err := strconv.ParseFloat(bytesString, 64)
if err != nil || bytes <= 0 {
return errInvalidSize
}
switch multiple {
case "B":
*b = ByteSize(bytes)
case "K", "KB", "KIB":
*b = ByteSize(bytes * float64(KB))
case "M", "MB", "MIB":
*b = ByteSize(bytes * float64(MB))
case "G", "GB", "GIB":
*b = ByteSize(bytes * float64(GB))
case "T", "TB", "TIB":
*b = ByteSize(bytes * float64(TB))
case "P", "PB", "PIB":
*b = ByteSize(bytes * float64(PB))
case "E", "EB", "EIB":
*b = ByteSize(bytes * float64(EB))
default:
return errInvalidUnit
}
return nil
}

View File

@@ -0,0 +1,66 @@
package units_test
import (
"testing"
"github.com/xtls/xray-core/common/units"
)
func TestByteSizes(t *testing.T) {
size := units.ByteSize(0)
assertSizeString(t, size, "0")
size++
assertSizeValue(t,
assertSizeString(t, size, "1.00B"),
size,
)
size <<= 10
assertSizeValue(t,
assertSizeString(t, size, "1.00KB"),
size,
)
size <<= 10
assertSizeValue(t,
assertSizeString(t, size, "1.00MB"),
size,
)
size <<= 10
assertSizeValue(t,
assertSizeString(t, size, "1.00GB"),
size,
)
size <<= 10
assertSizeValue(t,
assertSizeString(t, size, "1.00TB"),
size,
)
size <<= 10
assertSizeValue(t,
assertSizeString(t, size, "1.00PB"),
size,
)
size <<= 10
assertSizeValue(t,
assertSizeString(t, size, "1.00EB"),
size,
)
}
func assertSizeValue(t *testing.T, size string, expected units.ByteSize) {
actual := units.ByteSize(0)
err := actual.Parse(size)
if err != nil {
t.Error(err)
}
if actual != expected {
t.Errorf("expect %s, but got %s", expected, actual)
}
}
func assertSizeString(t *testing.T, size units.ByteSize, expected string) string {
actual := size.String()
if actual != expected {
t.Errorf("expect %s, but got %s", expected, actual)
}
return expected
}

View File

@@ -18,7 +18,7 @@ import (
) )
var ( var (
version = "1.5.0" version = "1.5.3"
build = "Custom" build = "Custom"
codename = "Xray, Penetrates Everything." codename = "Xray, Penetrates Everything."
intro = "A unified platform for anti-censorship." intro = "A unified platform for anti-censorship."

View File

@@ -49,8 +49,10 @@ func TestXrayClose(t *testing.T) {
Inbound: []*InboundHandlerConfig{ Inbound: []*InboundHandlerConfig{
{ {
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(port), PortList: &net.PortList{
Listen: net.NewIPOrDomain(net.LocalHostIP), Range: []*net.PortRange{net.SinglePortRange(port)},
},
Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(net.LocalHostIP), Address: net.NewIPOrDomain(net.LocalHostIP),

26
go.mod
View File

@@ -6,23 +6,23 @@ require (
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2 github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.6 github.com/google/go-cmp v0.5.7
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/lucas-clemente/quic-go v0.24.0 github.com/lucas-clemente/quic-go v0.25.0
github.com/miekg/dns v1.1.43 github.com/miekg/dns v1.1.45
github.com/pelletier/go-toml v1.9.4 github.com/pelletier/go-toml v1.9.4
github.com/pires/go-proxyproto v0.6.1 github.com/pires/go-proxyproto v0.6.1
github.com/refraction-networking/utls v0.0.0-20210713165636-0b2885c8c0d4 github.com/refraction-networking/utls v1.0.0
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
github.com/xtls/go v0.0.0-20210920065950-d4af136d3672 github.com/xtls/go v0.0.0-20210920065950-d4af136d3672
go.starlark.net v0.0.0-20211013185944-b0039bd2cfe3 go.starlark.net v0.0.0-20211203141949-70c0e40ae128
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed
golang.org/x/net v0.0.0-20211020060615-d418f374d309 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20211020064051-0ec99a608a1b golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27
google.golang.org/grpc v1.41.0 google.golang.org/grpc v1.44.0
google.golang.org/protobuf v1.27.1 google.golang.org/protobuf v1.27.1
h12.io/socks v1.0.3 h12.io/socks v1.0.3
) )
@@ -30,20 +30,22 @@ require (
require ( require (
github.com/cheekybits/genny v1.0.0 // indirect github.com/cheekybits/genny v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-metro v0.0.0-20211015221634-2661b20a2446 // indirect github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect
github.com/nxadm/tail v1.4.8 // indirect github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/stretchr/objx v0.3.0 // indirect
golang.org/x/mod v0.5.1 // indirect golang.org/x/mod v0.5.1 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.7 // indirect golang.org/x/tools v0.1.9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/genproto v0.0.0-20211019152133-63b7e35f4404 // indirect google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

75
go.sum
View File

@@ -25,8 +25,11 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -34,6 +37,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dgryski/go-metro v0.0.0-20211015221634-2661b20a2446 h1:QnWGyQI3H080vbC9E4jlr6scOYEnALtvV/69oATYzOo= github.com/dgryski/go-metro v0.0.0-20211015221634-2661b20a2446 h1:QnWGyQI3H080vbC9E4jlr6scOYEnALtvV/69oATYzOo=
github.com/dgryski/go-metro v0.0.0-20211015221634-2661b20a2446/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/go-metro v0.0.0-20211015221634-2661b20a2446/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0=
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -86,8 +91,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -114,8 +119,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lucas-clemente/quic-go v0.24.0 h1:ToR7SIIEdrgOhgVTHvPgdVRJfgVy+N0wQAagH7L4d5g= github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc=
github.com/lucas-clemente/quic-go v0.24.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
@@ -124,10 +129,12 @@ github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2i
github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk=
github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8=
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM=
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.45 h1:g5fRIhm9nx7g8osrAvgb16QJfmyMsyOCb+J7LSv+Qzk=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
@@ -161,8 +168,8 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/refraction-networking/utls v0.0.0-20210713165636-0b2885c8c0d4 h1:n9NMHJusHylTmtaJ0Qe0VV9dkTZLiwAxHmrI/l98GeE= github.com/refraction-networking/utls v1.0.0 h1:6XQHSjDmeBCF9sPq8p2zMVGq7Ud3rTD2q88Fw8Tz1tA=
github.com/refraction-networking/utls v0.0.0-20210713165636-0b2885c8c0d4/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0= github.com/refraction-networking/utls v1.0.0/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@@ -195,8 +202,12 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
@@ -210,11 +221,11 @@ github.com/xtls/go v0.0.0-20210920065950-d4af136d3672 h1:4mkzGhKqt3JO1BWYjtD3iRF
github.com/xtls/go v0.0.0-20210920065950-d4af136d3672/go.mod h1:YGGVbz9cOxyKFUmhW7LGaLZaMA0cPlHJinvAmVxEMSU= github.com/xtls/go v0.0.0-20210920065950-d4af136d3672/go.mod h1:YGGVbz9cOxyKFUmhW7LGaLZaMA0cPlHJinvAmVxEMSU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.starlark.net v0.0.0-20211013185944-b0039bd2cfe3 h1:oBcONsksxvpeodDrLjiMDaKHXKAVVfAydhe/792CE/o= go.starlark.net v0.0.0-20211203141949-70c0e40ae128 h1:bxH+EXOo87zEOwKDdZ8Tevgi6irRbqheRm/fr293c58=
go.starlark.net v0.0.0-20211013185944-b0039bd2cfe3/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= go.starlark.net v0.0.0-20211203141949-70c0e40ae128/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -224,8 +235,10 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b h1:QAqMVf3pSa6eeTsuklijukjXBlj7Es2QQplab+/RbQ4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed h1:YoWVYYAfvQ4ddHv3OKmIvX7NCAhFGTj62VP2l2kfBbA=
golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -253,9 +266,13 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -285,16 +302,17 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211020064051-0ec99a608a1b h1:byBDhtWGQmWDrv1MlEv/BzGRMkw36h9QqsNnZQcDhRw= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211020064051-0ec99a608a1b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d h1:1oIt9o40TWWI9FUaveVpUvBe13FNqBNVXy3ue2fcfkw=
golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -317,8 +335,11 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -339,8 +360,10 @@ google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRn
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20211019152133-63b7e35f4404 h1:ZB48alYoIN+Soc1OcXirVKYOhOOf6Pek+iN+L+pzQI4= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0=
google.golang.org/genproto v0.0.0-20211019152133-63b7e35f4404/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 h1:YxHp5zqIcAShDEvRr5/0rVESVS+njYF68PSdazrNLJo=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@@ -351,8 +374,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

View File

@@ -5,6 +5,7 @@ import (
"github.com/xtls/xray-core/app/commander" "github.com/xtls/xray-core/app/commander"
loggerservice "github.com/xtls/xray-core/app/log/command" loggerservice "github.com/xtls/xray-core/app/log/command"
observatoryservice "github.com/xtls/xray-core/app/observatory/command"
handlerservice "github.com/xtls/xray-core/app/proxyman/command" handlerservice "github.com/xtls/xray-core/app/proxyman/command"
statsservice "github.com/xtls/xray-core/app/stats/command" statsservice "github.com/xtls/xray-core/app/stats/command"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
@@ -31,6 +32,8 @@ func (c *APIConfig) Build() (*commander.Config, error) {
services = append(services, serial.ToTypedMessage(&loggerservice.Config{})) services = append(services, serial.ToTypedMessage(&loggerservice.Config{}))
case "statsservice": case "statsservice":
services = append(services, serial.ToTypedMessage(&statsservice.Config{})) services = append(services, serial.ToTypedMessage(&statsservice.Config{}))
case "observatoryservice":
services = append(services, serial.ToTypedMessage(&observatoryservice.Config{}))
} }
} }

View File

@@ -2,6 +2,7 @@ package conf
import ( import (
"encoding/json" "encoding/json"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"

View File

@@ -0,0 +1,33 @@
package duration
import (
"encoding/json"
"fmt"
"time"
)
type Duration int64
func (d *Duration) MarshalJSON() ([]byte, error) {
dr := time.Duration(*d)
return json.Marshal(dr.String())
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case string:
var err error
dr, err := time.ParseDuration(value)
if err != nil {
return err
}
*d = Duration(dr)
return nil
default:
return fmt.Errorf("invalid duration: %v", v)
}
}

View File

@@ -0,0 +1,33 @@
package duration_test
import (
"encoding/json"
"testing"
"time"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
)
type testWithDuration struct {
Duration duration.Duration
}
func TestDurationJSON(t *testing.T) {
expected := &testWithDuration{
Duration: duration.Duration(time.Hour),
}
data, err := json.Marshal(expected)
if err != nil {
t.Error(err)
return
}
actual := &testWithDuration{}
err = json.Unmarshal(data, &actual)
if err != nil {
t.Error(err)
return
}
if actual.Duration != expected.Duration {
t.Errorf("expected: %s, actual: %s", time.Duration(expected.Duration), time.Duration(actual.Duration))
}
}

View File

@@ -209,8 +209,7 @@ func TestUserParsing(t *testing.T) {
common.Must(json.Unmarshal([]byte(`{ common.Must(json.Unmarshal([]byte(`{
"id": "96edb838-6d68-42ef-a933-25f7ac3a9d09", "id": "96edb838-6d68-42ef-a933-25f7ac3a9d09",
"email": "love@example.com", "email": "love@example.com",
"level": 1, "level": 1
"alterId": 100
}`), user)) }`), user))
nUser := user.Build() nUser := user.Build()

View File

@@ -68,10 +68,10 @@ func (FakeDNSPostProcessingStage) Process(config *Config) error {
} }
switch strings.ToLower(config.DNSConfig.QueryStrategy) { switch strings.ToLower(config.DNSConfig.QueryStrategy) {
case "useip4", "useipv4", "use_ip4", "use_ipv4", "use_ip_v4", "use-ip4", "use-ipv4", "use-ip-v4": case "useip4", "useipv4", "use_ip4", "use_ipv4", "use_ip_v4", "use-ip4", "use-ipv4", "use-ip-v4":
isIPv4Enable, isIPv6Enable = true, false isIPv4Enable, isIPv6Enable = true, false
case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6": case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6":
isIPv4Enable, isIPv6Enable = false, true isIPv4Enable, isIPv6Enable = false, true
} }
} }

View File

@@ -12,6 +12,7 @@ type GRPCConfig struct {
IdleTimeout int32 `json:"idle_timeout"` IdleTimeout int32 `json:"idle_timeout"`
HealthCheckTimeout int32 `json:"health_check_timeout"` HealthCheckTimeout int32 `json:"health_check_timeout"`
PermitWithoutStream bool `json:"permit_without_stream"` PermitWithoutStream bool `json:"permit_without_stream"`
InitialWindowsSize int32 `json:"initial_windows_size"`
} }
func (g *GRPCConfig) Build() (proto.Message, error) { func (g *GRPCConfig) Build() (proto.Message, error) {
@@ -21,11 +22,17 @@ func (g *GRPCConfig) Build() (proto.Message, error) {
if g.HealthCheckTimeout <= 0 { if g.HealthCheckTimeout <= 0 {
g.HealthCheckTimeout = 0 g.HealthCheckTimeout = 0
} }
if g.InitialWindowsSize < 0 {
// default window size of gRPC-go
g.InitialWindowsSize = 0
}
return &grpc.Config{ return &grpc.Config{
ServiceName: g.ServiceName, ServiceName: g.ServiceName,
MultiMode: g.MultiMode, MultiMode: g.MultiMode,
IdleTimeout: g.IdleTimeout, IdleTimeout: g.IdleTimeout,
HealthCheckTimeout: g.HealthCheckTimeout, HealthCheckTimeout: g.HealthCheckTimeout,
PermitWithoutStream: g.PermitWithoutStream, PermitWithoutStream: g.PermitWithoutStream,
InitialWindowsSize: g.InitialWindowsSize,
}, nil }, nil
} }

View File

@@ -2,13 +2,18 @@ package conf
import ( import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
) )
type ObservatoryConfig struct { type ObservatoryConfig struct {
SubjectSelector []string `json:"subjectSelector"` SubjectSelector []string `json:"subjectSelector"`
ProbeURL string `json:"probeURL"`
ProbeInterval duration.Duration `json:"probeInterval"`
EnableConcurrency bool `json:"enableConcurrency"`
} }
func (o ObservatoryConfig) Build() (proto.Message, error) { func (o *ObservatoryConfig) Build() (proto.Message, error) {
return &observatory.Config{SubjectSelector: o.SubjectSelector}, nil return &observatory.Config{SubjectSelector: o.SubjectSelector, ProbeUrl: o.ProbeURL, ProbeInterval: int64(o.ProbeInterval), EnableConcurrency: o.EnableConcurrency}, nil
} }

View File

@@ -18,9 +18,16 @@ type RouterRulesConfig struct {
DomainStrategy string `json:"domainStrategy"` DomainStrategy string `json:"domainStrategy"`
} }
// StrategyConfig represents a strategy config
type StrategyConfig struct {
Type string `json:"type"`
Settings *json.RawMessage `json:"settings"`
}
type BalancingRule struct { type BalancingRule struct {
Tag string `json:"tag"` Tag string `json:"tag"`
Selectors StringList `json:"selector"` Selectors StringList `json:"selector"`
Strategy StrategyConfig `json:"strategy"`
} }
func (r *BalancingRule) Build() (*router.BalancingRule, error) { func (r *BalancingRule) Build() (*router.BalancingRule, error) {
@@ -31,9 +38,20 @@ func (r *BalancingRule) Build() (*router.BalancingRule, error) {
return nil, newError("empty selector list") return nil, newError("empty selector list")
} }
var strategy string
switch strings.ToLower(r.Strategy.Type) {
case strategyRandom, "":
strategy = strategyRandom
case strategyLeastPing:
strategy = "leastPing"
default:
return nil, newError("unknown balancing strategy: " + r.Strategy.Type)
}
return &router.BalancingRule{ return &router.BalancingRule{
Tag: r.Tag, Tag: r.Tag,
OutboundSelector: []string(r.Selectors), OutboundSelector: []string(r.Selectors),
Strategy: strategy,
}, nil }, nil
} }

View File

@@ -0,0 +1,6 @@
package conf
const (
strategyRandom string = "random"
strategyLeastPing string = "leastping"
)

View File

@@ -107,6 +107,7 @@ func TestRouterConfig(t *testing.T) {
{ {
Tag: "b1", Tag: "b1",
OutboundSelector: []string{"test"}, OutboundSelector: []string{"test"},
Strategy: "random",
}, },
}, },
Rule: []*router.RoutingRule{ Rule: []*router.RoutingRule{

View File

@@ -59,7 +59,7 @@ func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
return nil, newError("Shadowsocks password is not specified.") return nil, newError("Shadowsocks password is not specified.")
} }
if account.CipherType < shadowsocks.CipherType_AES_128_GCM || if account.CipherType < shadowsocks.CipherType_AES_128_GCM ||
account.CipherType > shadowsocks.CipherType_CHACHA20_POLY1305 { account.CipherType > shadowsocks.CipherType_XCHACHA20_POLY1305 {
return nil, newError("unsupported cipher method: ", user.Cipher) return nil, newError("unsupported cipher method: ", user.Cipher)
} }
config.Users = append(config.Users, &protocol.User{ config.Users = append(config.Users, &protocol.User{

View File

@@ -15,9 +15,10 @@ import (
) )
type VMessAccount struct { type VMessAccount struct {
ID string `json:"id"` ID string `json:"id"`
AlterIds uint16 `json:"alterId"` AlterIds uint16 `json:"alterId"`
Security string `json:"security"` Security string `json:"security"`
Experiments string `json:"experiments"`
} }
// Build implements Buildable // Build implements Buildable
@@ -43,6 +44,7 @@ func (a *VMessAccount) Build() *vmess.Account {
SecuritySettings: &protocol.SecurityConfig{ SecuritySettings: &protocol.SecurityConfig{
Type: st, Type: st,
}, },
TestsEnabled: a.Experiments,
} }
} }

View File

@@ -47,8 +47,7 @@ func TestVMessOutbound(t *testing.T) {
Email: "love@example.com", Email: "love@example.com",
Level: 255, Level: 255,
Account: serial.ToTypedMessage(&vmess.Account{ Account: serial.ToTypedMessage(&vmess.Account{
Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019", Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019",
AlterId: 0,
SecuritySettings: &protocol.SecurityConfig{ SecuritySettings: &protocol.SecurityConfig{
Type: protocol.SecurityType_AUTO, Type: protocol.SecurityType_AUTO,
}, },
@@ -74,14 +73,12 @@ func TestVMessInbound(t *testing.T) {
{ {
"id": "27848739-7e62-4138-9fd3-098a63964b6b", "id": "27848739-7e62-4138-9fd3-098a63964b6b",
"level": 0, "level": 0,
"alterId": 16,
"email": "love@example.com", "email": "love@example.com",
"security": "aes-128-gcm" "security": "aes-128-gcm"
} }
], ],
"default": { "default": {
"level": 0, "level": 0
"alterId": 32
}, },
"detour": { "detour": {
"to": "tag_to_detour" "to": "tag_to_detour"
@@ -95,8 +92,7 @@ func TestVMessInbound(t *testing.T) {
Level: 0, Level: 0,
Email: "love@example.com", Email: "love@example.com",
Account: serial.ToTypedMessage(&vmess.Account{ Account: serial.ToTypedMessage(&vmess.Account{
Id: "27848739-7e62-4138-9fd3-098a63964b6b", Id: "27848739-7e62-4138-9fd3-098a63964b6b",
AlterId: 16,
SecuritySettings: &protocol.SecurityConfig{ SecuritySettings: &protocol.SecurityConfig{
Type: protocol.SecurityType_AES128_GCM, Type: protocol.SecurityType_AES128_GCM,
}, },
@@ -104,8 +100,7 @@ func TestVMessInbound(t *testing.T) {
}, },
}, },
Default: &inbound.DefaultConfig{ Default: &inbound.DefaultConfig{
Level: 0, Level: 0,
AlterId: 32,
}, },
Detour: &inbound.DetourConfig{ Detour: &inbound.DetourConfig{
To: "tag_to_detour", To: "tag_to_detour",

View File

@@ -2,6 +2,7 @@ package conf
import ( import (
"encoding/json" "encoding/json"
"fmt"
"log" "log"
"os" "os"
"strings" "strings"
@@ -10,9 +11,8 @@ import (
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/app/stats"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/transport/internet"
core "github.com/xtls/xray-core/core" core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/xtls" "github.com/xtls/xray-core/transport/internet/xtls"
) )
@@ -162,7 +162,7 @@ func (c *InboundDetourAllocationConfig) Build() (*proxyman.AllocationStrategy, e
type InboundDetourConfig struct { type InboundDetourConfig struct {
Protocol string `json:"protocol"` Protocol string `json:"protocol"`
PortRange *PortRange `json:"port"` PortList *PortList `json:"port"`
ListenOn *Address `json:"listen"` ListenOn *Address `json:"listen"`
Settings *json.RawMessage `json:"settings"` Settings *json.RawMessage `json:"settings"`
Tag string `json:"tag"` Tag string `json:"tag"`
@@ -177,27 +177,27 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
receiverSettings := &proxyman.ReceiverConfig{} receiverSettings := &proxyman.ReceiverConfig{}
if c.ListenOn == nil { if c.ListenOn == nil {
// Listen on anyip, must set PortRange // Listen on anyip, must set PortList
if c.PortRange == nil { if c.PortList == nil {
return nil, newError("Listen on AnyIP but no Port(s) set in InboundDetour.") return nil, newError("Listen on AnyIP but no Port(s) set in InboundDetour.")
} }
receiverSettings.PortRange = c.PortRange.Build() receiverSettings.PortList = c.PortList.Build()
} else { } else {
// Listen on specific IP or Unix Domain Socket // Listen on specific IP or Unix Domain Socket
receiverSettings.Listen = c.ListenOn.Build() receiverSettings.Listen = c.ListenOn.Build()
listenDS := c.ListenOn.Family().IsDomain() && (c.ListenOn.Domain()[0] == '/' || c.ListenOn.Domain()[0] == '@') listenDS := c.ListenOn.Family().IsDomain() && (c.ListenOn.Domain()[0] == '/' || c.ListenOn.Domain()[0] == '@')
listenIP := c.ListenOn.Family().IsIP() || (c.ListenOn.Family().IsDomain() && c.ListenOn.Domain() == "localhost") listenIP := c.ListenOn.Family().IsIP() || (c.ListenOn.Family().IsDomain() && c.ListenOn.Domain() == "localhost")
if listenIP { if listenIP {
// Listen on specific IP, must set PortRange // Listen on specific IP, must set PortList
if c.PortRange == nil { if c.PortList == nil {
return nil, newError("Listen on specific ip without port in InboundDetour.") return nil, newError("Listen on specific ip without port in InboundDetour.")
} }
// Listen on IP:Port // Listen on IP:Port
receiverSettings.PortRange = c.PortRange.Build() receiverSettings.PortList = c.PortList.Build()
} else if listenDS { } else if listenDS {
if c.PortRange != nil { if c.PortList != nil {
// Listen on Unix Domain Socket, PortRange should be nil // Listen on Unix Domain Socket, PortList should be nil
receiverSettings.PortRange = nil receiverSettings.PortList = nil
} }
} else { } else {
return nil, newError("unable to listen on domain address: ", c.ListenOn.Domain()) return nil, newError("unable to listen on domain address: ", c.ListenOn.Domain())
@@ -209,9 +209,17 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
if c.Allocation.Concurrency != nil && c.Allocation.Strategy == "random" { if c.Allocation.Concurrency != nil && c.Allocation.Strategy == "random" {
concurrency = int(*c.Allocation.Concurrency) concurrency = int(*c.Allocation.Concurrency)
} }
portRange := int(c.PortRange.To - c.PortRange.From + 1) portRange := 0
for _, pr := range c.PortList.Range {
portRange += int(pr.To - pr.From + 1)
}
if concurrency >= 0 && concurrency >= portRange { if concurrency >= 0 && concurrency >= portRange {
return nil, newError("not enough ports. concurrency = ", concurrency, " ports: ", c.PortRange.From, " - ", c.PortRange.To) var ports strings.Builder
for _, pr := range c.PortList.Range {
fmt.Fprintf(&ports, "%d-%d ", pr.From, pr.To)
}
return nil, newError("not enough ports. concurrency = ", concurrency, " ports: ", ports.String())
} }
as, err := c.Allocation.Build() as, err := c.Allocation.Build()
@@ -464,6 +472,10 @@ func (c *Config) Override(o *Config, fn string) {
c.FakeDNS = o.FakeDNS c.FakeDNS = o.FakeDNS
} }
if o.Observatory != nil {
c.Observatory = o.Observatory
}
// deprecated attrs... keep them for now // deprecated attrs... keep them for now
if o.InboundConfig != nil { if o.InboundConfig != nil {
c.InboundConfig = o.InboundConfig c.InboundConfig = o.InboundConfig
@@ -636,11 +648,11 @@ func (c *Config) Build() (*core.Config, error) {
} }
// Backward compatibility. // Backward compatibility.
if len(inbounds) > 0 && inbounds[0].PortRange == nil && c.Port > 0 { if len(inbounds) > 0 && inbounds[0].PortList == nil && c.Port > 0 {
inbounds[0].PortRange = &PortRange{ inbounds[0].PortList = &PortList{[]PortRange{{
From: uint32(c.Port), From: uint32(c.Port),
To: uint32(c.Port), To: uint32(c.Port),
} }}}
} }
for _, rawInboundConfig := range inbounds { for _, rawInboundConfig := range inbounds {

View File

@@ -72,7 +72,6 @@ func TestXrayConfig(t *testing.T) {
"settings": { "settings": {
"clients": [ "clients": [
{ {
"alterId": 100,
"security": "aes-128-gcm", "security": "aes-128-gcm",
"id": "0cdf8a45-303d-4fed-9780-29aa7f54175e" "id": "0cdf8a45-303d-4fed-9780-29aa7f54175e"
} }
@@ -102,7 +101,6 @@ func TestXrayConfig(t *testing.T) {
"settings": { "settings": {
"clients": [ "clients": [
{ {
"alterId": 100,
"security": "aes-128-gcm", "security": "aes-128-gcm",
"id": "0cdf8a45-303d-4fed-9780-29aa7f54175e" "id": "0cdf8a45-303d-4fed-9780-29aa7f54175e"
} }
@@ -231,10 +229,7 @@ func TestXrayConfig(t *testing.T) {
Inbound: []*core.InboundHandlerConfig{ Inbound: []*core.InboundHandlerConfig{
{ {
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: &net.PortRange{ PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(443)}},
From: 443,
To: 443,
},
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
ProtocolName: "websocket", ProtocolName: "websocket",
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
@@ -269,8 +264,7 @@ func TestXrayConfig(t *testing.T) {
{ {
Level: 0, Level: 0,
Account: serial.ToTypedMessage(&vmess.Account{ Account: serial.ToTypedMessage(&vmess.Account{
Id: "0cdf8a45-303d-4fed-9780-29aa7f54175e", Id: "0cdf8a45-303d-4fed-9780-29aa7f54175e",
AlterId: 100,
SecuritySettings: &protocol.SecurityConfig{ SecuritySettings: &protocol.SecurityConfig{
Type: protocol.SecurityType_AES128_GCM, Type: protocol.SecurityType_AES128_GCM,
}, },
@@ -281,10 +275,10 @@ func TestXrayConfig(t *testing.T) {
}, },
{ {
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: &net.PortRange{ PortList: &net.PortList{Range: []*net.PortRange{{
From: 443, From: 443,
To: 500, To: 500,
}, }}},
AllocationStrategy: &proxyman.AllocationStrategy{ AllocationStrategy: &proxyman.AllocationStrategy{
Type: proxyman.AllocationStrategy_Random, Type: proxyman.AllocationStrategy_Random,
Concurrency: &proxyman.AllocationStrategy_AllocationStrategyConcurrency{ Concurrency: &proxyman.AllocationStrategy_AllocationStrategyConcurrency{
@@ -325,8 +319,7 @@ func TestXrayConfig(t *testing.T) {
{ {
Level: 0, Level: 0,
Account: serial.ToTypedMessage(&vmess.Account{ Account: serial.ToTypedMessage(&vmess.Account{
Id: "0cdf8a45-303d-4fed-9780-29aa7f54175e", Id: "0cdf8a45-303d-4fed-9780-29aa7f54175e",
AlterId: 100,
SecuritySettings: &protocol.SecurityConfig{ SecuritySettings: &protocol.SecurityConfig{
Type: protocol.SecurityType_AES128_GCM, Type: protocol.SecurityType_AES128_GCM,
}, },

View File

@@ -14,6 +14,9 @@ import (
_ "github.com/xtls/xray-core/app/proxyman/command" _ "github.com/xtls/xray-core/app/proxyman/command"
_ "github.com/xtls/xray-core/app/stats/command" _ "github.com/xtls/xray-core/app/stats/command"
// Developer preview services
_ "github.com/xtls/xray-core/app/observatory/command"
// Other optional features. // Other optional features.
_ "github.com/xtls/xray-core/app/dns" _ "github.com/xtls/xray-core/app/dns"
_ "github.com/xtls/xray-core/app/dns/fakedns" _ "github.com/xtls/xray-core/app/dns/fakedns"
@@ -26,6 +29,9 @@ import (
// Fix dependency cycle caused by core import in internet package // Fix dependency cycle caused by core import in internet package
_ "github.com/xtls/xray-core/transport/internet/tagged/taggedimpl" _ "github.com/xtls/xray-core/transport/internet/tagged/taggedimpl"
// Developer preview features
_ "github.com/xtls/xray-core/app/observatory"
// Inbound and outbound proxies. // Inbound and outbound proxies.
_ "github.com/xtls/xray-core/proxy/blackhole" _ "github.com/xtls/xray-core/proxy/blackhole"
_ "github.com/xtls/xray-core/proxy/dns" _ "github.com/xtls/xray-core/proxy/dns"

View File

@@ -6,8 +6,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"golang.org/x/net/dns/dnsmessage" "golang.org/x/net/dns/dnsmessage"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -22,6 +20,7 @@ import (
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
) )
func init() { func init() {

View File

@@ -117,8 +117,8 @@ func TestUDPDNSTunnel(t *testing.T) {
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(serverPort), PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
}, },
}, },
@@ -236,8 +236,8 @@ func TestTCPDNSTunnel(t *testing.T) {
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(serverPort), PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
}, },
}, },
@@ -322,8 +322,8 @@ func TestUDP2TCPDNSTunnel(t *testing.T) {
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(serverPort), PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
}, },
}, },

View File

@@ -7,8 +7,6 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
@@ -20,6 +18,7 @@ import (
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
) )
func init() { func init() {

View File

@@ -6,8 +6,6 @@ import (
"context" "context"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/dice"
@@ -22,6 +20,7 @@ import (
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
) )
func init() { func init() {

View File

@@ -9,8 +9,6 @@ import (
"net/url" "net/url"
"sync" "sync"
"github.com/xtls/xray-core/transport/internet/stat"
"golang.org/x/net/http2" "golang.org/x/net/http2"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -26,6 +24,7 @@ import (
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
) )

View File

@@ -9,8 +9,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -24,6 +22,7 @@ import (
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
) )
// Server is an HTTP proxy server. // Server is an HTTP proxy server.

View File

@@ -2,11 +2,11 @@ package loopback
import ( import (
"context" "context"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/retry" "github.com/xtls/xray-core/common/retry"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/common/task"

View File

@@ -5,8 +5,6 @@ import (
"context" "context"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/crypto" "github.com/xtls/xray-core/common/crypto"
@@ -18,6 +16,7 @@ import (
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
) )
var dcList = []net.Address{ var dcList = []net.Address{

View File

@@ -8,13 +8,12 @@ package proxy
import ( import (
"context" "context"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
) )
// An Inbound processes inbound connections. // An Inbound processes inbound connections.

View File

@@ -4,8 +4,6 @@ import (
"context" "context"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -18,6 +16,7 @@ import (
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
) )
// Client is a inbound handler for Shadowsocks protocol // Client is a inbound handler for Shadowsocks protocol
@@ -75,7 +74,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
if err != nil { if err != nil {
return newError("failed to find an available destination").AtWarning().Base(err) return newError("failed to find an available destination").AtWarning().Base(err)
} }
newError("tunneling request to ", destination, " via ", server.Destination()).WriteToLog(session.ExportIDToError(ctx)) newError("tunneling request to ", destination, " via ", network, ":", server.Destination().NetAddr()).WriteToLog(session.ExportIDToError(ctx))
defer conn.Close() defer conn.Close()

View File

@@ -7,8 +7,6 @@ import (
"crypto/md5" "crypto/md5"
"crypto/sha1" "crypto/sha1"
"io" "io"
"reflect"
"strconv"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/hkdf" "golang.org/x/crypto/hkdf"
@@ -28,6 +26,10 @@ type MemoryAccount struct {
replayFilter antireplay.GeneralizedReplayFilter replayFilter antireplay.GeneralizedReplayFilter
} }
var (
ErrIVNotUnique = newError("IV is not unique")
)
// Equals implements protocol.Account.Equals(). // Equals implements protocol.Account.Equals().
func (a *MemoryAccount) Equals(another protocol.Account) bool { func (a *MemoryAccount) Equals(another protocol.Account) bool {
if account, ok := another.(*MemoryAccount); ok { if account, ok := another.(*MemoryAccount); ok {
@@ -43,24 +45,7 @@ func (a *MemoryAccount) CheckIV(iv []byte) error {
if a.replayFilter.Check(iv) { if a.replayFilter.Check(iv) {
return nil return nil
} }
return newError("IV is not unique") return ErrIVNotUnique
}
func (a *MemoryAccount) GetCipherName() string {
switch a.Cipher.(type) {
case *AEADCipher:
switch reflect.ValueOf(a.Cipher.(*AEADCipher).AEADAuthCreator).Pointer() {
case reflect.ValueOf(createAesGcm).Pointer():
keyBytes := a.Cipher.(*AEADCipher).KeyBytes
return "AES_" + strconv.FormatInt(int64(keyBytes*8), 10) + "_GCM"
case reflect.ValueOf(createChaCha20Poly1305).Pointer():
return "CHACHA20_POLY1305"
}
case *NoneCipher:
return "NONE"
}
return ""
} }
func createAesGcm(key []byte) cipher.AEAD { func createAesGcm(key []byte) cipher.AEAD {

View File

@@ -1,7 +1,6 @@
package shadowsocks package shadowsocks
import ( import (
"crypto/cipher"
"crypto/hmac" "crypto/hmac"
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
@@ -11,7 +10,7 @@ import (
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/crypto" "github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/drain"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
) )
@@ -54,83 +53,55 @@ func (r *FullReader) Read(p []byte) (n int, err error) {
// ReadTCPSession reads a Shadowsocks TCP session from the given reader, returns its header and remaining parts. // ReadTCPSession reads a Shadowsocks TCP session from the given reader, returns its header and remaining parts.
func ReadTCPSession(validator *Validator, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) { func ReadTCPSession(validator *Validator, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
hashkdf := hmac.New(sha256.New, []byte("SSBSKDF")) behaviorSeed := validator.GetBehaviorSeed()
drainer, errDrain := drain.NewBehaviorSeedLimitedDrainer(int64(behaviorSeed), 16+38, 3266, 64)
behaviorSeed := crc32.ChecksumIEEE(hashkdf.Sum(nil)) if errDrain != nil {
return nil, nil, newError("failed to initialize drainer").Base(errDrain)
}
behaviorRand := dice.NewDeterministicDice(int64(behaviorSeed)) var r buf.Reader
BaseDrainSize := behaviorRand.Roll(3266)
RandDrainMax := behaviorRand.Roll(64) + 1
RandDrainRolled := dice.Roll(RandDrainMax)
DrainSize := BaseDrainSize + 16 + 38 + RandDrainRolled
readSizeRemain := DrainSize
var r2 buf.Reader
buffer := buf.New() buffer := buf.New()
defer buffer.Release() defer buffer.Release()
var user *protocol.MemoryUser if _, err := buffer.ReadFullFrom(reader, 50); err != nil {
var ivLen int32 drainer.AcknowledgeReceive(int(buffer.Len()))
var iv []byte return nil, nil, drain.WithError(drainer, reader, newError("failed to read 50 bytes").Base(err))
var err error }
count := validator.Count() bs := buffer.Bytes()
if count == 0 { user, aead, _, ivLen, err := validator.Get(bs, protocol.RequestCommandTCP)
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("invalid user")
} else if count > 1 {
var aead cipher.AEAD
if _, err := buffer.ReadFullFrom(reader, 50); err != nil { switch err {
readSizeRemain -= int(buffer.Len()) case ErrNotFound:
DrainConnN(reader, readSizeRemain) drainer.AcknowledgeReceive(int(buffer.Len()))
return nil, nil, newError("failed to read 50 bytes").Base(err) return nil, nil, drain.WithError(drainer, reader, newError("failed to match an user").Base(err))
} case ErrIVNotUnique:
drainer.AcknowledgeReceive(int(buffer.Len()))
return nil, nil, drain.WithError(drainer, reader, newError("failed iv check").Base(err))
default:
reader = &FullReader{reader, bs[ivLen:]}
drainer.AcknowledgeReceive(int(ivLen))
bs := buffer.Bytes() if aead != nil {
user, aead, _, ivLen, err = validator.Get(bs, protocol.RequestCommandTCP)
if user != nil {
if ivLen > 0 {
iv = append([]byte(nil), bs[:ivLen]...)
}
reader = &FullReader{reader, bs[ivLen:]}
auth := &crypto.AEADAuthenticator{ auth := &crypto.AEADAuthenticator{
AEAD: aead, AEAD: aead,
NonceGenerator: crypto.GenerateInitialAEADNonce(), NonceGenerator: crypto.GenerateAEADNonceWithSize(aead.NonceSize()),
} }
r2 = crypto.NewAuthenticationReader(auth, &crypto.AEADChunkSizeParser{ r = crypto.NewAuthenticationReader(auth, &crypto.AEADChunkSizeParser{
Auth: auth, Auth: auth,
}, reader, protocol.TransferTypeStream, nil) }, reader, protocol.TransferTypeStream, nil)
} else { } else {
readSizeRemain -= int(buffer.Len()) account := user.Account.(*MemoryAccount)
DrainConnN(reader, readSizeRemain) iv := append([]byte(nil), buffer.BytesTo(ivLen)...)
return nil, nil, newError("failed to match an user").Base(err) r, err = account.Cipher.NewDecryptionReader(account.Key, iv, reader)
} if err != nil {
} else { return nil, nil, drain.WithError(drainer, reader, newError("failed to initialize decoding stream").Base(err).AtError())
user, ivLen = validator.GetOnlyUser()
account := user.Account.(*MemoryAccount)
hashkdf.Write(account.Key)
if ivLen > 0 {
if _, err := buffer.ReadFullFrom(reader, ivLen); err != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed to read IV").Base(err)
} }
iv = append([]byte(nil), buffer.BytesTo(ivLen)...)
} }
r, err := account.Cipher.NewDecryptionReader(account.Key, iv, reader)
if err != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed to initialize decoding stream").Base(err).AtError()
}
r2 = r
} }
br := &buf.BufferedReader{Reader: r2} br := &buf.BufferedReader{Reader: r}
request := &protocol.RequestHeader{ request := &protocol.RequestHeader{
Version: Version, Version: Version,
@@ -138,40 +109,25 @@ func ReadTCPSession(validator *Validator, reader io.Reader) (*protocol.RequestHe
Command: protocol.RequestCommandTCP, Command: protocol.RequestCommandTCP,
} }
readSizeRemain -= int(buffer.Len())
buffer.Clear() buffer.Clear()
addr, port, err := addrParser.ReadAddressPort(buffer, br) addr, port, err := addrParser.ReadAddressPort(buffer, br)
if err != nil { if err != nil {
readSizeRemain -= int(buffer.Len()) drainer.AcknowledgeReceive(int(buffer.Len()))
DrainConnN(reader, readSizeRemain) return nil, nil, drain.WithError(drainer, reader, newError("failed to read address").Base(err))
return nil, nil, newError("failed to read address").Base(err)
} }
request.Address = addr request.Address = addr
request.Port = port request.Port = port
if request.Address == nil { if request.Address == nil {
readSizeRemain -= int(buffer.Len()) drainer.AcknowledgeReceive(int(buffer.Len()))
DrainConnN(reader, readSizeRemain) return nil, nil, drain.WithError(drainer, reader, newError("invalid remote address."))
return nil, nil, newError("invalid remote address.")
}
account := user.Account.(*MemoryAccount)
if ivError := account.CheckIV(iv); ivError != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed iv check").Base(ivError)
} }
return request, br, nil return request, br, nil
} }
func DrainConnN(reader io.Reader, n int) error {
_, err := io.CopyN(io.Discard, reader, int64(n))
return err
}
// WriteTCPRequest writes Shadowsocks request into the given writer, and returns a writer for body. // WriteTCPRequest writes Shadowsocks request into the given writer, and returns a writer for body.
func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) { func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
user := request.User user := request.User
@@ -210,16 +166,29 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
func ReadTCPResponse(user *protocol.MemoryUser, reader io.Reader) (buf.Reader, error) { func ReadTCPResponse(user *protocol.MemoryUser, reader io.Reader) (buf.Reader, error) {
account := user.Account.(*MemoryAccount) account := user.Account.(*MemoryAccount)
hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
hashkdf.Write(account.Key)
behaviorSeed := crc32.ChecksumIEEE(hashkdf.Sum(nil))
drainer, err := drain.NewBehaviorSeedLimitedDrainer(int64(behaviorSeed), 16+38, 3266, 64)
if err != nil {
return nil, newError("failed to initialize drainer").Base(err)
}
var iv []byte var iv []byte
if account.Cipher.IVSize() > 0 { if account.Cipher.IVSize() > 0 {
iv = make([]byte, account.Cipher.IVSize()) iv = make([]byte, account.Cipher.IVSize())
if _, err := io.ReadFull(reader, iv); err != nil { if n, err := io.ReadFull(reader, iv); err != nil {
return nil, newError("failed to read IV").Base(err) return nil, newError("failed to read IV").Base(err)
} else { // nolint: golint
drainer.AcknowledgeReceive(n)
} }
} }
if ivError := account.CheckIV(iv); ivError != nil { if ivError := account.CheckIV(iv); ivError != nil {
return nil, newError("failed iv check").Base(ivError) return nil, drain.WithError(drainer, reader, newError("failed iv check").Base(ivError))
} }
return account.Cipher.NewDecryptionReader(account.Key, iv, reader) return account.Cipher.NewDecryptionReader(account.Key, iv, reader)
@@ -273,34 +242,25 @@ func DecodeUDPPacket(validator *Validator, payload *buf.Buffer) (*protocol.Reque
return nil, nil, newError("len(bs) <= 32") return nil, nil, newError("len(bs) <= 32")
} }
var user *protocol.MemoryUser user, _, d, _, err := validator.Get(bs, protocol.RequestCommandUDP)
var err error switch err {
case ErrIVNotUnique:
count := validator.Count() return nil, nil, newError("failed iv check").Base(err)
if count == 0 { case ErrNotFound:
return nil, nil, newError("invalid user") return nil, nil, newError("failed to match an user").Base(err)
} else if count > 1 { default:
var d []byte account := user.Account.(*MemoryAccount)
user, _, d, _, err = validator.Get(bs, protocol.RequestCommandUDP) if account.Cipher.IsAEAD() {
if user != nil {
payload.Clear() payload.Clear()
payload.Write(d) payload.Write(d)
} else { } else {
return nil, nil, newError("failed to decrypt UDP payload").Base(err) if account.Cipher.IVSize() > 0 {
} iv := make([]byte, account.Cipher.IVSize())
} else { copy(iv, payload.BytesTo(account.Cipher.IVSize()))
user, _ = validator.GetOnlyUser() }
account := user.Account.(*MemoryAccount) if err = account.Cipher.DecodePacket(account.Key, payload); err != nil {
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
var iv []byte }
if !account.Cipher.IsAEAD() && account.Cipher.IVSize() > 0 {
// Keep track of IV as it gets removed from payload in DecodePacket.
iv = make([]byte, account.Cipher.IVSize())
copy(iv, payload.BytesTo(account.Cipher.IVSize()))
}
if err = account.Cipher.DecodePacket(account.Key, payload); err != nil {
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
} }
} }

View File

@@ -4,8 +4,6 @@ import (
"context" "context"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
@@ -18,6 +16,7 @@ import (
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/udp" "github.com/xtls/xray-core/transport/internet/udp"
) )
@@ -115,10 +114,6 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis
panic("no inbound metadata") panic("no inbound metadata")
} }
if s.validator.Count() == 1 {
inbound.User, _ = s.validator.GetOnlyUser()
}
var dest *net.Destination var dest *net.Destination
reader := buf.NewPacketReader(conn) reader := buf.NewPacketReader(conn)

View File

@@ -2,112 +2,127 @@ package shadowsocks
import ( import (
"crypto/cipher" "crypto/cipher"
"crypto/hmac"
"crypto/sha256"
"hash/crc64"
"strings" "strings"
"sync" "sync"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
) )
// Validator stores valid Shadowsocks users. // Validator stores valid Shadowsocks users.
type Validator struct { type Validator struct {
// Considering email's usage here, map + sync.Mutex/RWMutex may have better performance. sync.RWMutex
email sync.Map users []*protocol.MemoryUser
users sync.Map
behaviorSeed uint64
behaviorFused bool
} }
// Add a Shadowsocks user, Email must be empty or unique. var (
ErrNotFound = newError("Not Found")
)
// Add a Shadowsocks user.
func (v *Validator) Add(u *protocol.MemoryUser) error { func (v *Validator) Add(u *protocol.MemoryUser) error {
v.Lock()
defer v.Unlock()
account := u.Account.(*MemoryAccount) account := u.Account.(*MemoryAccount)
if !account.Cipher.IsAEAD() && len(v.users) > 0 {
return newError("The cipher is not support Single-port Multi-user")
}
v.users = append(v.users, u)
if !account.Cipher.IsAEAD() && v.Count() > 0 { if !v.behaviorFused {
return newError("The cipher do not support Single-port Multi-user") hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
hashkdf.Write(account.Key)
v.behaviorSeed = crc64.Update(v.behaviorSeed, crc64.MakeTable(crc64.ECMA), hashkdf.Sum(nil))
} }
if u.Email != "" {
_, loaded := v.email.LoadOrStore(strings.ToLower(u.Email), u)
if loaded {
return newError("User ", u.Email, " already exists.")
}
}
v.users.Store(string(account.Key)+"&"+account.GetCipherName(), u)
return nil return nil
} }
// Del a Shadowsocks user with a non-empty Email. // Del a Shadowsocks user with a non-empty Email.
func (v *Validator) Del(e string) error { func (v *Validator) Del(email string) error {
if e == "" { if email == "" {
return newError("Email must not be empty.") return newError("Email must not be empty.")
} }
le := strings.ToLower(e)
u, _ := v.email.Load(le) v.Lock()
if u == nil { defer v.Unlock()
return newError("User ", e, " not found.")
email = strings.ToLower(email)
idx := -1
for i, u := range v.users {
if strings.EqualFold(u.Email, email) {
idx = i
break
}
} }
account := u.(*protocol.MemoryUser).Account.(*MemoryAccount)
v.email.Delete(le) if idx == -1 {
v.users.Delete(string(account.Key) + "&" + account.GetCipherName()) return newError("User ", email, " not found.")
}
ulen := len(v.users)
v.users[idx] = v.users[ulen-1]
v.users[ulen-1] = nil
v.users = v.users[:ulen-1]
return nil return nil
} }
// Count the number of Shadowsocks users // Get a Shadowsocks user.
func (v *Validator) Count() int {
length := 0
v.users.Range(func(_, _ interface{}) bool {
length++
return true
})
return length
}
// Get a Shadowsocks user and the user's cipher.
func (v *Validator) Get(bs []byte, command protocol.RequestCommand) (u *protocol.MemoryUser, aead cipher.AEAD, ret []byte, ivLen int32, err error) { func (v *Validator) Get(bs []byte, command protocol.RequestCommand) (u *protocol.MemoryUser, aead cipher.AEAD, ret []byte, ivLen int32, err error) {
var dataSize int v.RLock()
defer v.RUnlock()
switch command { for _, user := range v.users {
case protocol.RequestCommandTCP: if account := user.Account.(*MemoryAccount); account.Cipher.IsAEAD() {
dataSize = 16 aeadCipher := account.Cipher.(*AEADCipher)
case protocol.RequestCommandUDP: ivLen = aeadCipher.IVSize()
dataSize = 8192 iv := bs[:ivLen]
subkey := make([]byte, 32)
subkey = subkey[:aeadCipher.KeyBytes]
hkdfSHA1(account.Key, iv, subkey)
aead = aeadCipher.AEADAuthCreator(subkey)
var matchErr error
switch command {
case protocol.RequestCommandTCP:
data := make([]byte, 4+aead.NonceSize())
ret, matchErr = aead.Open(data[:0], data[4:], bs[ivLen:ivLen+18], nil)
case protocol.RequestCommandUDP:
data := make([]byte, 8192)
ret, matchErr = aead.Open(data[:0], data[8192-aead.NonceSize():8192], bs[ivLen:], nil)
}
if matchErr == nil {
u = user
err = account.CheckIV(iv)
return
}
} else {
u = user
ivLen = user.Account.(*MemoryAccount).Cipher.IVSize()
// err = user.Account.(*MemoryAccount).CheckIV(bs[:ivLen]) // The IV size of None Cipher is 0.
return
}
} }
var aeadCipher *AEADCipher return nil, nil, nil, 0, ErrNotFound
subkey := make([]byte, 32)
data := make([]byte, dataSize)
v.users.Range(func(key, user interface{}) bool {
account := user.(*protocol.MemoryUser).Account.(*MemoryAccount)
aeadCipher = account.Cipher.(*AEADCipher)
ivLen = aeadCipher.IVSize()
subkey = subkey[:aeadCipher.KeyBytes]
hkdfSHA1(account.Key, bs[:ivLen], subkey)
aead = aeadCipher.AEADAuthCreator(subkey)
switch command {
case protocol.RequestCommandTCP:
ret, err = aead.Open(data[:0], data[4:16], bs[ivLen:ivLen+18], nil)
case protocol.RequestCommandUDP:
ret, err = aead.Open(data[:0], data[8180:8192], bs[ivLen:], nil)
}
if err == nil {
u = user.(*protocol.MemoryUser)
return false
}
return true
})
return
} }
// Get the only user without authentication func (v *Validator) GetBehaviorSeed() uint64 {
func (v *Validator) GetOnlyUser() (u *protocol.MemoryUser, ivLen int32) { v.Lock()
v.users.Range(func(_, user interface{}) bool { defer v.Unlock()
u = user.(*protocol.MemoryUser)
return false
})
ivLen = u.Account.(*MemoryAccount).Cipher.IVSize()
return v.behaviorFused = true
if v.behaviorSeed == 0 {
v.behaviorSeed = dice.RollUint64()
}
return v.behaviorSeed
} }

View File

@@ -4,8 +4,6 @@ import (
"context" "context"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -19,6 +17,7 @@ import (
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
) )
// Client is a Socks5 client. // Client is a Socks5 client.

View File

@@ -5,8 +5,6 @@ import (
"io" "io"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
@@ -20,6 +18,7 @@ import (
"github.com/xtls/xray-core/features" "github.com/xtls/xray-core/features"
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/udp" "github.com/xtls/xray-core/transport/internet/udp"
) )

View File

@@ -5,8 +5,6 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -22,6 +20,7 @@ import (
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/xtls" "github.com/xtls/xray-core/transport/internet/xtls"
) )
@@ -78,7 +77,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
if err != nil { if err != nil {
return newError("failed to find an available destination").AtWarning().Base(err) return newError("failed to find an available destination").AtWarning().Base(err)
} }
newError("tunneling request to ", destination, " via ", server.Destination()).WriteToLog(session.ExportIDToError(ctx)) newError("tunneling request to ", destination, " via ", server.Destination().NetAddr()).WriteToLog(session.ExportIDToError(ctx))
defer conn.Close() defer conn.Close()

View File

@@ -8,8 +8,6 @@ import (
"runtime" "runtime"
"syscall" "syscall"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -17,6 +15,7 @@ import (
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal" "github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/xtls" "github.com/xtls/xray-core/transport/internet/xtls"
) )

View File

@@ -8,8 +8,6 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -26,6 +24,7 @@ import (
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/internet/udp" "github.com/xtls/xray-core/transport/internet/udp"
"github.com/xtls/xray-core/transport/internet/xtls" "github.com/xtls/xray-core/transport/internet/xtls"

View File

@@ -9,8 +9,6 @@ import (
"runtime" "runtime"
"syscall" "syscall"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -19,6 +17,7 @@ import (
"github.com/xtls/xray-core/common/signal" "github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/proxy/vless" "github.com/xtls/xray-core/proxy/vless"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/xtls" "github.com/xtls/xray-core/transport/internet/xtls"
) )

View File

@@ -10,8 +10,6 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -31,6 +29,7 @@ import (
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/proxy/vless" "github.com/xtls/xray-core/proxy/vless"
"github.com/xtls/xray-core/proxy/vless/encoding" "github.com/xtls/xray-core/proxy/vless/encoding"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/internet/xtls" "github.com/xtls/xray-core/transport/internet/xtls"
) )

View File

@@ -7,8 +7,6 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -26,6 +24,7 @@ import (
"github.com/xtls/xray-core/proxy/vless/encoding" "github.com/xtls/xray-core/proxy/vless/encoding"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/xtls" "github.com/xtls/xray-core/transport/internet/xtls"
) )
@@ -104,7 +103,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
} }
target := outbound.Target target := outbound.Target
newError("tunneling request to ", target, " via ", rec.Destination()).AtInfo().WriteToLog(session.ExportIDToError(ctx)) newError("tunneling request to ", target, " via ", rec.Destination().NetAddr()).AtInfo().WriteToLog(session.ExportIDToError(ctx))
command := protocol.RequestCommandTCP command := protocol.RequestCommandTCP
if target.Network == net.Network_UDP { if target.Network == net.Network_UDP {

View File

@@ -1,6 +1,8 @@
package vmess package vmess
import ( import (
"strings"
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/uuid" "github.com/xtls/xray-core/common/uuid"
@@ -14,6 +16,9 @@ type MemoryAccount struct {
AlterIDs []*protocol.ID AlterIDs []*protocol.ID
// Security type of the account. Used for client connections. // Security type of the account. Used for client connections.
Security protocol.SecurityType Security protocol.SecurityType
AuthenticatedLengthExperiment bool
NoTerminationSignal bool
} }
// AnyValidID returns an ID that is either the main ID or one of the alternative IDs if any. // AnyValidID returns an ID that is either the main ID or one of the alternative IDs if any.
@@ -41,9 +46,18 @@ func (a *Account) AsAccount() (protocol.Account, error) {
return nil, newError("failed to parse ID").Base(err).AtError() return nil, newError("failed to parse ID").Base(err).AtError()
} }
protoID := protocol.NewID(id) protoID := protocol.NewID(id)
var AuthenticatedLength, NoTerminationSignal bool
if strings.Contains(a.TestsEnabled, "AuthenticatedLength") {
AuthenticatedLength = true
}
if strings.Contains(a.TestsEnabled, "NoTerminationSignal") {
NoTerminationSignal = true
}
return &MemoryAccount{ return &MemoryAccount{
ID: protoID, ID: protoID,
AlterIDs: protocol.NewAlterIDs(protoID, uint16(a.AlterId)), AlterIDs: protocol.NewAlterIDs(protoID, uint16(a.AlterId)),
Security: a.SecuritySettings.GetSecurityType(), Security: a.SecuritySettings.GetSecurityType(),
AuthenticatedLengthExperiment: AuthenticatedLength,
NoTerminationSignal: NoTerminationSignal,
}, nil }, nil
} }

View File

@@ -5,9 +5,10 @@ import (
"encoding/binary" "encoding/binary"
"hash/fnv" "hash/fnv"
"github.com/xtls/xray-core/common"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/crypto"
) )
// Authenticate authenticates a byte array using Fnv hash. // Authenticate authenticates a byte array using Fnv hash.
@@ -116,3 +117,11 @@ func (s *ShakeSizeParser) NextPaddingLen() uint16 {
func (s *ShakeSizeParser) MaxPaddingLen() uint16 { func (s *ShakeSizeParser) MaxPaddingLen() uint16 {
return 64 return 64
} }
type AEADSizeParser struct {
crypto.AEADChunkSizeParser
}
func NewAEADSizeParser(auth *crypto.AEADAuthenticator) *AEADSizeParser {
return &AEADSizeParser{crypto.AEADChunkSizeParser{Auth: auth}}
}

View File

@@ -20,6 +20,7 @@ import (
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/crypto" "github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/drain"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/proxy/vmess" "github.com/xtls/xray-core/proxy/vmess"
@@ -44,10 +45,12 @@ type ClientSession struct {
responseBodyIV [16]byte responseBodyIV [16]byte
responseReader io.Reader responseReader io.Reader
responseHeader byte responseHeader byte
readDrainer drain.Drainer
} }
// NewClientSession creates a new ClientSession. // NewClientSession creates a new ClientSession.
func NewClientSession(ctx context.Context, isAEAD bool, idHash protocol.IDHash) *ClientSession { func NewClientSession(ctx context.Context, isAEAD bool, idHash protocol.IDHash, behaviorSeed int64) *ClientSession {
session := &ClientSession{ session := &ClientSession{
isAEAD: isAEAD, isAEAD: isAEAD,
idHash: idHash, idHash: idHash,
@@ -68,6 +71,14 @@ func NewClientSession(ctx context.Context, isAEAD bool, idHash protocol.IDHash)
BodyIV := sha256.Sum256(session.requestBodyIV[:]) BodyIV := sha256.Sum256(session.requestBodyIV[:])
copy(session.responseBodyIV[:], BodyIV[:16]) copy(session.responseBodyIV[:], BodyIV[:16])
} }
{
var err error
session.readDrainer, err = drain.NewBehaviorSeedLimitedDrainer(behaviorSeed, 18, 3266, 64)
if err != nil {
newError("unable to initialize drainer").Base(err).WriteToLog()
session.readDrainer = drain.NewNopDrainer()
}
}
return session return session
} }
@@ -171,6 +182,17 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())), NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(), AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
} }
if request.Option.Has(protocol.RequestOptionAuthenticatedLength) {
AuthenticatedLengthKey := vmessaead.KDF16(c.requestBodyKey[:], "auth_len")
AuthenticatedLengthKeyAEAD := crypto.NewAesGcm(AuthenticatedLengthKey)
lengthAuth := &crypto.AEADAuthenticator{
AEAD: AuthenticatedLengthKeyAEAD,
NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
sizeParser = NewAEADSizeParser(lengthAuth)
}
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType(), padding) return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType(), padding)
case protocol.SecurityType_CHACHA20_POLY1305: case protocol.SecurityType_CHACHA20_POLY1305:
aead, err := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.requestBodyKey[:])) aead, err := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.requestBodyKey[:]))
@@ -181,6 +203,18 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())), NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(), AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
} }
if request.Option.Has(protocol.RequestOptionAuthenticatedLength) {
AuthenticatedLengthKey := vmessaead.KDF16(c.requestBodyKey[:], "auth_len")
AuthenticatedLengthKeyAEAD, err := chacha20poly1305.New(GenerateChacha20Poly1305Key(AuthenticatedLengthKey))
common.Must(err)
lengthAuth := &crypto.AEADAuthenticator{
AEAD: AuthenticatedLengthKeyAEAD,
NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
sizeParser = NewAEADSizeParser(lengthAuth)
}
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType(), padding) return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType(), padding)
default: default:
panic("Unknown security type.") panic("Unknown security type.")
@@ -202,12 +236,15 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
var decryptedResponseHeaderLength int var decryptedResponseHeaderLength int
var decryptedResponseHeaderLengthBinaryDeserializeBuffer uint16 var decryptedResponseHeaderLengthBinaryDeserializeBuffer uint16
if _, err := io.ReadFull(reader, aeadEncryptedResponseHeaderLength[:]); err != nil { if n, err := io.ReadFull(reader, aeadEncryptedResponseHeaderLength[:]); err != nil {
return nil, newError("Unable to Read Header Len").Base(err) c.readDrainer.AcknowledgeReceive(n)
return nil, drain.WithError(c.readDrainer, reader, newError("Unable to Read Header Len").Base(err))
} else { // nolint: golint
c.readDrainer.AcknowledgeReceive(n)
} }
if decryptedResponseHeaderLengthBinaryBuffer, err := aeadResponseHeaderLengthEncryptionAEAD.Open(nil, aeadResponseHeaderLengthEncryptionIV, aeadEncryptedResponseHeaderLength[:], nil); err != nil { if decryptedResponseHeaderLengthBinaryBuffer, err := aeadResponseHeaderLengthEncryptionAEAD.Open(nil, aeadResponseHeaderLengthEncryptionIV, aeadEncryptedResponseHeaderLength[:], nil); err != nil {
return nil, newError("Failed To Decrypt Length").Base(err) return nil, drain.WithError(c.readDrainer, reader, newError("Failed To Decrypt Length").Base(err))
} else { } else { // nolint: golint
common.Must(binary.Read(bytes.NewReader(decryptedResponseHeaderLengthBinaryBuffer), binary.BigEndian, &decryptedResponseHeaderLengthBinaryDeserializeBuffer)) common.Must(binary.Read(bytes.NewReader(decryptedResponseHeaderLengthBinaryBuffer), binary.BigEndian, &decryptedResponseHeaderLengthBinaryDeserializeBuffer))
decryptedResponseHeaderLength = int(decryptedResponseHeaderLengthBinaryDeserializeBuffer) decryptedResponseHeaderLength = int(decryptedResponseHeaderLengthBinaryDeserializeBuffer)
} }
@@ -220,13 +257,16 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
encryptedResponseHeaderBuffer := make([]byte, decryptedResponseHeaderLength+16) encryptedResponseHeaderBuffer := make([]byte, decryptedResponseHeaderLength+16)
if _, err := io.ReadFull(reader, encryptedResponseHeaderBuffer); err != nil { if n, err := io.ReadFull(reader, encryptedResponseHeaderBuffer); err != nil {
return nil, newError("Unable to Read Header Data").Base(err) c.readDrainer.AcknowledgeReceive(n)
return nil, drain.WithError(c.readDrainer, reader, newError("Unable to Read Header Data").Base(err))
} else { // nolint: golint
c.readDrainer.AcknowledgeReceive(n)
} }
if decryptedResponseHeaderBuffer, err := aeadResponseHeaderPayloadEncryptionAEAD.Open(nil, aeadResponseHeaderPayloadEncryptionIV, encryptedResponseHeaderBuffer, nil); err != nil { if decryptedResponseHeaderBuffer, err := aeadResponseHeaderPayloadEncryptionAEAD.Open(nil, aeadResponseHeaderPayloadEncryptionIV, encryptedResponseHeaderBuffer, nil); err != nil {
return nil, newError("Failed To Decrypt Payload").Base(err) return nil, drain.WithError(c.readDrainer, reader, newError("Failed To Decrypt Payload").Base(err))
} else { } else { // nolint: golint
c.responseReader = bytes.NewReader(decryptedResponseHeaderBuffer) c.responseReader = bytes.NewReader(decryptedResponseHeaderBuffer)
} }
} }
@@ -312,6 +352,17 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
NonceGenerator: GenerateChunkNonce(c.responseBodyIV[:], uint32(aead.NonceSize())), NonceGenerator: GenerateChunkNonce(c.responseBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(), AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
} }
if request.Option.Has(protocol.RequestOptionAuthenticatedLength) {
AuthenticatedLengthKey := vmessaead.KDF16(c.requestBodyKey[:], "auth_len")
AuthenticatedLengthKeyAEAD := crypto.NewAesGcm(AuthenticatedLengthKey)
lengthAuth := &crypto.AEADAuthenticator{
AEAD: AuthenticatedLengthKeyAEAD,
NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
sizeParser = NewAEADSizeParser(lengthAuth)
}
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType(), padding) return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType(), padding)
case protocol.SecurityType_CHACHA20_POLY1305: case protocol.SecurityType_CHACHA20_POLY1305:
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.responseBodyKey[:])) aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.responseBodyKey[:]))
@@ -321,6 +372,18 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
NonceGenerator: GenerateChunkNonce(c.responseBodyIV[:], uint32(aead.NonceSize())), NonceGenerator: GenerateChunkNonce(c.responseBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(), AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
} }
if request.Option.Has(protocol.RequestOptionAuthenticatedLength) {
AuthenticatedLengthKey := vmessaead.KDF16(c.requestBodyKey[:], "auth_len")
AuthenticatedLengthKeyAEAD, err := chacha20poly1305.New(GenerateChacha20Poly1305Key(AuthenticatedLengthKey))
common.Must(err)
lengthAuth := &crypto.AEADAuthenticator{
AEAD: AuthenticatedLengthKeyAEAD,
NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
sizeParser = NewAEADSizeParser(lengthAuth)
}
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType(), padding) return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType(), padding)
default: default:
panic("Unknown security type.") panic("Unknown security type.")

View File

@@ -13,9 +13,11 @@ import (
) )
var ( var (
ErrCommandTypeMismatch = newError("Command type mismatch.")
ErrUnknownCommand = newError("Unknown command.")
ErrCommandTooLarge = newError("Command too large.") ErrCommandTooLarge = newError("Command too large.")
ErrCommandTypeMismatch = newError("Command type mismatch.")
ErrInvalidAuth = newError("Invalid auth.")
ErrInsufficientLength = newError("Insufficient length.")
ErrUnknownCommand = newError("Unknown command.")
) )
func MarshalCommand(command interface{}, writer io.Writer) error { func MarshalCommand(command interface{}, writer io.Writer) error {
@@ -54,12 +56,12 @@ func MarshalCommand(command interface{}, writer io.Writer) error {
func UnmarshalCommand(cmdID byte, data []byte) (protocol.ResponseCommand, error) { func UnmarshalCommand(cmdID byte, data []byte) (protocol.ResponseCommand, error) {
if len(data) <= 4 { if len(data) <= 4 {
return nil, newError("insufficient length") return nil, ErrInsufficientLength
} }
expectedAuth := Authenticate(data[4:]) expectedAuth := Authenticate(data[4:])
actualAuth := binary.BigEndian.Uint32(data[:4]) actualAuth := binary.BigEndian.Uint32(data[:4])
if expectedAuth != actualAuth { if expectedAuth != actualAuth {
return nil, newError("invalid auth") return nil, ErrInvalidAuth
} }
var factory CommandFactory var factory CommandFactory
@@ -109,38 +111,38 @@ func (f *CommandSwitchAccountFactory) Marshal(command interface{}, writer io.Wri
func (f *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) { func (f *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) {
cmd := new(protocol.CommandSwitchAccount) cmd := new(protocol.CommandSwitchAccount)
if len(data) == 0 { if len(data) == 0 {
return nil, newError("insufficient length.") return nil, ErrInsufficientLength
} }
lenHost := int(data[0]) lenHost := int(data[0])
if len(data) < lenHost+1 { if len(data) < lenHost+1 {
return nil, newError("insufficient length.") return nil, ErrInsufficientLength
} }
if lenHost > 0 { if lenHost > 0 {
cmd.Host = net.ParseAddress(string(data[1 : 1+lenHost])) cmd.Host = net.ParseAddress(string(data[1 : 1+lenHost]))
} }
portStart := 1 + lenHost portStart := 1 + lenHost
if len(data) < portStart+2 { if len(data) < portStart+2 {
return nil, newError("insufficient length.") return nil, ErrInsufficientLength
} }
cmd.Port = net.PortFromBytes(data[portStart : portStart+2]) cmd.Port = net.PortFromBytes(data[portStart : portStart+2])
idStart := portStart + 2 idStart := portStart + 2
if len(data) < idStart+16 { if len(data) < idStart+16 {
return nil, newError("insufficient length.") return nil, ErrInsufficientLength
} }
cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16]) cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16])
alterIDStart := idStart + 16 alterIDStart := idStart + 16
if len(data) < alterIDStart+2 { if len(data) < alterIDStart+2 {
return nil, newError("insufficient length.") return nil, ErrInsufficientLength
} }
cmd.AlterIds = binary.BigEndian.Uint16(data[alterIDStart : alterIDStart+2]) cmd.AlterIds = binary.BigEndian.Uint16(data[alterIDStart : alterIDStart+2])
levelStart := alterIDStart + 2 levelStart := alterIDStart + 2
if len(data) < levelStart+1 { if len(data) < levelStart+1 {
return nil, newError("insufficient length.") return nil, ErrInsufficientLength
} }
cmd.Level = uint32(data[levelStart]) cmd.Level = uint32(data[levelStart])
timeStart := levelStart + 1 timeStart := levelStart + 1
if len(data) < timeStart { if len(data) < timeStart+1 {
return nil, newError("insufficient length.") return nil, ErrInsufficientLength
} }
cmd.ValidMin = data[timeStart] cmd.ValidMin = data[timeStart]
return cmd, nil return cmd, nil

Some files were not shown because too many files have changed in this diff Show More