From d2d9ad1db7693d5681588ea8c887ca385372d45b Mon Sep 17 00:00:00 2001 From: wjqserver <114663932+WJQSERVER@users.noreply.github.com> Date: Tue, 22 Jul 2025 16:37:59 +0800 Subject: [PATCH] 4.2.0-rc.0 --- .gitignore | 1 + CHANGELOG.md | 6 +++++ DEV-VERSION | 2 +- auth/blacklist.go | 2 +- auth/ipfilter.go | 60 ++++++++++++++++++++++++++++++++++++++++++++ auth/whitelist.go | 3 ++- config/config.go | 38 +++++++++++++++++++--------- config/config.toml | 6 +++++ config/ipfilter.json | 11 ++++++++ go.mod | 1 + go.sum | 2 ++ main.go | 22 ++++++++++++++++ 12 files changed, 139 insertions(+), 15 deletions(-) create mode 100644 auth/ipfilter.go create mode 100644 config/ipfilter.json diff --git a/.gitignore b/.gitignore index 0ad54a9..6358c7d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ demo.toml *.log *.bak list.json +iplist.json repos pages *_test \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 90c5047..f2a972d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # 更新日志 +4.2.0-rc.0 - 2025-07-22 +--- +- PRE-RELEASE: v4.2.0-rc.0是v4.2.0预发布版本,请勿在生产环境中使用; +- CHANGE: 支持根据IP(CDIR)进行白名单与屏蔽 +- CHANGE: 深化json/v2改革, 预备go1.25 json/v2 + 4.1.7 - 2025-07-20 --- - CHANGE: 更新相关依赖 diff --git a/DEV-VERSION b/DEV-VERSION index 0f725cf..5cff3f3 100644 --- a/DEV-VERSION +++ b/DEV-VERSION @@ -1 +1 @@ -4.1.7-rc.0 \ No newline at end of file +4.2.0-rc.0 \ No newline at end of file diff --git a/auth/blacklist.go b/auth/blacklist.go index 5ccc73c..014a41d 100644 --- a/auth/blacklist.go +++ b/auth/blacklist.go @@ -7,7 +7,7 @@ import ( "strings" "sync" - "encoding/json" + "github.com/go-json-experiment/json" ) type Blacklist struct { diff --git a/auth/ipfilter.go b/auth/ipfilter.go new file mode 100644 index 0000000..45fe884 --- /dev/null +++ b/auth/ipfilter.go @@ -0,0 +1,60 @@ +package auth + +import ( + "fmt" + "ghproxy/config" + "os" + + "github.com/go-json-experiment/json" + "github.com/go-json-experiment/json/jsontext" +) + +func ReadIPFilterList(cfg *config.Config) (whitelist []string, blacklist []string, err error) { + if cfg.IPFilter.IPFilterFile == "" { + return nil, nil, nil + } + + // 检查文件是否存在, 不存在则创建空json + if _, err := os.Stat(cfg.IPFilter.IPFilterFile); os.IsNotExist(err) { + if err := CreateEmptyIPFilterFile(cfg.IPFilter.IPFilterFile); err != nil { + return nil, nil, fmt.Errorf("failed to create empty IP filter file: %w", err) + } + } + + data, err := os.ReadFile(cfg.IPFilter.IPFilterFile) + if err != nil { + return nil, nil, fmt.Errorf("failed to read IP filter file: %w", err) + } + + var ipFilterData struct { + AllowList []string `json:"allow"` + BlockList []string `json:"block"` + } + if err := json.Unmarshal(data, &ipFilterData); err != nil { + return nil, nil, fmt.Errorf("invalid IP filter file format: %w", err) + } + + return ipFilterData.AllowList, ipFilterData.BlockList, nil +} + +// 创建空列表json +func CreateEmptyIPFilterFile(filePath string) error { + emptyData := struct { + AllowList []string `json:"allow"` + BlockList []string `json:"block"` + }{ + AllowList: []string{}, + BlockList: []string{}, + } + + jsonData, err := json.Marshal(emptyData, jsontext.Multiline(true), jsontext.WithIndent(" ")) + if err != nil { + return fmt.Errorf("failed to marshal empty IP filter data: %w", err) + } + + err = os.WriteFile(filePath, jsonData, 0644) + if err != nil { + return fmt.Errorf("failed to write empty IP filter file: %w", err) + } + return nil +} diff --git a/auth/whitelist.go b/auth/whitelist.go index ee93c20..1218307 100644 --- a/auth/whitelist.go +++ b/auth/whitelist.go @@ -1,12 +1,13 @@ package auth import ( - "encoding/json" "fmt" "ghproxy/config" "os" "strings" "sync" + + "github.com/go-json-experiment/json" ) // Whitelist 用于存储白名单信息 diff --git a/config/config.go b/config/config.go index 0e59f0e..48d43fc 100644 --- a/config/config.go +++ b/config/config.go @@ -7,18 +7,19 @@ import ( ) type Config struct { - Server ServerConfig - Httpc HttpcConfig - GitClone GitCloneConfig - Shell ShellConfig - Pages PagesConfig - Log LogConfig - Auth AuthConfig - Blacklist BlacklistConfig - Whitelist WhitelistConfig - RateLimit RateLimitConfig - Outbound OutboundConfig - Docker DockerConfig + Server ServerConfig `toml:"server"` + Httpc HttpcConfig `toml:"httpc"` + GitClone GitCloneConfig `toml:"gitclone"` + Shell ShellConfig `toml:"shell"` + Pages PagesConfig `toml:"pages"` + Log LogConfig `toml:"log"` + Auth AuthConfig `toml:"auth"` + Blacklist BlacklistConfig `toml:"blacklist"` + Whitelist WhitelistConfig `toml:"whitelist"` + IPFilter IPFilterConfig `toml:"ipFilter"` + RateLimit RateLimitConfig `toml:"rateLimit"` + Outbound OutboundConfig `toml:"outbound"` + Docker DockerConfig `toml:"docker"` } /* @@ -128,6 +129,13 @@ type WhitelistConfig struct { WhitelistFile string `toml:"whitelistFile"` } +type IPFilterConfig struct { + Enabled bool `toml:"enabled"` + EnableAllowList bool `toml:"enableAllowList"` + EnableBlockList bool `toml:"enableBlockList"` + IPFilterFile string +} + /* [rateLimit] enabled = false @@ -273,6 +281,12 @@ func DefaultConfig() *Config { Enabled: false, WhitelistFile: "/data/ghproxy/config/whitelist.json", }, + IPFilter: IPFilterConfig{ + Enabled: false, + IPFilterFile: "/data/ghproxy/config/ipfilter.json", + EnableAllowList: false, + EnableBlockList: false, + }, RateLimit: RateLimitConfig{ Enabled: false, RatePerMinute: 100, diff --git a/config/config.toml b/config/config.toml index ecf4959..ce490ca 100644 --- a/config/config.toml +++ b/config/config.toml @@ -49,6 +49,12 @@ enabled = false enabled = false whitelistFile = "/data/ghproxy/config/whitelist.json" +[ipFilter] +enabled = false +enableAllowList = false +enableBlockList = false +ipFilterFile = "/data/ghproxy/config/ipfilter.json" + [rateLimit] enabled = false ratePerMinute = 180 diff --git a/config/ipfilter.json b/config/ipfilter.json new file mode 100644 index 0000000..283bbd8 --- /dev/null +++ b/config/ipfilter.json @@ -0,0 +1,11 @@ +{ + "allow": [ + "127.0.0.1", + "192.168.1.0/24", + "::1" + ], + "block": [ + "10.0.0.0/8", + "192.168.1.0/24" + ] +} \ No newline at end of file diff --git a/go.mod b/go.mod index 1d5ff59..7d21b88 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/WJQSERVER-STUDIO/go-utils/limitreader v0.0.2 github.com/fenthope/bauth v0.0.1 github.com/fenthope/ikumi v0.0.2 + github.com/fenthope/ipfilter v0.0.1 github.com/fenthope/reco v0.0.3 github.com/fenthope/record v0.0.3 github.com/hashicorp/golang-lru/v2 v2.0.7 diff --git a/go.sum b/go.sum index 3347216..81d8fbc 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/fenthope/bauth v0.0.1 h1:+4UIQshGx3mYD4L3f2S4MLZOi5PWU7fU5GK3wsZvwzE= github.com/fenthope/bauth v0.0.1/go.mod h1:1fveTpgfR1p+WXQ8MXm9BfBCeNYi55j23jxCOGOvBSA= github.com/fenthope/ikumi v0.0.2 h1:5oaSTf/Msp7M2O3o/X20omKWEQbFhX4KV0CVF21oCdk= github.com/fenthope/ikumi v0.0.2/go.mod h1:IYbxzOGndZv/yRrbVMyV6dxh06X2wXCbfxrTRM1IruU= +github.com/fenthope/ipfilter v0.0.1 h1:HrYAyixCMvsDAz36GRyFfyCNtrgYwzrhMcY0XV7fGcM= +github.com/fenthope/ipfilter v0.0.1/go.mod h1:QfY0GrpG0D82HROgdH4c9eog4js42ghLIfl/iM4MvvY= github.com/fenthope/reco v0.0.3 h1:RmnQ0D9a8PWtwOODawitTe4BztTnS9wYwrDbipISNq4= github.com/fenthope/reco v0.0.3/go.mod h1:mDkGLHte5udWTIcjQTxrABRcf56SSdxBOCLgrRDwI/Y= github.com/fenthope/record v0.0.3 h1:v5urgs5LAkLMlljAT/MjW8fWuRHXPnAraTem5ui7rm4= diff --git a/main.go b/main.go index fac8fb4..52f9fca 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,7 @@ import ( "ghproxy/weakcache" "github.com/fenthope/ikumi" + "github.com/fenthope/ipfilter" "github.com/fenthope/reco" "github.com/fenthope/record" "github.com/infinite-iroha/touka" @@ -366,6 +367,27 @@ func main() { Burst: cfg.RateLimit.Burst, })) } + + if cfg.IPFilter.Enabled { + var err error + ipAllowList, ipBlockList, err := auth.ReadIPFilterList(cfg) + if err != nil { + fmt.Printf("Failed to read IP filter list: %v\n", err) + os.Exit(1) + } + ipBlockFilter, err := ipfilter.NewIPFilter(ipfilter.IPFilterConfig{ + EnableAllowList: cfg.IPFilter.EnableAllowList, + EnableBlockList: cfg.IPFilter.EnableBlockList, + AllowList: ipAllowList, + BlockList: ipBlockList, + }) + if err != nil { + fmt.Printf("Failed to initialize IP filter: %v\n", err) + os.Exit(1) + } else { + r.Use(ipBlockFilter) + } + } setupApi(cfg, r, version) setupPages(cfg, r) r.SetRedirectTrailingSlash(false)