mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-21 16:11:32 +00:00
Refactor geo resources
This commit is contained in:
parent
8392567962
commit
2d9203ee74
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,5 +1,4 @@
|
|||
/.idea/
|
||||
/vendor/
|
||||
/*.json
|
||||
/Country.mmdb
|
||||
/geosite.db
|
||||
/*.db
|
|
@ -6,124 +6,23 @@ import (
|
|||
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type (
|
||||
ConnectionHandler interface {
|
||||
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
|
||||
}
|
||||
PacketHandler interface {
|
||||
NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata InboundContext) error
|
||||
}
|
||||
PacketConnectionHandler interface {
|
||||
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
|
||||
}
|
||||
UpstreamHandlerAdapter interface {
|
||||
N.TCPConnectionHandler
|
||||
N.UDPConnectionHandler
|
||||
E.Handler
|
||||
}
|
||||
ConnectionHandlerFunc = func(ctx context.Context, conn net.Conn, metadata InboundContext) error
|
||||
PacketConnectionHandlerFunc = func(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
|
||||
)
|
||||
|
||||
func NewUpstreamHandler(
|
||||
metadata InboundContext,
|
||||
connectionHandler ConnectionHandlerFunc,
|
||||
packetHandler PacketConnectionHandlerFunc,
|
||||
errorHandler E.Handler,
|
||||
) UpstreamHandlerAdapter {
|
||||
return &myUpstreamHandlerWrapper{
|
||||
metadata: metadata,
|
||||
connectionHandler: connectionHandler,
|
||||
packetHandler: packetHandler,
|
||||
errorHandler: errorHandler,
|
||||
}
|
||||
type ConnectionHandler interface {
|
||||
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
|
||||
}
|
||||
|
||||
var _ UpstreamHandlerAdapter = (*myUpstreamHandlerWrapper)(nil)
|
||||
|
||||
type myUpstreamHandlerWrapper struct {
|
||||
metadata InboundContext
|
||||
connectionHandler ConnectionHandlerFunc
|
||||
packetHandler PacketConnectionHandlerFunc
|
||||
errorHandler E.Handler
|
||||
type PacketHandler interface {
|
||||
NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata InboundContext) error
|
||||
}
|
||||
|
||||
func (w *myUpstreamHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||
w.metadata.Destination = metadata.Destination
|
||||
return w.connectionHandler(ctx, conn, w.metadata)
|
||||
type PacketConnectionHandler interface {
|
||||
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
|
||||
}
|
||||
|
||||
func (w *myUpstreamHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
w.metadata.Destination = metadata.Destination
|
||||
return w.packetHandler(ctx, conn, w.metadata)
|
||||
}
|
||||
|
||||
func (w *myUpstreamHandlerWrapper) NewError(ctx context.Context, err error) {
|
||||
w.errorHandler.NewError(ctx, err)
|
||||
}
|
||||
|
||||
var myContextType = (*MetadataContext)(nil)
|
||||
|
||||
type MetadataContext struct {
|
||||
context.Context
|
||||
Metadata InboundContext
|
||||
}
|
||||
|
||||
func (c *MetadataContext) Value(key any) any {
|
||||
if key == myContextType {
|
||||
return c
|
||||
}
|
||||
return c.Context.Value(key)
|
||||
}
|
||||
|
||||
func ContextWithMetadata(ctx context.Context, metadata InboundContext) context.Context {
|
||||
return &MetadataContext{
|
||||
Context: ctx,
|
||||
Metadata: metadata,
|
||||
}
|
||||
}
|
||||
|
||||
func UpstreamMetadata(metadata InboundContext) M.Metadata {
|
||||
return M.Metadata{
|
||||
Source: metadata.Source,
|
||||
Destination: metadata.Destination,
|
||||
}
|
||||
}
|
||||
|
||||
type myUpstreamContextHandlerWrapper struct {
|
||||
connectionHandler ConnectionHandlerFunc
|
||||
packetHandler PacketConnectionHandlerFunc
|
||||
errorHandler E.Handler
|
||||
}
|
||||
|
||||
func NewUpstreamContextHandler(
|
||||
connectionHandler ConnectionHandlerFunc,
|
||||
packetHandler PacketConnectionHandlerFunc,
|
||||
errorHandler E.Handler,
|
||||
) UpstreamHandlerAdapter {
|
||||
return &myUpstreamContextHandlerWrapper{
|
||||
connectionHandler: connectionHandler,
|
||||
packetHandler: packetHandler,
|
||||
errorHandler: errorHandler,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *myUpstreamContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||
myCtx := ctx.Value(myContextType).(*MetadataContext)
|
||||
myCtx.Metadata.Destination = metadata.Destination
|
||||
return w.connectionHandler(ctx, conn, myCtx.Metadata)
|
||||
}
|
||||
|
||||
func (w *myUpstreamContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
myCtx := ctx.Value(myContextType).(*MetadataContext)
|
||||
myCtx.Metadata.Destination = metadata.Destination
|
||||
return w.packetHandler(ctx, conn, myCtx.Metadata)
|
||||
}
|
||||
|
||||
func (w *myUpstreamContextHandlerWrapper) NewError(ctx context.Context, err error) {
|
||||
w.errorHandler.NewError(ctx, err)
|
||||
type UpstreamHandlerAdapter interface {
|
||||
N.TCPConnectionHandler
|
||||
N.UDPConnectionHandler
|
||||
E.Handler
|
||||
}
|
||||
|
|
|
@ -4,25 +4,23 @@ import (
|
|||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/oschwald/geoip2-golang"
|
||||
"github.com/sagernet/sing-box/common/geoip"
|
||||
"github.com/sagernet/sing-box/common/geosite"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type Router interface {
|
||||
Start() error
|
||||
Close() error
|
||||
|
||||
Service
|
||||
Outbound(tag string) (Outbound, bool)
|
||||
RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
|
||||
RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
|
||||
GeoIPReader() *geoip2.Reader
|
||||
GeoIPReader() *geoip.Reader
|
||||
GeositeReader() *geosite.Reader
|
||||
}
|
||||
|
||||
type Rule interface {
|
||||
Start() error
|
||||
Close() error
|
||||
Service
|
||||
UpdateGeosite() error
|
||||
Match(metadata *InboundContext) bool
|
||||
Outbound() string
|
||||
String() string
|
||||
|
|
114
adapter/upstream.go
Normal file
114
adapter/upstream.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
package adapter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type (
|
||||
ConnectionHandlerFunc = func(ctx context.Context, conn net.Conn, metadata InboundContext) error
|
||||
PacketConnectionHandlerFunc = func(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
|
||||
)
|
||||
|
||||
func NewUpstreamHandler(
|
||||
metadata InboundContext,
|
||||
connectionHandler ConnectionHandlerFunc,
|
||||
packetHandler PacketConnectionHandlerFunc,
|
||||
errorHandler E.Handler,
|
||||
) UpstreamHandlerAdapter {
|
||||
return &myUpstreamHandlerWrapper{
|
||||
metadata: metadata,
|
||||
connectionHandler: connectionHandler,
|
||||
packetHandler: packetHandler,
|
||||
errorHandler: errorHandler,
|
||||
}
|
||||
}
|
||||
|
||||
var _ UpstreamHandlerAdapter = (*myUpstreamHandlerWrapper)(nil)
|
||||
|
||||
type myUpstreamHandlerWrapper struct {
|
||||
metadata InboundContext
|
||||
connectionHandler ConnectionHandlerFunc
|
||||
packetHandler PacketConnectionHandlerFunc
|
||||
errorHandler E.Handler
|
||||
}
|
||||
|
||||
func (w *myUpstreamHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||
w.metadata.Destination = metadata.Destination
|
||||
return w.connectionHandler(ctx, conn, w.metadata)
|
||||
}
|
||||
|
||||
func (w *myUpstreamHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
w.metadata.Destination = metadata.Destination
|
||||
return w.packetHandler(ctx, conn, w.metadata)
|
||||
}
|
||||
|
||||
func (w *myUpstreamHandlerWrapper) NewError(ctx context.Context, err error) {
|
||||
w.errorHandler.NewError(ctx, err)
|
||||
}
|
||||
|
||||
var myContextType = (*MetadataContext)(nil)
|
||||
|
||||
type MetadataContext struct {
|
||||
context.Context
|
||||
Metadata InboundContext
|
||||
}
|
||||
|
||||
func (c *MetadataContext) Value(key any) any {
|
||||
if key == myContextType {
|
||||
return c
|
||||
}
|
||||
return c.Context.Value(key)
|
||||
}
|
||||
|
||||
func ContextWithMetadata(ctx context.Context, metadata InboundContext) context.Context {
|
||||
return &MetadataContext{
|
||||
Context: ctx,
|
||||
Metadata: metadata,
|
||||
}
|
||||
}
|
||||
|
||||
func UpstreamMetadata(metadata InboundContext) M.Metadata {
|
||||
return M.Metadata{
|
||||
Source: metadata.Source,
|
||||
Destination: metadata.Destination,
|
||||
}
|
||||
}
|
||||
|
||||
type myUpstreamContextHandlerWrapper struct {
|
||||
connectionHandler ConnectionHandlerFunc
|
||||
packetHandler PacketConnectionHandlerFunc
|
||||
errorHandler E.Handler
|
||||
}
|
||||
|
||||
func NewUpstreamContextHandler(
|
||||
connectionHandler ConnectionHandlerFunc,
|
||||
packetHandler PacketConnectionHandlerFunc,
|
||||
errorHandler E.Handler,
|
||||
) UpstreamHandlerAdapter {
|
||||
return &myUpstreamContextHandlerWrapper{
|
||||
connectionHandler: connectionHandler,
|
||||
packetHandler: packetHandler,
|
||||
errorHandler: errorHandler,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *myUpstreamContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||
myCtx := ctx.Value(myContextType).(*MetadataContext)
|
||||
myCtx.Metadata.Destination = metadata.Destination
|
||||
return w.connectionHandler(ctx, conn, myCtx.Metadata)
|
||||
}
|
||||
|
||||
func (w *myUpstreamContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
myCtx := ctx.Value(myContextType).(*MetadataContext)
|
||||
myCtx.Metadata.Destination = metadata.Destination
|
||||
return w.packetHandler(ctx, conn, myCtx.Metadata)
|
||||
}
|
||||
|
||||
func (w *myUpstreamContextHandlerWrapper) NewError(ctx context.Context, err error) {
|
||||
w.errorHandler.NewError(ctx, err)
|
||||
}
|
37
common/geoip/reader.go
Normal file
37
common/geoip/reader.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package geoip
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/oschwald/maxminddb-golang"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type Reader struct {
|
||||
reader *maxminddb.Reader
|
||||
}
|
||||
|
||||
func Open(path string) (*Reader, []string, error) {
|
||||
database, err := maxminddb.Open(path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if database.Metadata.DatabaseType != "sing-geoip" {
|
||||
database.Close()
|
||||
return nil, nil, E.New("incorrect database type, expected sing-geoip, got ", database.Metadata.DatabaseType)
|
||||
}
|
||||
return &Reader{database}, database.Metadata.Languages, nil
|
||||
}
|
||||
|
||||
func (r *Reader) Lookup(addr netip.Addr) string {
|
||||
var code string
|
||||
_ = r.reader.Lookup(addr.AsSlice(), &code)
|
||||
if code != "" {
|
||||
return code
|
||||
}
|
||||
if !N.IsPublicAddr(addr) {
|
||||
return "private"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
|
@ -14,10 +14,10 @@ type Reader struct {
|
|||
domainLength map[string]int
|
||||
}
|
||||
|
||||
func Open(path string) (*Reader, error) {
|
||||
func Open(path string) (*Reader, []string, error) {
|
||||
content, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
reader := &Reader{
|
||||
reader: content,
|
||||
|
@ -25,9 +25,13 @@ func Open(path string) (*Reader, error) {
|
|||
err = reader.readMetadata()
|
||||
if err != nil {
|
||||
content.Close()
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return reader, nil
|
||||
codes := make([]string, 0, len(reader.domainIndex))
|
||||
for code := range reader.domainIndex {
|
||||
codes = append(codes, code)
|
||||
}
|
||||
return reader, codes, nil
|
||||
}
|
||||
|
||||
func (r *Reader) readMetadata() error {
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/oschwald/geoip2-golang"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/geoip"
|
||||
"github.com/sagernet/sing-box/common/geosite"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
|
@ -36,12 +36,11 @@ type Router struct {
|
|||
defaultOutboundForConnection adapter.Outbound
|
||||
defaultOutboundForPacketConnection adapter.Outbound
|
||||
|
||||
needGeoIPDatabase bool
|
||||
geoIPOptions option.GeoIPOptions
|
||||
geoIPReader *geoip2.Reader
|
||||
|
||||
needGeoIPDatabase bool
|
||||
needGeositeDatabase bool
|
||||
geoIPOptions option.GeoIPOptions
|
||||
geositeOptions option.GeositeOptions
|
||||
geoIPReader *geoip.Reader
|
||||
geositeReader *geosite.Reader
|
||||
}
|
||||
|
||||
|
@ -154,17 +153,28 @@ func (r *Router) Start() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if r.needGeositeDatabase {
|
||||
for _, rule := range r.rules {
|
||||
err := rule.UpdateGeosite()
|
||||
if err != nil {
|
||||
r.logger.Error("failed to initialize geosite: ", err)
|
||||
}
|
||||
}
|
||||
err := common.Close(r.geositeReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Router) Close() error {
|
||||
return common.Close(
|
||||
common.PtrOrNil(r.geoIPReader),
|
||||
common.PtrOrNil(r.geositeReader),
|
||||
)
|
||||
}
|
||||
|
||||
func (r *Router) GeoIPReader() *geoip2.Reader {
|
||||
func (r *Router) GeoIPReader() *geoip.Reader {
|
||||
return r.geoIPReader
|
||||
}
|
||||
|
||||
|
@ -199,7 +209,7 @@ func (r *Router) match(ctx context.Context, metadata adapter.InboundContext, def
|
|||
for i, rule := range r.rules {
|
||||
if rule.Match(&metadata) {
|
||||
detour := rule.Outbound()
|
||||
r.logger.WithContext(ctx).Info("match [", i, "]", rule.String(), " => ", detour)
|
||||
r.logger.WithContext(ctx).Info("match[", i, "] ", rule.String(), " => ", detour)
|
||||
if outbound, loaded := r.Outbound(detour); loaded {
|
||||
return outbound
|
||||
}
|
||||
|
@ -245,7 +255,7 @@ func (r *Router) prepareGeoIPDatabase() error {
|
|||
if r.geoIPOptions.Path != "" {
|
||||
geoPath = r.geoIPOptions.Path
|
||||
} else {
|
||||
geoPath = "Country.mmdb"
|
||||
geoPath = "geoip.db"
|
||||
if foundPath, loaded := C.Find(geoPath); loaded {
|
||||
geoPath = foundPath
|
||||
}
|
||||
|
@ -266,13 +276,12 @@ func (r *Router) prepareGeoIPDatabase() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
geoReader, err := geoip2.Open(geoPath)
|
||||
if err == nil {
|
||||
r.logger.Info("loaded geoip database")
|
||||
r.geoIPReader = geoReader
|
||||
} else {
|
||||
geoReader, codes, err := geoip.Open(geoPath)
|
||||
if err != nil {
|
||||
return E.Cause(err, "open geoip database")
|
||||
}
|
||||
r.logger.Info("loaded geoip database: ", len(codes), " codes")
|
||||
r.geoIPReader = geoReader
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -302,9 +311,9 @@ func (r *Router) prepareGeositeDatabase() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
geoReader, err := geosite.Open(geoPath)
|
||||
geoReader, codes, err := geosite.Open(geoPath)
|
||||
if err == nil {
|
||||
r.logger.Info("loaded geosite database")
|
||||
r.logger.Info("loaded geosite database: ", len(codes), " codes")
|
||||
r.geositeReader = geoReader
|
||||
} else {
|
||||
return E.Cause(err, "open geosite database")
|
||||
|
@ -317,7 +326,7 @@ func (r *Router) downloadGeoIPDatabase(savePath string) error {
|
|||
if r.geoIPOptions.DownloadURL != "" {
|
||||
downloadURL = r.geoIPOptions.DownloadURL
|
||||
} else {
|
||||
downloadURL = "https://cdn.jsdelivr.net/gh/Dreamacro/maxmind-geoip@release/Country.mmdb"
|
||||
downloadURL = "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db"
|
||||
}
|
||||
r.logger.Info("downloading geoip database")
|
||||
var detour adapter.Outbound
|
||||
|
@ -342,7 +351,6 @@ func (r *Router) downloadGeoIPDatabase(savePath string) error {
|
|||
defer saveFile.Close()
|
||||
|
||||
httpClient := &http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
|
@ -390,7 +398,6 @@ func (r *Router) downloadGeositeDatabase(savePath string) error {
|
|||
defer saveFile.Close()
|
||||
|
||||
httpClient := &http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
|
|
|
@ -44,6 +44,7 @@ type DefaultRule struct {
|
|||
items []RuleItem
|
||||
sourceAddressItems []RuleItem
|
||||
destinationAddressItems []RuleItem
|
||||
allItems []RuleItem
|
||||
outbound string
|
||||
}
|
||||
|
||||
|
@ -57,12 +58,16 @@ func NewDefaultRule(router adapter.Router, logger log.Logger, options option.Def
|
|||
outbound: options.Outbound,
|
||||
}
|
||||
if len(options.Inbound) > 0 {
|
||||
rule.items = append(rule.items, NewInboundRule(options.Inbound))
|
||||
item := NewInboundRule(options.Inbound)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if options.IPVersion > 0 {
|
||||
switch options.IPVersion {
|
||||
case 4, 6:
|
||||
rule.items = append(rule.items, NewIPVersionItem(options.IPVersion == 6))
|
||||
item := NewIPVersionItem(options.IPVersion == 6)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
default:
|
||||
return nil, E.New("invalid ip version: ", options.IPVersion)
|
||||
}
|
||||
|
@ -70,19 +75,27 @@ func NewDefaultRule(router adapter.Router, logger log.Logger, options option.Def
|
|||
if options.Network != "" {
|
||||
switch options.Network {
|
||||
case C.NetworkTCP, C.NetworkUDP:
|
||||
rule.items = append(rule.items, NewNetworkItem(options.Network))
|
||||
item := NewNetworkItem(options.Network)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
default:
|
||||
return nil, E.New("invalid network: ", options.Network)
|
||||
}
|
||||
}
|
||||
if len(options.Protocol) > 0 {
|
||||
rule.items = append(rule.items, NewProtocolItem(options.Protocol))
|
||||
item := NewProtocolItem(options.Protocol)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.Domain) > 0 || len(options.DomainSuffix) > 0 {
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, NewDomainItem(options.Domain, options.DomainSuffix))
|
||||
item := NewDomainItem(options.Domain, options.DomainSuffix)
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.DomainKeyword) > 0 {
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, NewDomainKeywordItem(options.DomainKeyword))
|
||||
item := NewDomainKeywordItem(options.DomainKeyword)
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.DomainRegex) > 0 {
|
||||
item, err := NewDomainRegexItem(options.DomainRegex)
|
||||
|
@ -90,15 +103,22 @@ func NewDefaultRule(router adapter.Router, logger log.Logger, options option.Def
|
|||
return nil, E.Cause(err, "domain_regex")
|
||||
}
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.Geosite) > 0 {
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, NewGeositeItem(router, logger, options.Geosite))
|
||||
item := NewGeositeItem(router, logger, options.Geosite)
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.SourceGeoIP) > 0 {
|
||||
rule.sourceAddressItems = append(rule.sourceAddressItems, NewGeoIPItem(router, logger, true, options.SourceGeoIP))
|
||||
item := NewGeoIPItem(router, logger, true, options.SourceGeoIP)
|
||||
rule.sourceAddressItems = append(rule.sourceAddressItems, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.GeoIP) > 0 {
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, NewGeoIPItem(router, logger, false, options.GeoIP))
|
||||
item := NewGeoIPItem(router, logger, false, options.GeoIP)
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.SourceIPCIDR) > 0 {
|
||||
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
||||
|
@ -106,6 +126,7 @@ func NewDefaultRule(router adapter.Router, logger log.Logger, options option.Def
|
|||
return nil, E.Cause(err, "source_ipcidr")
|
||||
}
|
||||
rule.sourceAddressItems = append(rule.sourceAddressItems, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.IPCIDR) > 0 {
|
||||
item, err := NewIPCIDRItem(false, options.IPCIDR)
|
||||
|
@ -113,30 +134,23 @@ func NewDefaultRule(router adapter.Router, logger log.Logger, options option.Def
|
|||
return nil, E.Cause(err, "ipcidr")
|
||||
}
|
||||
rule.destinationAddressItems = append(rule.destinationAddressItems, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.SourcePort) > 0 {
|
||||
rule.items = append(rule.items, NewPortItem(true, options.SourcePort))
|
||||
item := NewPortItem(true, options.SourcePort)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.Port) > 0 {
|
||||
rule.items = append(rule.items, NewPortItem(false, options.Port))
|
||||
item := NewPortItem(false, options.Port)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
func (r *DefaultRule) Start() error {
|
||||
for _, item := range r.items {
|
||||
err := common.Start(item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, item := range r.sourceAddressItems {
|
||||
err := common.Start(item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, item := range r.destinationAddressItems {
|
||||
for _, item := range r.allItems {
|
||||
err := common.Start(item)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -146,22 +160,22 @@ func (r *DefaultRule) Start() error {
|
|||
}
|
||||
|
||||
func (r *DefaultRule) Close() error {
|
||||
for _, item := range r.items {
|
||||
for _, item := range r.allItems {
|
||||
err := common.Close(item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, item := range r.sourceAddressItems {
|
||||
err := common.Close(item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, item := range r.destinationAddressItems {
|
||||
err := common.Close(item)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DefaultRule) UpdateGeosite() error {
|
||||
for _, item := range r.allItems {
|
||||
if geositeItem, isSite := item.(*GeositeItem); isSite {
|
||||
err := geositeItem.Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -208,5 +222,5 @@ func (r *DefaultRule) Outbound() string {
|
|||
}
|
||||
|
||||
func (r *DefaultRule) String() string {
|
||||
return strings.Join(common.Map(r.items, F.ToString0[RuleItem]), " ")
|
||||
return strings.Join(common.Map(r.allItems, F.ToString0[RuleItem]), " ")
|
||||
}
|
||||
|
|
|
@ -28,11 +28,11 @@ func NewDomainRegexItem(expressions []string) (*DomainRegexItem, error) {
|
|||
description := "domain_regex="
|
||||
eLen := len(expressions)
|
||||
if eLen == 1 {
|
||||
description = expressions[0]
|
||||
description += expressions[0]
|
||||
} else if eLen > 3 {
|
||||
description = F.ToString("[", strings.Join(expressions[:3], " "), "]")
|
||||
description += F.ToString("[", strings.Join(expressions[:3], " "), "]")
|
||||
} else {
|
||||
description = F.ToString("[", strings.Join(expressions, " "), "]")
|
||||
description += F.ToString("[", strings.Join(expressions, " "), "]")
|
||||
}
|
||||
return &DomainRegexItem{matchers, description}, nil
|
||||
}
|
||||
|
|
|
@ -39,24 +39,14 @@ func (r *GeoIPItem) Match(metadata *adapter.InboundContext) bool {
|
|||
}
|
||||
if r.isSource {
|
||||
if metadata.SourceGeoIPCode == "" {
|
||||
country, err := geoReader.Country(metadata.Source.Addr.AsSlice())
|
||||
if err != nil {
|
||||
r.logger.Error("query geoip for ", metadata.Source.Addr, ": ", err)
|
||||
return false
|
||||
}
|
||||
metadata.SourceGeoIPCode = strings.ToLower(country.Country.IsoCode)
|
||||
metadata.SourceGeoIPCode = geoReader.Lookup(metadata.Source.Addr)
|
||||
}
|
||||
} else {
|
||||
if metadata.Destination.IsFqdn() {
|
||||
return false
|
||||
}
|
||||
if metadata.GeoIPCode == "" {
|
||||
country, err := geoReader.Country(metadata.Destination.Addr.AsSlice())
|
||||
if err != nil {
|
||||
r.logger.Error("query geoip for ", metadata.Destination.Addr, ": ", err)
|
||||
return false
|
||||
}
|
||||
metadata.GeoIPCode = strings.ToLower(country.Country.IsoCode)
|
||||
metadata.GeoIPCode = geoReader.Lookup(metadata.Destination.Addr)
|
||||
}
|
||||
}
|
||||
return r.match(metadata)
|
||||
|
|
|
@ -27,7 +27,7 @@ func NewGeositeItem(router adapter.Router, logger log.Logger, codes []string) *G
|
|||
}
|
||||
}
|
||||
|
||||
func (r *GeositeItem) Start() error {
|
||||
func (r *GeositeItem) Update() error {
|
||||
geositeReader := r.router.GeositeReader()
|
||||
if geositeReader == nil {
|
||||
return E.New("geosite reader is not initialized")
|
||||
|
@ -50,6 +50,9 @@ func (r *GeositeItem) Start() error {
|
|||
}
|
||||
|
||||
func (r *GeositeItem) Match(metadata *adapter.InboundContext) bool {
|
||||
if r.matcher == nil {
|
||||
return false
|
||||
}
|
||||
return r.matcher.Match(metadata)
|
||||
}
|
||||
|
||||
|
@ -57,11 +60,11 @@ func (r *GeositeItem) String() string {
|
|||
description := "geosite="
|
||||
cLen := len(r.codes)
|
||||
if cLen == 1 {
|
||||
description = r.codes[0]
|
||||
description += r.codes[0]
|
||||
} else if cLen > 3 {
|
||||
description = "[" + strings.Join(r.codes[:3], " ") + "...]"
|
||||
description += "[" + strings.Join(r.codes[:3], " ") + "...]"
|
||||
} else {
|
||||
description = "[" + strings.Join(r.codes, " ") + "]"
|
||||
description += "[" + strings.Join(r.codes, " ") + "]"
|
||||
}
|
||||
return description
|
||||
}
|
||||
|
|
|
@ -20,6 +20,16 @@ type LogicalRule struct {
|
|||
outbound string
|
||||
}
|
||||
|
||||
func (r *LogicalRule) UpdateGeosite() error {
|
||||
for _, rule := range r.rules {
|
||||
err := rule.UpdateGeosite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *LogicalRule) Start() error {
|
||||
for _, rule := range r.rules {
|
||||
err := rule.Start()
|
||||
|
|
Loading…
Reference in a new issue