dae/component/routing/matcher_builder.go

192 lines
6.4 KiB
Go
Raw Normal View History

2023-01-23 18:54:21 +07:00
/*
* SPDX-License-Identifier: AGPL-3.0-only
2023-01-28 12:56:06 +07:00
* Copyright (c) since 2022, v2rayA Organization <team@v2raya.org>
2023-01-23 18:54:21 +07:00
*/
package routing
import (
"fmt"
2023-01-29 10:19:58 +07:00
"github.com/sirupsen/logrus"
"github.com/v2rayA/dae/common"
2023-01-23 19:01:24 +07:00
"github.com/v2rayA/dae/common/consts"
2023-01-28 00:50:21 +07:00
"github.com/v2rayA/dae/pkg/config_parser"
2023-01-23 18:54:21 +07:00
"net/netip"
"strings"
)
2023-01-23 19:01:24 +07:00
var FakeOutbound_AND = consts.OutboundLogicalAnd.String()
var FakeOutbound_OR = consts.OutboundLogicalOr.String()
2023-01-23 18:54:21 +07:00
type MatcherBuilder interface {
AddDomain(f *config_parser.Function, key string, values []string, outbound string)
AddIp(f *config_parser.Function, values []netip.Prefix, outbound string)
AddPort(f *config_parser.Function, values [][2]uint16, outbound string)
AddSourceIp(f *config_parser.Function, values []netip.Prefix, outbound string)
AddSourcePort(f *config_parser.Function, values [][2]uint16, outbound string)
AddL4Proto(f *config_parser.Function, values consts.L4ProtoType, outbound string)
AddIpVersion(f *config_parser.Function, values consts.IpVersion, outbound string)
AddSourceMac(f *config_parser.Function, values [][6]byte, outbound string)
2023-01-23 18:54:21 +07:00
AddFinal(outbound string)
AddAnyBefore(f *config_parser.Function, key string, values []string, outbound string)
AddAnyAfter(f *config_parser.Function, key string, values []string, outbound string)
2023-01-23 18:54:21 +07:00
Build() (err error)
}
func GroupParamValuesByKey(params []*config_parser.Param) (keyToValues map[string][]string, keyOrder []string) {
2023-01-23 18:54:21 +07:00
groups := make(map[string][]string)
for _, param := range params {
if _, ok := groups[param.Key]; !ok {
keyOrder = append(keyOrder, param.Key)
}
2023-01-23 18:54:21 +07:00
groups[param.Key] = append(groups[param.Key], param.Val)
}
return groups, keyOrder
2023-01-23 18:54:21 +07:00
}
func ParsePrefixes(values []string) (cidrs []netip.Prefix, err error) {
for _, value := range values {
toParse := value
if strings.LastIndexByte(value, '/') == -1 {
toParse += "/32"
}
prefix, err := netip.ParsePrefix(toParse)
if err != nil {
return nil, fmt.Errorf("cannot parse %v: %w", value, err)
}
cidrs = append(cidrs, prefix)
}
return cidrs, nil
}
2023-01-28 00:50:21 +07:00
func ApplyMatcherBuilder(builder MatcherBuilder, rules []*config_parser.RoutingRule, finalOutbound string) (err error) {
2023-01-23 18:54:21 +07:00
for _, rule := range rules {
2023-01-29 10:19:58 +07:00
logrus.Debugln("[rule]", rule.String(true))
2023-01-23 18:54:21 +07:00
// rule is like: domain(domain:baidu.com) && port(443) -> proxy
for iFunc, f := range rule.AndFunctions {
// f is like: domain(domain:baidu.com)
paramValueGroups, keyOrder := GroupParamValuesByKey(f.Params)
for jMatchSet, key := range keyOrder {
paramValueGroup := paramValueGroups[key]
2023-01-23 18:54:21 +07:00
// Preprocess the outbound and pass FakeOutbound_AND to all but the last function.
outbound := FakeOutbound_OR
if jMatchSet == len(keyOrder)-1 {
outbound = FakeOutbound_AND
if iFunc == len(rule.AndFunctions)-1 {
outbound = rule.Outbound
}
2023-01-23 18:54:21 +07:00
}
2023-01-29 10:19:58 +07:00
{
// Debug
symNot := ""
if f.Not {
symNot = "!"
}
logrus.Debugf("\t%v%v(%v) -> %v", symNot, f.Name, key, outbound)
}
builder.AddAnyBefore(f, key, paramValueGroup, outbound)
2023-01-23 18:54:21 +07:00
switch f.Name {
case consts.Function_Domain:
builder.AddDomain(f, key, paramValueGroup, outbound)
case consts.Function_Ip, consts.Function_SourceIp:
2023-01-23 18:54:21 +07:00
cidrs, err := ParsePrefixes(paramValueGroup)
if err != nil {
return err
}
if f.Name == consts.Function_Ip {
builder.AddIp(f, cidrs, outbound)
} else {
builder.AddSourceIp(f, cidrs, outbound)
}
case consts.Function_Mac:
var macAddrs [][6]byte
for _, v := range paramValueGroup {
mac, err := common.ParseMac(v)
if err != nil {
return err
}
macAddrs = append(macAddrs, mac)
}
builder.AddSourceMac(f, macAddrs, outbound)
case consts.Function_Port, consts.Function_SourcePort:
var portRanges [][2]uint16
for _, v := range paramValueGroup {
portRange, err := common.ParsePortRange(v)
if err != nil {
return err
}
portRanges = append(portRanges, portRange)
}
if f.Name == consts.Function_Port {
builder.AddPort(f, portRanges, outbound)
} else {
builder.AddSourcePort(f, portRanges, outbound)
}
case consts.Function_L4Proto:
var l4protoType consts.L4ProtoType
for _, v := range paramValueGroup {
switch v {
case "tcp":
l4protoType |= consts.L4ProtoType_TCP
case "udp":
l4protoType |= consts.L4ProtoType_UDP
}
}
builder.AddL4Proto(f, l4protoType, outbound)
case consts.Function_IpVersion:
var ipVersion consts.IpVersion
for _, v := range paramValueGroup {
switch v {
case "4":
ipVersion |= consts.IpVersion_4
case "6":
ipVersion |= consts.IpVersion_6
}
}
builder.AddIpVersion(f, ipVersion, outbound)
default:
return fmt.Errorf("unsupported function name: %v", f.Name)
2023-01-23 18:54:21 +07:00
}
builder.AddAnyAfter(f, key, paramValueGroup, outbound)
2023-01-23 18:54:21 +07:00
}
}
}
builder.AddAnyBefore(&config_parser.Function{
Name: "final",
}, "", nil, finalOutbound)
2023-01-23 18:54:21 +07:00
builder.AddFinal(finalOutbound)
builder.AddAnyAfter(&config_parser.Function{
Name: "final",
}, "", nil, finalOutbound)
2023-01-23 18:54:21 +07:00
return nil
}
type DefaultMatcherBuilder struct {
}
2023-01-23 18:54:21 +07:00
func (d *DefaultMatcherBuilder) AddDomain(f *config_parser.Function, key string, values []string, outbound string) {
}
func (d *DefaultMatcherBuilder) AddIp(f *config_parser.Function, values []netip.Prefix, outbound string) {
}
func (d *DefaultMatcherBuilder) AddPort(f *config_parser.Function, values [][2]uint16, outbound string) {
}
func (d *DefaultMatcherBuilder) AddSourceIp(f *config_parser.Function, values []netip.Prefix, outbound string) {
}
func (d *DefaultMatcherBuilder) AddSourcePort(f *config_parser.Function, values [][2]uint16, outbound string) {
}
func (d *DefaultMatcherBuilder) AddL4Proto(f *config_parser.Function, values consts.L4ProtoType, outbound string) {
}
func (d *DefaultMatcherBuilder) AddIpVersion(f *config_parser.Function, values consts.IpVersion, outbound string) {
}
func (d *DefaultMatcherBuilder) AddSourceMac(f *config_parser.Function, values [][6]byte, outbound string) {
}
func (d *DefaultMatcherBuilder) AddFinal(outbound string) {}
func (d *DefaultMatcherBuilder) AddAnyBefore(f *config_parser.Function, key string, values []string, outbound string) {
2023-01-27 01:10:27 +07:00
}
func (d *DefaultMatcherBuilder) AddAnyAfter(f *config_parser.Function, key string, values []string, outbound string) {
2023-01-27 01:10:27 +07:00
}
func (d *DefaultMatcherBuilder) Build() (err error) { return nil }