Chore: script built

This commit is contained in:
yaling888 2021-10-21 20:22:23 +08:00
parent cbea46b0c8
commit 63d07db4bf
17 changed files with 139 additions and 249 deletions

View file

@ -29,6 +29,26 @@ jobs:
- name: Get dependencies, run test and static check
run: |
# fetch python cross compile source files
mkdir -p bin/python/
cd bin/python/
curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-darwin-amd64.tar.xz
curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-darwin-arm64.tar.xz
curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-windows-amd64.tar.xz
curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-windows-386.tar.xz
curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-linux-amd64.tar.xz
curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-linux-arm64.tar.xz
#curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-linux-386.tar.xz
tar -Jxf python-3.9.7-darwin-amd64.tar.xz
tar -Jxf python-3.9.7-darwin-arm64.tar.xz
tar -Jxf python-3.9.7-windows-amd64.tar.xz
tar -Jxf python-3.9.7-windows-386.tar.xz
tar -Jxf python-3.9.7-linux-amd64.tar.xz
tar -Jxf python-3.9.7-linux-arm64.tar.xz
#tar -Jxf python-3.9.7-linux-386.tar.xz
rm python-3.9.7-*.tar.xz
cd ../../
go test ./...
go vet ./...
go install honnef.co/go/tools/cmd/staticcheck@latest
@ -41,6 +61,8 @@ jobs:
- name: SSH connection to Actions
uses: P3TERX/ssh2actions@v1.0.0
if: github.actor == github.repository_owner && contains(github.event.head_commit.message, '[ssh]')
env:
SSH_PASSWORD: ${{ secrets.ADAWADLHIOH }}
- name: Build
#if: startsWith(github.ref, 'refs/tags/')
@ -48,11 +70,12 @@ jobs:
NAME: clash
BINDIR: bin
run: |
make cleancache && make -j releases
make -j releases
- name: Prepare upload
if: startsWith(github.ref, 'refs/tags/') == false
run: |
rm -rf bin/python/
echo "FILE_DATE=_$(date +"%Y%m%d%H%M")" >> $GITHUB_ENV
echo "FILE_SHA=$(git describe --tags --always 2>/dev/null)" >> $GITHUB_ENV
@ -83,6 +106,6 @@ jobs:
with:
keep_latest: 1
delete_tags: true
delete_tag_pattern: premium
delete_tag_pattern: plus-pro
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -16,27 +16,29 @@ STATIC_LDFLAGS='-X "github.com/Dreamacro/clash/constant.Version=$(VERSION)" \
-w -s -buildid='
PLATFORM_LIST = \
darwin-10.12-amd64 \
darwin-10.15-arm64 \
linux-386 \
darwin-amd64 \
darwin-arm64 \
linux-amd64 \
linux-arm64
# linux-386
WINDOWS_ARCH_LIST = \
windows-4.0-amd64 \
windows-4.0-386
windows-amd64 \
windows-386
# windows-arm64
all: linux-amd64 darwin-10.12-amd64 windows-4.0-amd64 # Most used
all: linux-amd64 darwin-amd64 windows-amd64 # Most used
build:
$(GOBUILD) -ldflags $(RELEASE_LDFLAGS) -o $(BINDIR)/$(NAME)-$@
$(GOBUILD) -ldflags $(RELEASE_LDFLAGS) -tags build_local -o $(BINDIR)/$(NAME)-$@
darwin-10.12-amd64:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=darwin-10.12/amd64 $(BUILD_PACKAGE)
darwin-amd64:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=darwin-10.12/amd64 $(BUILD_PACKAGE) && \
mv $(BINDIR)/$(NAME)-darwin-10.12-amd64 $(BINDIR)/$(NAME)-darwin-amd64
darwin-10.15-arm64:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=darwin-10.15/arm64 $(BUILD_PACKAGE)
darwin-arm64:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=darwin-11.1/arm64 $(BUILD_PACKAGE) && \
mv $(BINDIR)/$(NAME)-darwin-11.1-arm64 $(BINDIR)/$(NAME)-darwin-arm64
linux-386:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(STATIC_LDFLAGS) -targets=linux/386 $(BUILD_PACKAGE)
@ -48,14 +50,17 @@ linux-amd64:
linux-arm64:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(STATIC_LDFLAGS) -targets=linux/arm64 $(BUILD_PACKAGE)
windows-4.0-386:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=windows-4.0/386 $(BUILD_PACKAGE)
windows-386:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=windows-4.0/386 $(BUILD_PACKAGE) && \
mv $(BINDIR)/$(NAME)-windows-4.0-386.exe $(BINDIR)/$(NAME)-windows-386.exe
windows-4.0-amd64:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=windows-4.0/amd64 $(BUILD_PACKAGE)
windows-amd64:
$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=windows-4.0/amd64 $(BUILD_PACKAGE) && \
mv $(BINDIR)/$(NAME)-windows-4.0-amd64.exe $(BINDIR)/$(NAME)-windows-amd64.exe
#windows-arm64:
# $(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(RELEASE_LDFLAGS) -targets=windows/arm64 $(BUILD_PACKAGE)
# mv $(NAME)-windows-4.0-arm64.exe $(NAME)-windows-arm64.exe
gz_releases=$(addsuffix .gz, $(PLATFORM_LIST))
zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST))

