diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..cdf33594 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,70 @@ +name: "CodeQL" + +on: + push: + branches: [master] + paths: + - "**/*.go" + pull_request: + # The branches below must be a subset of the branches above + branches: [master] + paths: + - "**/*.go" + schedule: + - cron: '0 0 * * 1' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + # Override automatic language detection by changing the below list + # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] + language: ['go'] + # Learn more... + # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 84bf2365..bdf74bb1 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -3,9 +3,13 @@ name: Linter on: push: branches: [master] + paths: + - "**/*.go" pull_request: branches: [master] types: [opened, synchronize, reopened] + paths: + - "**/*.go" jobs: lint: @@ -19,29 +23,8 @@ jobs: - name: Checkout codebase uses: actions/checkout@v2 - - name: Cache go module - uses: actions/cache@v2 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: ${{ runner.os }}-go- - - - name: Lint other files - if: ${{ always() }} - uses: github/super-linter@v3.10.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - VALIDATE_ALL_CODEBASE: false - VALIDATE_BASH: false - VALIDATE_DOCKERFILE: false - VALIDATE_DOCKERFILE_HADOLINT: false - VALIDATE_GO: false - VALIDATE_JSON: false - VALIDATE_MD: false - VALIDATE_PROTOBUF: false - - name: golangci-lint uses: golangci/golangci-lint-action@v2 with: version: v1.31 - args: --config=.github/linters/.golangci.yml \ No newline at end of file + args: --config=.github/linters/.golangci.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ef5b0eab..34eb103b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -8,7 +8,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v3.0.10 + - uses: actions/stale@v3.0.11 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: "This issue is stale because it has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days" diff --git a/app/router/condition.go b/app/router/condition.go index 5db1fa3c..c77fc657 100644 --- a/app/router/condition.go +++ b/app/router/condition.go @@ -288,17 +288,11 @@ func NewAttributeMatcher(code string) (*AttributeMatcher, error) { }, nil } -func (m *AttributeMatcher) Match(attrs map[string]interface{}) bool { +// Match implements attributes matching. +func (m *AttributeMatcher) Match(attrs map[string]string) bool { attrsDict := new(starlark.Dict) for key, value := range attrs { - var starValue starlark.Value - switch value := value.(type) { - case string: - starValue = starlark.String(value) - } - if starValue != nil { - attrsDict.SetKey(starlark.String(key), starValue) - } + attrsDict.SetKey(starlark.String(key), starlark.String(value)) } predefined := make(starlark.StringDict) diff --git a/app/router/condition_test.go b/app/router/condition_test.go index caef7367..af055bb4 100644 --- a/app/router/condition_test.go +++ b/app/router/condition_test.go @@ -313,7 +313,7 @@ func TestRoutingRule(t *testing.T) { }, test: []ruleTest{ { - input: withContent(&session.Content{Protocol: "http/1.1", Attributes: map[string]interface{}{":path": "/test/1"}}), + input: withContent(&session.Content{Protocol: "http/1.1", Attributes: map[string]string{":path": "/test/1"}}), output: true, }, }, diff --git a/common/session/session.go b/common/session/session.go index 8d7b1ff6..17b461d5 100644 --- a/common/session/session.go +++ b/common/session/session.go @@ -53,6 +53,7 @@ type Outbound struct { Gateway net.Address } +// SniffingRequest controls the behavior of content sniffing. type SniffingRequest struct { OverrideDestinationForProtocol []string Enabled bool @@ -65,7 +66,7 @@ type Content struct { SniffingRequest SniffingRequest - Attributes map[string]interface{} + Attributes map[string]string SkipRoutePick bool } @@ -76,16 +77,18 @@ type Sockopt struct { Mark int32 } -func (c *Content) SetAttribute(name string, value interface{}) { +// SetAttribute attachs additional string attributes to content. +func (c *Content) SetAttribute(name string, value string) { if c.Attributes == nil { - c.Attributes = make(map[string]interface{}) + c.Attributes = make(map[string]string) } c.Attributes[name] = value } -func (c *Content) Attribute(name string) interface{} { +// Attribute retrieves additional string attributes from content. +func (c *Content) Attribute(name string) string { if c.Attributes == nil { - return nil + return "" } return c.Attributes[name] } diff --git a/core.go b/core.go index aa6972c1..df47249a 100644 --- a/core.go +++ b/core.go @@ -19,7 +19,7 @@ import ( ) var ( - version = "4.28.0" + version = "4.28.2" build = "Custom" codename = "V2Fly, a community-driven edition of V2Ray." intro = "A unified platform for anti-censorship." diff --git a/features/routing/context.go b/features/routing/context.go index b4adabaf..8fea1915 100644 --- a/features/routing/context.go +++ b/features/routing/context.go @@ -6,7 +6,7 @@ import ( // Context is a feature to store connection information for routing. // -// v2ray:api:beta +// v2ray:api:stable type Context interface { // GetInboundTag returns the tag of the inbound the connection was from. GetInboundTag() string @@ -36,5 +36,5 @@ type Context interface { GetUser() string // GetAttributes returns extra attributes from the conneciont content. - GetAttributes() map[string]interface{} + GetAttributes() map[string]string } diff --git a/features/routing/session/context.go b/features/routing/session/context.go index 6d61d4f9..bd5bb633 100644 --- a/features/routing/session/context.go +++ b/features/routing/session/context.go @@ -95,14 +95,14 @@ func (ctx *Context) GetProtocol() string { // GetUser implements routing.Context. func (ctx *Context) GetUser() string { - if ctx.Inbound == nil { + if ctx.Inbound == nil || ctx.Inbound.User == nil { return "" } return ctx.Inbound.User.Email } // GetAttributes implements routing.Context. -func (ctx *Context) GetAttributes() map[string]interface{} { +func (ctx *Context) GetAttributes() map[string]string { if ctx.Content == nil { return nil } diff --git a/proxy/http/client.go b/proxy/http/client.go index dd30ff36..745ddcfd 100644 --- a/proxy/http/client.go +++ b/proxy/http/client.go @@ -210,9 +210,10 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u } cachedH2Mutex.Lock() - defer cachedH2Mutex.Unlock() + cachedConn, cachedConnFound := cachedH2Conns[dest] + cachedH2Mutex.Unlock() - if cachedConn, found := cachedH2Conns[dest]; found { + if cachedConnFound { rc, cc := cachedConn.rawConn, cachedConn.h2Conn if cc.CanTakeNewRequest() { proxyConn, err := connectHTTP2(rc, cc) @@ -260,6 +261,7 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u return nil, err } + cachedH2Mutex.Lock() if cachedH2Conns == nil { cachedH2Conns = make(map[net.Destination]h2Conn) } @@ -268,6 +270,7 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u rawConn: rawConn, h2Conn: h2clientConn, } + cachedH2Mutex.Unlock() return proxyConn, err default: diff --git a/proxy/vmess/encoding/client.go b/proxy/vmess/encoding/client.go index 96808622..cdff7c8a 100644 --- a/proxy/vmess/encoding/client.go +++ b/proxy/vmess/encoding/client.go @@ -12,6 +12,7 @@ import ( "hash" "hash/fnv" "io" + "os" vmessaead "v2ray.com/core/proxy/vmess/aead" "golang.org/x/crypto/chacha20poly1305" @@ -62,6 +63,12 @@ func NewClientSession(idHash protocol.IDHash, ctx context.Context) *ClientSessio } } + if vmessAeadDisable, vmessAeadDisableFound := os.LookupEnv("V2RAY_VMESS_AEAD_DISABLED"); vmessAeadDisableFound { + if vmessAeadDisable == "true" { + session.isAEADRequest = false + } + } + copy(session.requestBodyKey[:], randomBytes[:16]) copy(session.requestBodyIV[:], randomBytes[16:32]) session.responseHeader = randomBytes[32] @@ -71,7 +78,7 @@ func NewClientSession(idHash protocol.IDHash, ctx context.Context) *ClientSessio } else { BodyKey := sha256.Sum256(session.requestBodyKey[:]) copy(session.responseBodyKey[:], BodyKey[:16]) - BodyIV := sha256.Sum256(session.requestBodyKey[:]) + BodyIV := sha256.Sum256(session.requestBodyIV[:]) copy(session.responseBodyIV[:], BodyIV[:16]) } diff --git a/proxy/vmess/encoding/server.go b/proxy/vmess/encoding/server.go index 11146cd6..680f35ef 100644 --- a/proxy/vmess/encoding/server.go +++ b/proxy/vmess/encoding/server.go @@ -374,7 +374,7 @@ func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, wr } else { BodyKey := sha256.Sum256(s.requestBodyKey[:]) copy(s.responseBodyKey[:], BodyKey[:16]) - BodyIV := sha256.Sum256(s.requestBodyKey[:]) + BodyIV := sha256.Sum256(s.requestBodyIV[:]) copy(s.responseBodyIV[:], BodyIV[:16]) }