From 9c0705f3108dccc1b9aa64ff4bc97bcc3fb7e8dc Mon Sep 17 00:00:00 2001 From: gVisor bot Date: Wed, 26 Jan 2022 14:02:10 +0800 Subject: [PATCH 1/4] [Refactor] logic rule parse --- rule/logic/and.go | 2 +- rule/logic/common.go | 89 ++++++++++++++++++-------------------------- rule/logic/not.go | 2 +- rule/logic/or.go | 2 +- 4 files changed, 39 insertions(+), 56 deletions(-) diff --git a/rule/logic/and.go b/rule/logic/and.go index f75de048..01862e51 100644 --- a/rule/logic/and.go +++ b/rule/logic/and.go @@ -11,7 +11,7 @@ type AND struct { func NewAND(payload string, adapter string) (*AND, error) { and := &AND{payload: payload, adapter: adapter} - rules, err := parseRule(payload) + rules, err := parseRuleByPayload(payload) if err != nil { return nil, err } diff --git a/rule/logic/common.go b/rule/logic/common.go index 4c1aa44c..11d67915 100644 --- a/rule/logic/common.go +++ b/rule/logic/common.go @@ -10,63 +10,29 @@ import ( "strings" ) -func parseRule(payload string) ([]C.Rule, error) { +func parseRuleByPayload(payload string) ([]C.Rule, error) { regex, err := regexp.Compile("\\(.*\\)") if err != nil { return nil, err } if regex.MatchString(payload) { - subRanges, err := format(payload) + subAllRanges, err := format(payload) if err != nil { return nil, err } - rules := make([]C.Rule, 0, len(subRanges)) + rules := make([]C.Rule, 0, len(subAllRanges)) + + subRanges := findSubRuleRange(payload, subAllRanges) + for _, subRange := range subRanges { + subPayload := payload[subRange.start+1 : subRange.end] - if len(subRanges) == 1 { - subPayload := payload[subRanges[0].start+1 : subRanges[0].end-1] rule, err := payloadToRule(subPayload) if err != nil { return nil, err } rules = append(rules, rule) - } else { - preStart := subRanges[0].start - preEnd := subRanges[0].end - for _, sr := range subRanges[1:] { - if containRange(sr, preStart, preEnd) && sr.start-preStart > 1 { - str := "" - if preStart+1 <= sr.start-1 { - str = strings.TrimSpace(payload[preStart+1 : sr.start-1]) - } - - if str == "AND" || str == "OR" || str == "NOT" { - subPayload := payload[preStart+1 : preEnd] - rule, err := payloadToRule(subPayload) - if err != nil { - return nil, err - } - - rules = append(rules, rule) - preStart = sr.start - preEnd = sr.end - } - - continue - } - - preStart = sr.start - preEnd = sr.end - - subPayload := payload[sr.start+1 : sr.end] - rule, err := payloadToRule(subPayload) - if err != nil { - return nil, err - } - - rules = append(rules, rule) - } } return rules, nil @@ -84,23 +50,14 @@ func payloadToRule(subPayload string) (C.Rule, error) { tp := splitStr[0] payload := splitStr[1] if tp == "NOT" || tp == "OR" || tp == "AND" { - return parseSubRule(tp, payload, nil) + return parseRule(tp, payload, nil) } param := strings.Split(payload, ",") - return parseSubRule(tp, param[0], param[1:]) + return parseRule(tp, param[0], param[1:]) } -func splitSubRule(subRuleStr string) (string, string, []string, error) { - typeAndRule := strings.Split(subRuleStr, ",") - if len(typeAndRule) < 2 { - return "", "", nil, fmt.Errorf("format error:[%s]", typeAndRule) - } - - return strings.TrimSpace(typeAndRule[0]), strings.TrimSpace(typeAndRule[1]), typeAndRule[2:], nil -} - -func parseSubRule(tp, payload string, params []string) (C.Rule, error) { +func parseRule(tp, payload string, params []string) (C.Rule, error) { var ( parseErr error parsed C.Rule @@ -183,3 +140,29 @@ func format(payload string) ([]Range, error) { return sortResult, nil } + +func findSubRuleRange(payload string, ruleRanges []Range) []Range { + payloadLen := len(payload) + subRuleRange := make([]Range, 0) + for _, rr := range ruleRanges { + if rr.start == 0 && rr.end == payloadLen-1 { + // 最大范围跳过 + continue + } + + containInSub := false + for _, r := range subRuleRange { + if containRange(rr, r.start, r.end) { + // The subRuleRange contains a range of rr, which is the next level node of the tree + containInSub = true + break + } + } + + if !containInSub { + subRuleRange = append(subRuleRange, rr) + } + } + + return subRuleRange +} diff --git a/rule/logic/not.go b/rule/logic/not.go index 94ca0e3c..79102d4e 100644 --- a/rule/logic/not.go +++ b/rule/logic/not.go @@ -13,7 +13,7 @@ type NOT struct { func NewNOT(payload string, adapter string) (*NOT, error) { not := &NOT{payload: payload, adapter: adapter} - rule, err := parseRule(payload) + rule, err := parseRuleByPayload(payload) if err != nil { return nil, err } diff --git a/rule/logic/or.go b/rule/logic/or.go index fb38a20f..3822e315 100644 --- a/rule/logic/or.go +++ b/rule/logic/or.go @@ -41,7 +41,7 @@ func (or *OR) RuleExtra() *C.RuleExtra { func NewOR(payload string, adapter string) (*OR, error) { or := &OR{payload: payload, adapter: adapter} - rules, err := parseRule(payload) + rules, err := parseRuleByPayload(payload) if err != nil { return nil, err } From 8663c1734559da12f9cf829fb1c1c0ad896bbb31 Mon Sep 17 00:00:00 2001 From: gVisor bot Date: Wed, 26 Jan 2022 21:29:22 +0800 Subject: [PATCH 2/4] github action build config --- .github/workflows/dev.yml | 44 +++++++++++++++++++++++++++++++++++++++ Makefile | 14 ++++++++++--- 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/dev.yml diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml new file mode 100644 index 00000000..1c0b0a62 --- /dev/null +++ b/.github/workflows/dev.yml @@ -0,0 +1,44 @@ +name: Dev +on: [push] +jobs: + dev-build: + if: ${{ !contains(github.event.head_commit.message, '[Skip CI]') }} + runs-on: ubuntu-latest + steps: + - name: Get latest go version + id: version + run: | + echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: ${{ steps.version.outputs.go_version }} + + - name: Check out code into the Go module directory + 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: Get dependencies, run test +# run: | +# go test ./... + - name: Build + if: success() + env: + NAME: Clash.Meta + BINDIR: bin + run: make -j releases + + - name: Upload Dev + uses: softprops/action-gh-release@v1 + if: ${{ env.GIT_BRANCH != 'Meta' && success() }} + with: + tag_name: develop + files: bin/* + prerelease: true + diff --git a/Makefile b/Makefile index f547164e..7c2a5980 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,10 @@ NAME=Clash.Meta BINDIR=bin -VERSION=$(shell git describe --tags || echo "unknown version") +BRANCH=$(shell git rev-parse --abbrev-ref HEAD) +VERSION=$(shell git describe --tags || echo "unknown version" ) +ifeq ($(BRANCH),Dev) +VERSION=develop-$(shell git rev-parse --short HEAD) +endif BUILDTIME=$(shell date -u) AUTOIPTABLES=Enable GOBUILD=CGO_ENABLED=0 go build -trimpath -ldflags '-X "github.com/Dreamacro/clash/constant.Version=$(VERSION)" \ @@ -38,7 +42,11 @@ WINDOWS_ARCH_LIST = \ windows-arm32v7 -all: linux-arm64-AutoIptables linux-amd64-AutoIptables linux-arm64 linux-amd64 darwin-amd64 darwin-arm64 windows-amd64 windows-386 # Most used +all:linux-amd64-AutoIptables linux-amd64\ + linux-arm64 linux-arm64-AutoIptables linux-armv7\ + darwin-amd64 darwin-arm64\ + windows-amd64 windows-386 \ + linux-mips-hardfloat linux-mips-softfloat linux-mips64 linux-mips64le linux-mipsle-hardfloat linux-mipsle-softfloat# Most used docker: $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ @@ -141,4 +149,4 @@ all-arch: $(PLATFORM_LIST) $(WINDOWS_ARCH_LIST) releases: $(gz_releases) $(zip_releases) clean: - rm $(BINDIR)/* \ No newline at end of file + rm $(BINDIR)/* From b79eb1cea964829f287d77af13ff63b1fe872021 Mon Sep 17 00:00:00 2001 From: gVisor bot Date: Fri, 4 Feb 2022 16:45:23 +0800 Subject: [PATCH 3/4] [Fixed] Abnormal rule when host is ip addr --- adapter/inbound/socket.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index f761bd9b..cca260c6 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -26,10 +26,20 @@ func NewInner(conn net.Conn, dst string, host string) *context.ConnContext { metadata.NetWork = C.TCP metadata.Type = C.INNER metadata.DNSMode = C.DNSMapping - metadata.AddrType = C.AtypDomainName metadata.Host = host - if _, port, err := parseAddr(dst); err == nil { + metadata.AddrType = C.AtypDomainName + + if ip, port, err := parseAddr(dst); err == nil { metadata.DstPort = port + if host == "" { + metadata.DstIP = ip + if ip.To4() == nil { + metadata.AddrType = C.AtypIPv6 + } else { + metadata.AddrType = C.AtypIPv4 + } + } } + return context.NewConnContext(conn, metadata) } From a8dafd434eb75525f6aa8559f40b6375cf4cd0d9 Mon Sep 17 00:00:00 2001 From: gVisor bot Date: Fri, 4 Feb 2022 17:36:34 +0800 Subject: [PATCH 4/4] [Fixed] Fixed clash process name is `Clash.Meta` --- adapter/inbound/socket.go | 2 +- constant/version.go | 1 + rule/common/process.go | 34 ++++++++++++++++++---------------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index cca260c6..ebb2095e 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -28,7 +28,7 @@ func NewInner(conn net.Conn, dst string, host string) *context.ConnContext { metadata.DNSMode = C.DNSMapping metadata.Host = host metadata.AddrType = C.AtypDomainName - + metadata.Process = C.ClashName if ip, port, err := parseAddr(dst); err == nil { metadata.DstPort = port if host == "" { diff --git a/constant/version.go b/constant/version.go index 5a511382..1d4e6e7b 100644 --- a/constant/version.go +++ b/constant/version.go @@ -5,4 +5,5 @@ var ( Version = "1.9.0" BuildTime = "unknown time" AutoIptables string + ClashName = "Clash.Meta" ) diff --git a/rule/common/process.go b/rule/common/process.go index 47731443..669714ec 100644 --- a/rule/common/process.go +++ b/rule/common/process.go @@ -35,26 +35,28 @@ func (ps *Process) Match(metadata *C.Metadata) bool { } key := fmt.Sprintf("%s:%s:%s", metadata.NetWork.String(), metadata.SrcIP.String(), metadata.SrcPort) - cached, hit := processCache.Get(key) - if !hit { - srcPort, err := strconv.Atoi(metadata.SrcPort) - if err != nil { - processCache.Set(key, "") - return false + if strings.TrimSpace(metadata.Process) == "" { + cached, hit := processCache.Get(key) + if !hit { + srcPort, err := strconv.Atoi(metadata.SrcPort) + if err != nil { + processCache.Set(key, "") + return false + } + + name, err := process.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, srcPort) + if err != nil { + log.Debugln("[Rule] find process name %s error: %s", C.Process.String(), err.Error()) + } + + processCache.Set(key, name) + + cached = name } - name, err := process.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, srcPort) - if err != nil { - log.Debugln("[Rule] find process name %s error: %s", C.Process.String(), err.Error()) - } - - processCache.Set(key, name) - - cached = name + metadata.Process = cached.(string) } - metadata.Process = cached.(string) - return strings.EqualFold(metadata.Process, ps.process) }