Skip to content

Commit

Permalink
add ip range matcher for bypass
Browse files Browse the repository at this point in the history
  • Loading branch information
ginuerzh committed Dec 23, 2024
1 parent be8e055 commit a5d4774
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
16 changes: 16 additions & 0 deletions bypass/bypass.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/go-gost/core/logger"
"github.com/go-gost/x/internal/loader"
"github.com/go-gost/x/internal/matcher"
xnet "github.com/go-gost/x/internal/net"
)

var (
Expand Down Expand Up @@ -79,6 +80,7 @@ type localBypass struct {
cidrMatcher matcher.Matcher
addrMatcher matcher.Matcher
wildcardMatcher matcher.Matcher
ipRangeMatcher matcher.Matcher
cancelFunc context.CancelFunc
options options
mu sync.RWMutex
Expand Down Expand Up @@ -141,15 +143,24 @@ func (bp *localBypass) reload(ctx context.Context) error {
var addrs []string
var inets []*net.IPNet
var wildcards []string
var ipRanges []xnet.IPRange
for _, pattern := range patterns {
if _, inet, err := net.ParseCIDR(pattern); err == nil {
inets = append(inets, inet)
continue
}

if strings.ContainsAny(pattern, "*?") {
wildcards = append(wildcards, pattern)
continue
}

r := xnet.IPRange{}
if err := r.Parse(pattern); err == nil {
ipRanges = append(ipRanges, r)
continue
}

addrs = append(addrs, pattern)
}

Expand All @@ -159,6 +170,7 @@ func (bp *localBypass) reload(ctx context.Context) error {
bp.cidrMatcher = matcher.CIDRMatcher(inets)
bp.addrMatcher = matcher.AddrMatcher(addrs)
bp.wildcardMatcher = matcher.WildcardMatcher(wildcards)
bp.ipRangeMatcher = matcher.IPRangeMatcher(ipRanges)

return nil
}
Expand Down Expand Up @@ -263,6 +275,10 @@ func (bp *localBypass) matched(addr string) bool {
bp.mu.RLock()
defer bp.mu.RUnlock()

if bp.ipRangeMatcher.Match(addr) {
return true
}

if bp.addrMatcher.Match(addr) {
return true
}
Expand Down
35 changes: 35 additions & 0 deletions internal/matcher/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package matcher

import (
"net"
"net/netip"
"strconv"
"strings"

Expand Down Expand Up @@ -177,6 +178,7 @@ type wildcardMatcherPattern struct {
glob glob.Glob
pr *xnet.PortRange
}

type wildcardMatcher struct {
patterns []wildcardMatcherPattern
}
Expand Down Expand Up @@ -224,3 +226,36 @@ func (m *wildcardMatcher) Match(addr string) bool {

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
}
42 changes: 41 additions & 1 deletion internal/net/addr.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package net
import (
"fmt"
"net"
"net/netip"
"strconv"
"strings"
)
Expand Down Expand Up @@ -146,14 +147,53 @@ func (pr *PortRange) Parse(s string) error {
return nil

default:
return fmt.Errorf("invalid range: %s", s)
return fmt.Errorf("invalid port range: %s", s)
}
}

func (pr *PortRange) Contains(port int) bool {
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 {
ClientAddr() net.Addr
}

0 comments on commit a5d4774

Please sign in to comment.