Merge pull request #143 from WJQSERVER-STUDIO/dev
Some checks failed
Build / prepare (push) Has been cancelled
Build / build (amd64, darwin) (push) Has been cancelled
Build / build (amd64, freebsd) (push) Has been cancelled
Build / build (amd64, linux) (push) Has been cancelled
Build / build (arm64, darwin) (push) Has been cancelled
Build / build (arm64, freebsd) (push) Has been cancelled
Build / build (arm64, linux) (push) Has been cancelled
Build / docker (push) Has been cancelled

4.2.0
This commit is contained in:
WJQSERVER 2025-07-22 17:32:27 +08:00 committed by GitHub
commit 88d84d0703
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 150 additions and 17 deletions

1
.gitignore vendored
View file

@ -3,6 +3,7 @@ demo.toml
*.log *.log
*.bak *.bak
list.json list.json
iplist.json
repos repos
pages pages
*_test *_test

View file

@ -1,5 +1,16 @@
# 更新日志 # 更新日志
4.2.0 - 2025-07-22
---
- CHANGE: 支持根据IP(CDIR)进行白名单与屏蔽
- CHANGE: 进一步推进`json/v2`支持
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 4.1.7 - 2025-07-20
--- ---
- CHANGE: 更新相关依赖 - CHANGE: 更新相关依赖

View file

@ -1 +1 @@
4.1.7-rc.0 4.2.0-rc.0

View file

