add ip range matcher for bypass
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
"github.com/go-gost/x/internal/loader"
|
"github.com/go-gost/x/internal/loader"
|
||||||
"github.com/go-gost/x/internal/matcher"
|
"github.com/go-gost/x/internal/matcher"
|
||||||
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -79,6 +80,7 @@ type localBypass struct {
|
|||||||
cidrMatcher matcher.Matcher
|
cidrMatcher matcher.Matcher
|
||||||
addrMatcher matcher.Matcher
|
addrMatcher matcher.Matcher
|
||||||
wildcardMatcher matcher.Matcher
|
wildcardMatcher matcher.Matcher
|
||||||
|
ipRangeMatcher matcher.Matcher
|
||||||
cancelFunc context.CancelFunc
|
cancelFunc context.CancelFunc
|
||||||
options options
|
options options
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
@@ -141,15 +143,24 @@ func (bp *localBypass) reload(ctx context.Context) error {
|
|||||||
var addrs []string
|
var addrs []string
|
||||||
var inets []*net.IPNet
|
var inets []*net.IPNet
|
||||||
var wildcards []string
|
var wildcards []string
|
||||||
|
var ipRanges []xnet.IPRange
|
||||||
for _, pattern := range patterns {
|
for _, pattern := range patterns {
|
||||||
if _, inet, err := net.ParseCIDR(pattern); err == nil {
|
if _, inet, err := net.ParseCIDR(pattern); err == nil {
|
||||||
inets = append(inets, inet)
|
inets = append(inets, inet)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.ContainsAny(pattern, "*?") {
|
if strings.ContainsAny(pattern, "*?") {
|
||||||
wildcards = append(wildcards, pattern)
|
wildcards = append(wildcards, pattern)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r := xnet.IPRange{}
|
||||||
|
if err := r.Parse(pattern); err == nil {
|
||||||
|
ipRanges = append(ipRanges, r)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
addrs = append(addrs, pattern)
|
addrs = append(addrs, pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +170,7 @@ func (bp *localBypass) reload(ctx context.Context) error {
|
|||||||
bp.cidrMatcher = matcher.CIDRMatcher(inets)
|
bp.cidrMatcher = matcher.CIDRMatcher(inets)
|
||||||
bp.addrMatcher = matcher.AddrMatcher(addrs)
|
bp.addrMatcher = matcher.AddrMatcher(addrs)
|
||||||
bp.wildcardMatcher = matcher.WildcardMatcher(wildcards)
|
bp.wildcardMatcher = matcher.WildcardMatcher(wildcards)
|
||||||
|
bp.ipRangeMatcher = matcher.IPRangeMatcher(ipRanges)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -263,6 +275,10 @@ func (bp *localBypass) matched(addr string) bool {
|
|||||||
bp.mu.RLock()
|
bp.mu.RLock()
|
||||||
defer bp.mu.RUnlock()
|
defer bp.mu.RUnlock()
|
||||||
|
|
||||||
|
if bp.ipRangeMatcher.Match(addr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if bp.addrMatcher.Match(addr) {
|
if bp.addrMatcher.Match(addr) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package matcher
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -177,6 +178,7 @@ type wildcardMatcherPattern struct {
|
|||||||
glob glob.Glob
|
glob glob.Glob
|
||||||
pr *xnet.PortRange
|
pr *xnet.PortRange
|
||||||
}
|
}
|
||||||
|
|
||||||
type wildcardMatcher struct {
|
type wildcardMatcher struct {
|
||||||
patterns []wildcardMatcherPattern
|
patterns []wildcardMatcherPattern
|
||||||
}
|
}
|
||||||
@@ -224,3 +226,36 @@ func (m *wildcardMatcher) Match(addr string) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ipRangeMatcher struct {
|
||||||
|
ranges []xnet.IPRange
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPRangeMatcher(ranges []xnet.IPRange) Matcher {
|
||||||
|
matcher := &ipRangeMatcher{
|
||||||
|
ranges: ranges,
|
||||||
|
}
|
||||||
|
return matcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ipRangeMatcher) Match(addr string) bool {
|
||||||
|
if m == nil || len(m.ranges) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
host, _, _ := net.SplitHostPort(addr)
|
||||||
|
if host == "" {
|
||||||
|
host = addr
|
||||||
|
}
|
||||||
|
adr, err := netip.ParseAddr(host)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ra := range m.ranges {
|
||||||
|
if ra.Contains(adr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
+41
-1
@@ -3,6 +3,7 @@ package net
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -146,7 +147,7 @@ func (pr *PortRange) Parse(s string) error {
|
|||||||
return nil
|
return nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid range: %s", s)
|
return fmt.Errorf("invalid port range: %s", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +155,45 @@ func (pr *PortRange) Contains(port int) bool {
|
|||||||
return port >= pr.Min && port <= pr.Max
|
return port >= pr.Min && port <= pr.Max
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IPRange struct {
|
||||||
|
Min netip.Addr
|
||||||
|
Max netip.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *IPRange) Parse(s string) error {
|
||||||
|
minmax := strings.Split(s, "-")
|
||||||
|
switch len(minmax) {
|
||||||
|
case 1:
|
||||||
|
addr, err := netip.ParseAddr(strings.TrimSpace(s))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Min, r.Max = addr, addr
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
min, err := netip.ParseAddr(strings.TrimSpace(minmax[0]))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
max, err := netip.ParseAddr(strings.TrimSpace(minmax[1]))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Min, r.Max = min, max
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid ip range: %s", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *IPRange) Contains(addr netip.Addr) bool {
|
||||||
|
return !(addr.Less(r.Min) || r.Max.Less(addr))
|
||||||
|
}
|
||||||
|
|
||||||
type ClientAddr interface {
|
type ClientAddr interface {
|
||||||
ClientAddr() net.Addr
|
ClientAddr() net.Addr
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user