sing-box/route/rule_geoip.go

100 lines
2.2 KiB
Go
Raw Permalink Normal View History

2022-07-02 14:55:10 +00:00
package route
import (
2023-02-07 04:20:47 +00:00
"net/netip"
2022-07-02 14:55:10 +00:00
"strings"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
2023-02-07 04:20:47 +00:00
N "github.com/sagernet/sing/common/network"
2022-07-02 14:55:10 +00:00
)
var _ RuleItem = (*GeoIPItem)(nil)
type GeoIPItem struct {
router adapter.Router
2022-07-12 07:17:29 +00:00
logger log.ContextLogger
2022-07-02 14:55:10 +00:00
isSource bool
codes []string
codeMap map[string]bool
}
2022-07-12 07:17:29 +00:00
func NewGeoIPItem(router adapter.Router, logger log.ContextLogger, isSource bool, codes []string) *GeoIPItem {
2022-07-02 14:55:10 +00:00
codeMap := make(map[string]bool)
for _, code := range codes {
codeMap[code] = true
}
return &GeoIPItem{
router: router,
logger: logger,
codes: codes,
isSource: isSource,
codeMap: codeMap,
}
}
func (r *GeoIPItem) Match(metadata *adapter.InboundContext) bool {
2023-02-07 04:20:47 +00:00
var geoipCode string
if r.isSource && metadata.SourceGeoIPCode != "" {
geoipCode = metadata.SourceGeoIPCode
} else if !r.isSource && metadata.GeoIPCode != "" {
geoipCode = metadata.GeoIPCode
2022-07-02 14:55:10 +00:00
}
2023-02-07 04:20:47 +00:00
if geoipCode != "" {
return r.codeMap[geoipCode]
}
var destination netip.Addr
2022-07-02 14:55:10 +00:00
if r.isSource {
2023-02-07 04:20:47 +00:00
destination = metadata.Source.Addr
2022-07-03 07:57:09 +00:00
} else {
2023-02-07 04:20:47 +00:00
destination = metadata.Destination.Addr
}
if destination.IsValid() {
return r.match(metadata, destination)
}
for _, destinationAddress := range metadata.DestinationAddresses {
if r.match(metadata, destinationAddress) {
return true
2022-07-02 14:55:10 +00:00
}
2023-02-07 04:20:47 +00:00
}
return false
}
func (r *GeoIPItem) match(metadata *adapter.InboundContext, destination netip.Addr) bool {
var geoipCode string
geoReader := r.router.GeoIPReader()
if geoReader != nil {
geoipCode = geoReader.Lookup(destination)
}
if geoipCode == "" && !N.IsPublicAddr(destination) {
geoipCode = "private"
}
if geoipCode == "" {
2022-07-07 15:36:32 +00:00
return false
2022-07-02 14:55:10 +00:00
}
2023-02-07 04:20:47 +00:00
if r.isSource {
metadata.SourceGeoIPCode = geoipCode
} else {
metadata.GeoIPCode = geoipCode
}
return r.codeMap[geoipCode]
2022-07-02 14:55:10 +00:00
}
func (r *GeoIPItem) String() string {
var description string
if r.isSource {
description = "source_geoip="
} else {
description = "geoip="
}
cLen := len(r.codes)
if cLen == 1 {
description += r.codes[0]
} else if cLen > 3 {
description += "[" + strings.Join(r.codes[:3], " ") + "...]"
} else {
description += "[" + strings.Join(r.codes, " ") + "]"
}
return description
}