View file

@ -67,17 +67,17 @@ script:
privacy: '"analytics" in host or "adservice" in host or "firebase" in host or "safebrowsing" in host or "doubleclick" in host'
rules:
# network condition for all rules
# rule SCRIPT
- SCRIPT,quic,REJECT # Disable QUIC, same as rule "DST-PORT,443,REJECT,udp"
- SCRIPT,privacy,REJECT
# network(tcp/udp) condition for all rules
- DOMAIN-SUFFIX,bilibili.com,DIRECT,tcp
- DOMAIN-SUFFIX,bilibili.com,REJECT,udp
# multiport condition for rules SRC-PORT and DST-PORT
- DST-PORT,123/136/137-139,DIRECT,udp
# rule SCRIPT
- SCRIPT,quic,REJECT # Disable QUIC, same as rule "- DST-PORT,443,REJECT,udp"
- SCRIPT,privacy,REJECT
# rule GEOSITE
- GEOSITE,category-ads-all,REJECT
- GEOSITE,icloud@cn,DIRECT
@ -106,7 +106,7 @@ Script enables users to programmatically select a policy for the packets with mo
mode: script
rules:
# the rule GEOSITE just as a rule provider in script mode
# the rule GEOSITE just as a rule provider in mode script
- GEOSITE,category-ads-all,Whatever
- GEOSITE,youtube,Whatever
- GEOSITE,geolocation-cn,Whatever
@ -138,7 +138,7 @@ script:
if ctx.rule_providers["geosite:geolocation-cn"].match(metadata):
ctx.log('[Script] domain %s matched geolocation-cn' % host)
return "CN"
return "DIRECT"
ip = metadata["dst_ip"]
if host != "":
@ -153,23 +153,23 @@ script:
return "Proxy" # default policy for requests which are not matched by any other script
```
the context and metadata
```python
```ts
interface Metadata {
type: string // socks5、http
network: string // tcp
host: string
process_name: string
src_ip: string
src_port: int
dst_ip: string
dst_port: int
type: string // socks5、http
network: string // tcp
host: string
process_name: string
src_ip: string
src_port: int
dst_ip: string
dst_port: int
}
interface Context {
resolve_ip: (host: string) => string // ip string
geoip: (ip: string) => string // country code
log: (log: string) => void
rule_providers: Record<string, { match: (metadata: Metadata) => boolean }>
resolve_ip: (host: string) => string // ip string
geoip: (ip: string) => string // country code
log: (log: string) => void
rule_providers: Record<string, { match: (metadata: Metadata) => boolean }>
}
```
@ -219,7 +219,7 @@ Create user given name `clash`.
Run Clash by user `clash` as a daemon.
Create the systemd configuration file at /etc/systemd/system/clash.service:
```shell
```
[Unit]
Description=Clash daemon, A rule-based proxy in Go.
After=network.target
@ -246,7 +246,7 @@ $ systemctl start clash
```
### Display Process name
Add field `Process` to `Metadata` and prepare to get process name for Restful API `GET /connections`.
Clash add field `Process` to `Metadata` and prepare to get process name for Restful API `GET /connections`.
To display process name in GUI please use https://yaling888.github.io/yacd/.

View file

@ -0,0 +1,9 @@
//go:build build_local
// +build build_local
package script
/*
#cgo pkg-config: python3-embed
*/
import "C"

View file

@ -0,0 +1,25 @@
//go:build !build_local
// +build !build_local
package script
/*
//#cgo linux,amd64 pkg-config: python-3.9-embed
#cgo darwin,amd64 CFLAGS: -I/build/python/python-3.9.7-darwin-amd64/include/python3.9
#cgo darwin,arm64 CFLAGS: -I/build/python/python-3.9.7-darwin-arm64/include/python3.9
#cgo windows,amd64 CFLAGS: -I/build/python/python-3.9.7-windows-amd64/include -DMS_WIN64
#cgo windows,386 CFLAGS: -I/build/python/python-3.9.7-windows-386/include
#cgo linux,amd64 CFLAGS: -I/home/runner/work/clash/clash/bin/python/python-3.9.7-linux-amd64/include/python3.9
#cgo linux,arm64 CFLAGS: -I/build/python/python-3.9.7-linux-arm64/include/python3.9
#cgo linux,386 CFLAGS: -I/build/python/python-3.9.7-linux-386/include/python3.9
#cgo darwin,amd64 LDFLAGS: -L/build/python/python-3.9.7-darwin-amd64/lib -lpython3.9 -ldl -framework CoreFoundation
#cgo darwin,arm64 LDFLAGS: -L/build/python/python-3.9.7-darwin-arm64/lib -lpython3.9 -ldl -framework CoreFoundation
#cgo windows,amd64 LDFLAGS: -L/build/python/python-3.9.7-windows-amd64/lib -lpython39 -lpthread -lm
#cgo windows,386 LDFLAGS: -L/build/python/python-3.9.7-windows-386/lib -lpython39 -lpthread -lm
#cgo linux,amd64 LDFLAGS: -L/home/runner/work/clash/clash/bin/python/python-3.9.7-linux-amd64/lib -lpython3.9 -lpthread -ldl -lutil -lm
#cgo linux,arm64 LDFLAGS: -L/build/python/python-3.9.7-linux-arm64/lib -lpython3.9 -lpthread -ldl -lutil -lm
#cgo linux,386 LDFLAGS: -L/build/python/python-3.9.7-linux-386/lib -lpython3.9 -lcrypt -lpthread -ldl -lutil -lm
*/
import "C"

View file

@ -37,8 +37,6 @@ void init_python(const char *path) {
import can be deferred until the embedded script
imports it. */
clash_module = PyImport_ImportModule("clash");
main_fn = load_func(CLASH_SCRIPT_MODULE_NAME, "main");
}
// Load function, same as "import module_name.func_name as obj" in Python
@ -87,6 +85,10 @@ void py_clear(PyObject *obj) {
Py_CLEAR(obj);
}
void load_main_func() {
main_fn = load_func(CLASH_SCRIPT_MODULE_NAME, "main");
}
/** callback function, that call go function by python3 script. **/
resolve_ip_callback resolve_ip_callback_fn;

View file

@ -1,10 +1,6 @@
package script
/*
#cgo pkg-config: python3-embed
//#cgo pkg-config: python3
//#cgo LDFLAGS: -lpython3
#include "clash_module.h"
extern const char *resolveIPCallbackFn(const char *host);
@ -42,6 +38,7 @@ import (
"os"
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"unsafe"
@ -88,6 +85,7 @@ func Py_Initialize(path string) error {
C.finalize_Python()
}
path = strings.ReplaceAll(path, "\\", "/")
cPath := C.CString(path)
//defer C.free(unsafe.Pointer(cPath))
@ -182,6 +180,15 @@ func LoadShortcutFunction(shortcut string) (*PyObject, error) {
return togo(fnc), nil
}
func LoadMainFunction() error {
C.load_main_func()
err := PyLastError()
if err != nil {
return err
}
return nil
}
//CallPyMainFunction call python script main function
//return the proxy adapter name.
func CallPyMainFunction(mtd *constant.Metadata) (string, error) {
@ -226,7 +233,7 @@ func CallPyMainFunction(mtd *constant.Metadata) (string, error) {
err := PyLastError()
if err != nil {
log.Errorln("[Script] script code error: %s", err.Error())
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
killSelf()
return "", fmt.Errorf("script code error: %w", err)
} else {
return "", fmt.Errorf("script code error, result: %v", rs)
@ -281,7 +288,7 @@ func CallPyShortcut(fn *PyObject, mtd *constant.Metadata) (bool, error) {
err := PyLastError()
if err != nil {
log.Errorln("[Script] script shortcut code error: %s", err.Error())
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
killSelf()
return false, fmt.Errorf("script shortcut code error: %w", err)
} else {
return false, fmt.Errorf("script shortcut code error: result: %d", rs)
@ -319,3 +326,14 @@ func NewClashPyContext(ruleProvidersName []string) error {
return nil
}
func killSelf() {
p, err := os.FindProcess(os.Getpid())
if err != nil {
os.Exit(int(syscall.SIGINT))
return
}
p.Signal(syscall.SIGINT)
}

View file

@ -30,6 +30,7 @@ void set_log_callback(log_callback cb);
void append_inittab();
void init_python(const char *path);
void load_main_func();
void finalize_Python();
void py_clear(PyObject *obj);
const char *py_last_error();

View file

@ -98,7 +98,7 @@ func ruleProviderCallbackFn(cProviderName *C.char, cMetadata *C.struct_Metadata)
rule, ok := ruleProviders[providerName]
if !ok {
log.Warnln("rule provider [%s] not found", providerName)
log.Warnln("[Script] rule provider [%s] not found", providerName)
return C.int(0)
}

View file

@ -475,10 +475,14 @@ time = ClashTime()
if err = S.Py_Initialize(C.Path.ScriptDir()); err != nil {
return fmt.Errorf("initialized script module failure, %s", err.Error())
} else {
log.Infoln("Start initial script module successful")
} else if mode == T.Script {
if err = S.LoadMainFunction(); err != nil {
return fmt.Errorf("initialized script module failure, %s", err.Error())
}
}
log.Infoln("Start initial script module successful")
return nil
}

View file

@ -6,7 +6,7 @@ import (
"github.com/Dreamacro/clash/component/mmdb"
"github.com/Dreamacro/clash/component/trie"
//_ "github.com/Dreamacro/clash/rule/geodata/standard"
C "github.com/Dreamacro/clash/constant"
)
type fallbackIPFilter interface {
@ -19,7 +19,7 @@ type geoipFilter struct {
func (gf *geoipFilter) Match(ip net.IP) bool {
record, _ := mmdb.Instance().Country(ip)
return !strings.EqualFold(record.Country.IsoCode, gf.code) && !ip.IsPrivate()
return !strings.EqualFold(record.Country.IsoCode, gf.code) && !ip.IsPrivate() && !ip.Equal(C.TunBroadcastAddr)
}
type ipnetFilter struct {

3
go.mod
View file

@ -25,7 +25,6 @@ require (
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v2 v2.4.0
gvisor.dev/gvisor v0.0.0-20210922003438-b39716d116fd
inet.af/netaddr v0.0.0-20210903134321-85fa6c94624e
)
require (
@ -34,8 +33,6 @@ require (
github.com/oschwald/maxminddb-golang v1.8.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
go4.org/intern v0.0.0-20210108033219-3eb7198706b2 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect

8
go.sum
View file

@ -186,7 +186,6 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
@ -601,11 +600,6 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go4.org/intern v0.0.0-20210108033219-3eb7198706b2 h1:VFTf+jjIgsldaz/Mr00VaCSswHJrI2hIjQygE/W4IMg=
go4.org/intern v0.0.0-20210108033219-3eb7198706b2/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 h1:1tk03FUNpulq2cuWpXZWj649rwJpk0d20rxWiopKRmc=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -1025,8 +1019,6 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.1/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
inet.af/netaddr v0.0.0-20210903134321-85fa6c94624e h1:tvgqez5ZQoBBiBAGNU/fmJy247yB/7++kcLOEoMYup0=
inet.af/netaddr v0.0.0-20210903134321-85fa6c94624e/go.mod h1:z0nx+Dh+7N7CC8V5ayHtHGpZpxLQZZxkIaaz6HN65Ls=
k8s.io/api v0.16.13/go.mod h1:QWu8UWSTiuQZMMeYjwLs6ILu5O74qKSJ0c+4vrchDxs=
k8s.io/apimachinery v0.16.13/go.mod h1:4HMHS3mDHtVttspuuhrJ1GGr/0S9B6iWYWZ57KnnZqQ=
k8s.io/apimachinery v0.16.14-rc.0/go.mod h1:4HMHS3mDHtVttspuuhrJ1GGr/0S9B6iWYWZ57KnnZqQ=

View file

@ -69,9 +69,6 @@ func ParseWithPath(path string) (*config.Config, error) {
// ParseWithBytes config with buffer
func ParseWithBytes(buf []byte) (*config.Config, error) {
mux.Lock()
defer mux.Unlock()
return config.Parse(buf)
}

View file

@ -2,7 +2,6 @@ package router
import (
"fmt"
"net"
"strings"
"github.com/Dreamacro/clash/rule/geodata/strmatcher"
@ -69,44 +68,3 @@ func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) {
func (m *DomainMatcher) ApplyDomain(domain string) bool {
return len(m.matchers.Match(strings.ToLower(domain))) > 0
}
type MultiGeoIPMatcher struct {
matchers []*GeoIPMatcher
}
func NewMultiGeoIPMatcher(geoips []*GeoIP) (*MultiGeoIPMatcher, error) {
var matchers []*GeoIPMatcher
for _, geoip := range geoips {
matcher, err := globalGeoIPContainer.Add(geoip)
if err != nil {
return nil, err
}
matchers = append(matchers, matcher)
}
matcher := &MultiGeoIPMatcher{
matchers: matchers,
}
return matcher, nil
}
func (m *MultiGeoIPMatcher) ApplyIp(ip net.IP) bool {
for _, matcher := range m.matchers {
if matcher.Match(ip) {
return true
}
}
return false
}
func NewGeoIPMatcher(geoip *GeoIP) (*GeoIPMatcher, error) {
matcher, err := globalGeoIPContainer.Add(geoip)
if err != nil {
return nil, err
}
return matcher, nil
}

View file

@ -1,110 +0,0 @@
package router
import (
"fmt"
"net"
"inet.af/netaddr"
)
type GeoIPMatcher struct {
countryCode string
reverseMatch bool
ip4 *netaddr.IPSet
ip6 *netaddr.IPSet
}
func (m *GeoIPMatcher) Init(cidrs []*CIDR) error {
var builder4, builder6 netaddr.IPSetBuilder
for _, cidr := range cidrs {
netaddrIP, ok := netaddr.FromStdIP(net.IP(cidr.GetIp()))
if !ok {
return fmt.Errorf("invalid IP address %v", cidr)
}
ipPrefix := netaddr.IPPrefixFrom(netaddrIP, uint8(cidr.GetPrefix()))
switch {
case netaddrIP.Is4():
builder4.AddPrefix(ipPrefix)
case netaddrIP.Is6():
builder6.AddPrefix(ipPrefix)
}
}
var err error
m.ip4, err = builder4.IPSet()
if err != nil {
return err
}
m.ip6, err = builder6.IPSet()
if err != nil {
return err
}
return nil
}
func (m *GeoIPMatcher) SetReverseMatch(isReverseMatch bool) {
m.reverseMatch = isReverseMatch
}
func (m *GeoIPMatcher) match4(ip net.IP) bool {
nip, ok := netaddr.FromStdIP(ip)
if !ok {
return false
}
return m.ip4.Contains(nip)
}
func (m *GeoIPMatcher) match6(ip net.IP) bool {
nip, ok := netaddr.FromStdIP(ip)
if !ok {
return false
}
return m.ip6.Contains(nip)
}
// Match returns true if the given ip is included by the GeoIP.
func (m *GeoIPMatcher) Match(ip net.IP) bool {
isMatched := false
switch len(ip) {
case net.IPv4len:
isMatched = m.match4(ip)
case net.IPv6len:
isMatched = m.match6(ip)
}
if m.reverseMatch {
return !isMatched
}
return isMatched
}
// GeoIPMatcherContainer is a container for GeoIPMatchers. It keeps unique copies of GeoIPMatcher by country code.
type GeoIPMatcherContainer struct {
matchers []*GeoIPMatcher
}
// Add adds a new GeoIP set into the container.
// If the country code of GeoIP is not empty, GeoIPMatcherContainer will try to find an existing one, instead of adding a new one.
func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
if geoip.CountryCode != "" {
for _, m := range c.matchers {
if m.countryCode == geoip.CountryCode && m.reverseMatch == geoip.ReverseMatch {
return m, nil
}
}
}
m := &GeoIPMatcher{
countryCode: geoip.CountryCode,
reverseMatch: geoip.ReverseMatch,
}
if err := m.Init(geoip.Cidr); err != nil {
return nil, err
}
if geoip.CountryCode != "" {
c.matchers = append(c.matchers, m)
}
return m, nil
}
var globalGeoIPContainer GeoIPMatcherContainer

View file

@ -5,9 +5,6 @@ import (
"github.com/Dreamacro/clash/component/mmdb"
C "github.com/Dreamacro/clash/constant"
//"github.com/Dreamacro/clash/rule/geodata"
//"github.com/Dreamacro/clash/rule/geodata/router"
//_ "github.com/Dreamacro/clash/rule/geodata/standard"
)
type GEOIP struct {
@ -15,7 +12,6 @@ type GEOIP struct {
adapter string
noResolveIP bool
ruleExtra *C.RuleExtra
//geoIPMatcher *router.GeoIPMatcher
}
func (g *GEOIP) RuleType() C.RuleType {
@ -56,38 +52,11 @@ func (g *GEOIP) GetCountry() string {
}
func NewGEOIP(country string, adapter string, noResolveIP bool, ruleExtra *C.RuleExtra) (*GEOIP, error) {
//geoLoaderName := "standard"
////geoLoaderName := "memconservative"
//geoLoader, err := geodata.GetGeoDataLoader(geoLoaderName)
//if err != nil {
// return nil, fmt.Errorf("load GeoIP data error, %s", err.Error())
//}
//
//records, err := geoLoader.LoadGeoIP(strings.ReplaceAll(country, "!", ""))
//if err != nil {
// return nil, fmt.Errorf("load GeoIP data error, %s", err.Error())
//}
//
//geoIP := &router.GeoIP{
// CountryCode: country,
// Cidr: records,
// ReverseMatch: strings.Contains(country, "!"),
//}
//
//geoIPMatcher, err := router.NewGeoIPMatcher(geoIP)
//
//if err != nil {
// return nil, fmt.Errorf("load GeoIP data error, %s", err.Error())
//}
//
//log.Infoln("Start initial GeoIP rule %s => %s, records: %d, reverse match: %v", country, adapter, len(records), geoIP.ReverseMatch)
geoip := &GEOIP{
country: country,
adapter: adapter,
noResolveIP: noResolveIP,
ruleExtra: ruleExtra,
//geoIPMatcher: geoIPMatcher,
}
return geoip, nil