0d84b07f68
CI / docker (push) Successful in 1m58s
Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。 Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。 Co-authored-by: Cursor <cursoragent@cursor.com>
65 lines
1.5 KiB
Go
65 lines
1.5 KiB
Go
package security
|
|
|
|
import (
|
|
"net"
|
|
|
|
"github.com/wormhole/wormhole/internal/cache"
|
|
"github.com/wormhole/wormhole/internal/store"
|
|
)
|
|
|
|
type Service struct {
|
|
cache *cache.Manager
|
|
store *store.Store
|
|
}
|
|
|
|
func NewService(c *cache.Manager, st *store.Store) *Service {
|
|
return &Service{cache: c, store: st}
|
|
}
|
|
|
|
func (s *Service) Allow(ip string, clientID uint, resourceType string, resourceID uint) bool {
|
|
scopes := []cache.Scope{
|
|
{Kind: "global", ResourceID: 0},
|
|
{Kind: "client", ResourceID: clientID},
|
|
}
|
|
if resourceType == "host" || resourceType == "tunnel" {
|
|
scopes = append(scopes, cache.Scope{Kind: resourceType, ResourceID: resourceID})
|
|
}
|
|
return s.cache.AllowIP(ip, scopes)
|
|
}
|
|
|
|
func (s *Service) BlockIP(ip, scope string, resourceID uint, remark string) error {
|
|
rule := &store.IPRule{
|
|
Scope: scope,
|
|
ResourceID: resourceID,
|
|
Type: "deny",
|
|
Pattern: ip,
|
|
PatternKind: "exact",
|
|
Priority: 100,
|
|
Remark: remark,
|
|
}
|
|
if err := s.store.CreateIPRule(rule); err != nil {
|
|
return err
|
|
}
|
|
return s.cache.ReloadIPRules(s.store)
|
|
}
|
|
|
|
func DetectPatternKind(pattern string) string {
|
|
if _, _, err := net.ParseCIDR(pattern); err == nil {
|
|
return "cidr"
|
|
}
|
|
if len(pattern) > 0 && (pattern[0] == '^' || pattern[len(pattern)-1] == '$' || containsMeta(pattern)) {
|
|
return "regex"
|
|
}
|
|
return "exact"
|
|
}
|
|
|
|
func containsMeta(s string) bool {
|
|
for _, c := range s {
|
|
switch c {
|
|
case '.', '*', '+', '?', '[', ']', '(', ')', '|', '\\':
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|