@ -36,6 +36,8 @@
[相关文章](https://blog.wjqserver.com/categories/my-program/) [相关文章](https://blog.wjqserver.com/categories/my-program/)
代理相关推广: [Thordata](https://www.thordata.com/?ls=github&lk=WJQserver)市面上最具性价比的代理服务商便宜好用来自全球195个国家城市的6000万IP轮换住宅/原生ISP/无限量仅从$0.65/GB 起,新用户$1=5GB .联系客户可获得免费测试.
### 使用示例 ### 使用示例
```bash ```bash

View file

@ -1 +1 @@
4.1.7 4.2.0

View file

@ -7,7 +7,7 @@ import (
"strings" "strings"
"sync" "sync"
"encoding/json" "github.com/go-json-experiment/json"
) )
type Blacklist struct { type Blacklist struct {

60
auth/ipfilter.go Normal file
View file

@ -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
}

View file

@ -1,12 +1,13 @@
package auth package auth
import ( import (
"encoding/json"
"fmt" "fmt"
"ghproxy/config" "ghproxy/config"
"os" "os"
"strings" "strings"
"sync" "sync"
"github.com/go-json-experiment/json"
) )
// Whitelist 用于存储白名单信息 // Whitelist 用于存储白名单信息

View file

@ -7,18 +7,19 @@ import (
) )
type Config struct { type Config struct {
Server ServerConfig Server ServerConfig `toml:"server"`
Httpc HttpcConfig Httpc HttpcConfig `toml:"httpc"`
GitClone GitCloneConfig GitClone GitCloneConfig `toml:"gitclone"`
Shell ShellConfig Shell ShellConfig `toml:"shell"`
Pages PagesConfig Pages PagesConfig `toml:"pages"`
Log LogConfig Log LogConfig `toml:"log"`
Auth AuthConfig Auth AuthConfig `toml:"auth"`
Blacklist BlacklistConfig Blacklist BlacklistConfig `toml:"blacklist"`
Whitelist WhitelistConfig Whitelist WhitelistConfig `toml:"whitelist"`
RateLimit RateLimitConfig IPFilter IPFilterConfig `toml:"ipFilter"`
Outbound OutboundConfig RateLimit RateLimitConfig `toml:"rateLimit"`
Docker DockerConfig Outbound OutboundConfig `toml:"outbound"`
Docker DockerConfig `toml:"docker"`
} }
/* /*
@ -128,6 +129,13 @@ type WhitelistConfig struct {
WhitelistFile string `toml:"whitelistFile"` WhitelistFile string `toml:"whitelistFile"`
} }
type IPFilterConfig struct {
Enabled bool `toml:"enabled"`
EnableAllowList bool `toml:"enableAllowList"`
EnableBlockList bool `toml:"enableBlockList"`
IPFilterFile string `toml:"ipFilterFile"`
}
/* /*
[rateLimit] [rateLimit]
enabled = false enabled = false
@ -273,6 +281,12 @@ func DefaultConfig() *Config {
Enabled: false, Enabled: false,
WhitelistFile: "/data/ghproxy/config/whitelist.json", WhitelistFile: "/data/ghproxy/config/whitelist.json",
}, },
IPFilter: IPFilterConfig{
Enabled: false,
IPFilterFile: "/data/ghproxy/config/ipfilter.json",
EnableAllowList: false,
EnableBlockList: false,
},
RateLimit: RateLimitConfig{ RateLimit: RateLimitConfig{
Enabled: false, Enabled: false,
RatePerMinute: 100, RatePerMinute: 100,

View file

@ -49,6 +49,12 @@ enabled = false
enabled = false enabled = false
whitelistFile = "/data/ghproxy/config/whitelist.json" whitelistFile = "/data/ghproxy/config/whitelist.json"
[ipFilter]
enabled = false
enableAllowList = false
enableBlockList = false
ipFilterFile = "/data/ghproxy/config/ipfilter.json"
[rateLimit] [rateLimit]
enabled = false enabled = false
ratePerMinute = 180 ratePerMinute = 180

11
config/ipfilter.json Normal file
View file

@ -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"
]
}

3
go.mod
View file

@ -13,8 +13,10 @@ require (
github.com/WJQSERVER-STUDIO/go-utils/limitreader v0.0.2 github.com/WJQSERVER-STUDIO/go-utils/limitreader v0.0.2
github.com/fenthope/bauth v0.0.1 github.com/fenthope/bauth v0.0.1
github.com/fenthope/ikumi v0.0.2 github.com/fenthope/ikumi v0.0.2
github.com/fenthope/ipfilter v0.0.1
github.com/fenthope/reco v0.0.3 github.com/fenthope/reco v0.0.3
github.com/fenthope/record v0.0.3 github.com/fenthope/record v0.0.3
github.com/go-json-experiment/json v0.0.0-20250714165856-be8212f5270d
github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/infinite-iroha/touka v0.3.1 github.com/infinite-iroha/touka v0.3.1
github.com/wjqserver/modembed v0.0.1 github.com/wjqserver/modembed v0.0.1
@ -22,6 +24,5 @@ require (
require ( require (
github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.6 // indirect github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.6 // indirect
github.com/go-json-experiment/json v0.0.0-20250714165856-be8212f5270d // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
) )

2
go.sum
View file

@ -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/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 h1:5oaSTf/Msp7M2O3o/X20omKWEQbFhX4KV0CVF21oCdk=
github.com/fenthope/ikumi v0.0.2/go.mod h1:IYbxzOGndZv/yRrbVMyV6dxh06X2wXCbfxrTRM1IruU= 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 h1:RmnQ0D9a8PWtwOODawitTe4BztTnS9wYwrDbipISNq4=
github.com/fenthope/reco v0.0.3/go.mod h1:mDkGLHte5udWTIcjQTxrABRcf56SSdxBOCLgrRDwI/Y= github.com/fenthope/reco v0.0.3/go.mod h1:mDkGLHte5udWTIcjQTxrABRcf56SSdxBOCLgrRDwI/Y=
github.com/fenthope/record v0.0.3 h1:v5urgs5LAkLMlljAT/MjW8fWuRHXPnAraTem5ui7rm4= github.com/fenthope/record v0.0.3 h1:v5urgs5LAkLMlljAT/MjW8fWuRHXPnAraTem5ui7rm4=

24
main.go
View file

@ -21,6 +21,7 @@ import (
"ghproxy/weakcache" "ghproxy/weakcache"
"github.com/fenthope/ikumi" "github.com/fenthope/ikumi"
"github.com/fenthope/ipfilter"
"github.com/fenthope/reco" "github.com/fenthope/reco"
"github.com/fenthope/record" "github.com/fenthope/record"
"github.com/infinite-iroha/touka" "github.com/infinite-iroha/touka"
@ -366,6 +367,29 @@ func main() {
Burst: cfg.RateLimit.Burst, 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)
logger.Errorf("Failed to read IP filter list: %v", 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)
logger.Errorf("Failed to initialize IP filter: %v", err)
os.Exit(1)
} else {
r.Use(ipBlockFilter)
}
}
setupApi(cfg, r, version) setupApi(cfg, r, version)
setupPages(cfg, r) setupPages(cfg, r)
r.SetRedirectTrailingSlash(false) r.SetRedirectTrailingSlash(false)