mirror of
https://github.com/cmz0228/hysteria-dev.git
synced 2025-06-09 13:59:54 +00:00
80 lines
1.4 KiB
Go
80 lines
1.4 KiB
Go
package acl
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
|
|
"golang.org/x/net/idna"
|
|
)
|
|
|
|
const (
|
|
domainMatchExact = uint8(iota)
|
|
domainMatchWildcard
|
|
domainMatchSuffix
|
|
)
|
|
|
|
type hostMatcher interface {
|
|
Match(HostInfo) bool
|
|
}
|
|
|
|
type ipMatcher struct {
|
|
IP net.IP
|
|
}
|
|
|
|
func (m *ipMatcher) Match(host HostInfo) bool {
|
|
return m.IP.Equal(host.IPv4) || m.IP.Equal(host.IPv6)
|
|
}
|
|
|
|
type cidrMatcher struct {
|
|
IPNet *net.IPNet
|
|
}
|
|
|
|
func (m *cidrMatcher) Match(host HostInfo) bool {
|
|
return m.IPNet.Contains(host.IPv4) || m.IPNet.Contains(host.IPv6)
|
|
}
|
|
|
|
type domainMatcher struct {
|
|
Pattern string
|
|
Mode uint8
|
|
}
|
|
|
|
func (m *domainMatcher) Match(host HostInfo) bool {
|
|
name, err := idna.ToUnicode(host.Name)
|
|
if err != nil {
|
|
name = host.Name
|
|
}
|
|
switch m.Mode {
|
|
case domainMatchExact:
|
|
return name == m.Pattern
|
|
case domainMatchWildcard:
|
|
return deepMatchRune([]rune(name), []rune(m.Pattern))
|
|
case domainMatchSuffix:
|
|
return name == m.Pattern || strings.HasSuffix(name, "."+m.Pattern)
|
|
default:
|
|
return false // Invalid mode
|
|
}
|
|
}
|
|
|
|
func deepMatchRune(str, pattern []rune) bool {
|
|
for len(pattern) > 0 {
|
|
switch pattern[0] {
|
|
default:
|
|
if len(str) == 0 || str[0] != pattern[0] {
|
|
return false
|
|
}
|
|
case '*':
|
|
return deepMatchRune(str, pattern[1:]) ||
|
|
(len(str) > 0 && deepMatchRune(str[1:], pattern))
|
|
}
|
|
str = str[1:]
|
|
pattern = pattern[1:]
|
|
}
|
|
return len(str) == 0 && len(pattern) == 0
|
|
}
|
|
|
|
type allMatcher struct{}
|
|
|
|
func (m *allMatcher) Match(host HostInfo) bool {
|
|
return true
|
|
}
|