mirror of
https://github.com/daeuniverse/dae.git
synced 2025-01-03 13:31:00 +07:00
feat: support routing by l4proto, ipversion, mac, sip, port, sport
This commit is contained in:
parent
686d6dedc3
commit
916a55d480
@ -10,7 +10,6 @@ As a successor of [v2rayA](https://github.com/v2rayA/v2rayA), dae abandoned v2ra
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
1. Control plane does not support MAC and other matching yet.
|
|
||||||
1. Dns upstream. Check dns upstream and source loop (whether upstream is also a client of us) and remind user to add source rule.
|
1. Dns upstream. Check dns upstream and source loop (whether upstream is also a client of us) and remind user to add source rule.
|
||||||
1. Routing performance optimization.
|
1. Domain routing performance optimization.
|
||||||
1. ...
|
1. ...
|
||||||
|
@ -40,7 +40,7 @@ const (
|
|||||||
RoutingType_SourceIpSet
|
RoutingType_SourceIpSet
|
||||||
RoutingType_Port
|
RoutingType_Port
|
||||||
RoutingType_SourcePort
|
RoutingType_SourcePort
|
||||||
RoutingType_Network
|
RoutingType_L4Proto
|
||||||
RoutingType_IpVersion
|
RoutingType_IpVersion
|
||||||
RoutingType_Mac
|
RoutingType_Mac
|
||||||
RoutingType_Final
|
RoutingType_Final
|
||||||
@ -71,12 +71,12 @@ const (
|
|||||||
MaxRoutingLen = 96
|
MaxRoutingLen = 96
|
||||||
)
|
)
|
||||||
|
|
||||||
type NetworkType uint8
|
type L4ProtoType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NetworkType_TCP NetworkType = 1
|
L4ProtoType_TCP L4ProtoType = 1
|
||||||
NetworkType_UDP NetworkType = 2
|
L4ProtoType_UDP L4ProtoType = 2
|
||||||
NetworkType_TCP_UDP NetworkType = 3
|
L4ProtoType_TCP_UDP L4ProtoType = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
type IpVersion uint8
|
type IpVersion uint8
|
||||||
|
@ -11,6 +11,12 @@ const (
|
|||||||
RoutingDomain_Suffix = "suffix"
|
RoutingDomain_Suffix = "suffix"
|
||||||
RoutingDomain_Regex = "regex"
|
RoutingDomain_Regex = "regex"
|
||||||
|
|
||||||
Function_Domain = "domain"
|
Function_Domain = "domain"
|
||||||
Function_Ip = "ip"
|
Function_Ip = "ip"
|
||||||
|
Function_SourceIp = "sip"
|
||||||
|
Function_Port = "port"
|
||||||
|
Function_SourcePort = "sport"
|
||||||
|
Function_Mac = "mac"
|
||||||
|
Function_L4Proto = "l4proto"
|
||||||
|
Function_IpVersion = "ipversion"
|
||||||
)
|
)
|
||||||
|
@ -8,7 +8,10 @@ package common
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -78,3 +81,42 @@ func SetValue(values *url.Values, key string, value string) {
|
|||||||
}
|
}
|
||||||
values.Set(key, value)
|
values.Set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseMac(mac string) (addr [6]byte, err error) {
|
||||||
|
fields := strings.SplitN(mac, ":", 6)
|
||||||
|
if len(fields) != 6 {
|
||||||
|
return addr, fmt.Errorf("invalid mac: %v", mac)
|
||||||
|
}
|
||||||
|
for i, field := range fields {
|
||||||
|
v, err := hex.DecodeString(field)
|
||||||
|
if err != nil {
|
||||||
|
return addr, fmt.Errorf("parse mac %v: %w", mac, err)
|
||||||
|
}
|
||||||
|
if len(v) != 1 {
|
||||||
|
return addr, fmt.Errorf("invalid mac: %v", mac)
|
||||||
|
}
|
||||||
|
addr[i] = v[0]
|
||||||
|
}
|
||||||
|
return addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePortRange(pr string) (portRange [2]int, err error) {
|
||||||
|
fields := strings.SplitN(pr, "-", 2)
|
||||||
|
for i, field := range fields {
|
||||||
|
if field == "" {
|
||||||
|
return portRange, fmt.Errorf("bad port range: %v", pr)
|
||||||
|
}
|
||||||
|
port, err := strconv.Atoi(field)
|
||||||
|
if err != nil {
|
||||||
|
return portRange, err
|
||||||
|
}
|
||||||
|
if port < 0 || port > 0xffff {
|
||||||
|
return portRange, fmt.Errorf("port %v exceeds uint16 range", port)
|
||||||
|
}
|
||||||
|
portRange[i] = port
|
||||||
|
}
|
||||||
|
if len(fields) == 1 {
|
||||||
|
portRange[1] = portRange[0]
|
||||||
|
}
|
||||||
|
return portRange, nil
|
||||||
|
}
|
||||||
|
@ -162,15 +162,15 @@ enum __attribute__((__packed__)) ROUTING_TYPE {
|
|||||||
ROUTING_TYPE_SOURCE_IP_SET,
|
ROUTING_TYPE_SOURCE_IP_SET,
|
||||||
ROUTING_TYPE_PORT,
|
ROUTING_TYPE_PORT,
|
||||||
ROUTING_TYPE_SOURCE_PORT,
|
ROUTING_TYPE_SOURCE_PORT,
|
||||||
ROUTING_TYPE_NETWORK,
|
ROUTING_TYPE_L4PROTO,
|
||||||
ROUTING_TYPE_IPVERSION,
|
ROUTING_TYPE_IPVERSION,
|
||||||
ROUTING_TYPE_MAC,
|
ROUTING_TYPE_MAC,
|
||||||
ROUTING_TYPE_FINAL,
|
ROUTING_TYPE_FINAL,
|
||||||
};
|
};
|
||||||
enum __attribute__((__packed__)) NETWORK_TYPE {
|
enum __attribute__((__packed__)) L4PROTO_TYPE {
|
||||||
NETWORK_TYPE_TCP = 1,
|
L4PROTO_TYPE_TCP = 1,
|
||||||
NETWORK_TYPE_UDP = 2,
|
L4PROTO_TYPE_UDP = 2,
|
||||||
NETWORK_TYPE_TCP_UDP = 3,
|
L4PROTO_TYPE_TCP_UDP = 3,
|
||||||
};
|
};
|
||||||
enum __attribute__((__packed__)) IP_VERSION {
|
enum __attribute__((__packed__)) IP_VERSION {
|
||||||
IPVERSION_4 = 1,
|
IPVERSION_4 = 1,
|
||||||
@ -187,7 +187,7 @@ struct routing {
|
|||||||
|
|
||||||
__u32 index;
|
__u32 index;
|
||||||
struct port_range port_range;
|
struct port_range port_range;
|
||||||
enum NETWORK_TYPE network_type;
|
enum L4PROTO_TYPE l4proto_type;
|
||||||
enum IP_VERSION ip_version;
|
enum IP_VERSION ip_version;
|
||||||
};
|
};
|
||||||
enum ROUTING_TYPE type;
|
enum ROUTING_TYPE type;
|
||||||
@ -740,7 +740,7 @@ static __always_inline int decap_after_udp_hdr(struct __sk_buff *skb,
|
|||||||
// Do not use __always_inline here because this function is too heavy.
|
// Do not use __always_inline here because this function is too heavy.
|
||||||
static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
||||||
__be32 daddr[4], __be32 mac[4]) {
|
__be32 daddr[4], __be32 mac[4]) {
|
||||||
#define _network flag[0]
|
#define _l4proto flag[0]
|
||||||
#define _ipversion flag[1]
|
#define _ipversion flag[1]
|
||||||
// // Get len of routings and epoch from param_map.
|
// // Get len of routings and epoch from param_map.
|
||||||
// __u32 *routings_len = bpf_map_lookup_elem(¶m_map, &routings_len_key);
|
// __u32 *routings_len = bpf_map_lookup_elem(¶m_map, &routings_len_key);
|
||||||
@ -754,7 +754,7 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
|||||||
// Define variables for further use.
|
// Define variables for further use.
|
||||||
__u16 h_dport;
|
__u16 h_dport;
|
||||||
__u16 h_sport;
|
__u16 h_sport;
|
||||||
if (_network == NETWORK_TYPE_TCP) {
|
if (_l4proto == L4PROTO_TYPE_TCP) {
|
||||||
h_dport = bpf_ntohs(((struct tcphdr *)l4_hdr)->dest);
|
h_dport = bpf_ntohs(((struct tcphdr *)l4_hdr)->dest);
|
||||||
h_sport = bpf_ntohs(((struct tcphdr *)l4_hdr)->source);
|
h_sport = bpf_ntohs(((struct tcphdr *)l4_hdr)->source);
|
||||||
} else {
|
} else {
|
||||||
@ -762,8 +762,9 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
|||||||
h_sport = bpf_ntohs(((struct udphdr *)l4_hdr)->source);
|
h_sport = bpf_ntohs(((struct udphdr *)l4_hdr)->source);
|
||||||
}
|
}
|
||||||
// Modify DNS upstream for routing.
|
// Modify DNS upstream for routing.
|
||||||
if (h_dport == 53 && _network == NETWORK_TYPE_UDP) {
|
if (h_dport == 53 && _l4proto == L4PROTO_TYPE_UDP) {
|
||||||
struct ip_port* upstream = bpf_map_lookup_elem(&dns_upstream_map, &zero_key);
|
struct ip_port *upstream =
|
||||||
|
bpf_map_lookup_elem(&dns_upstream_map, &zero_key);
|
||||||
if (!upstream) {
|
if (!upstream) {
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
@ -777,6 +778,7 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
|||||||
__builtin_memcpy(lpm_key_saddr.data, saddr, IPV6_BYTE_LENGTH);
|
__builtin_memcpy(lpm_key_saddr.data, saddr, IPV6_BYTE_LENGTH);
|
||||||
__builtin_memcpy(lpm_key_daddr.data, daddr, IPV6_BYTE_LENGTH);
|
__builtin_memcpy(lpm_key_daddr.data, daddr, IPV6_BYTE_LENGTH);
|
||||||
__builtin_memcpy(lpm_key_mac.data, mac, IPV6_BYTE_LENGTH);
|
__builtin_memcpy(lpm_key_mac.data, mac, IPV6_BYTE_LENGTH);
|
||||||
|
bpf_printk("mac: %pI6", mac);
|
||||||
|
|
||||||
struct map_lpm_type *lpm;
|
struct map_lpm_type *lpm;
|
||||||
struct routing *routing;
|
struct routing *routing;
|
||||||
@ -842,8 +844,8 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
|||||||
h_sport > routing->port_range.port_end) {
|
h_sport > routing->port_range.port_end) {
|
||||||
bad_rule = true;
|
bad_rule = true;
|
||||||
}
|
}
|
||||||
} else if (routing->type == ROUTING_TYPE_NETWORK) {
|
} else if (routing->type == ROUTING_TYPE_L4PROTO) {
|
||||||
if (!(_network & routing->network_type)) {
|
if (!(_l4proto & routing->l4proto_type)) {
|
||||||
bad_rule = true;
|
bad_rule = true;
|
||||||
}
|
}
|
||||||
} else if (routing->type == ROUTING_TYPE_IPVERSION) {
|
} else if (routing->type == ROUTING_TYPE_IPVERSION) {
|
||||||
@ -867,7 +869,7 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
|||||||
// Decide whether to hit.
|
// Decide whether to hit.
|
||||||
if (!bad_rule) {
|
if (!bad_rule) {
|
||||||
if (routing->outbound == OUTBOUND_DIRECT && h_dport == 53 &&
|
if (routing->outbound == OUTBOUND_DIRECT && h_dport == 53 &&
|
||||||
_network == NETWORK_TYPE_UDP) {
|
_l4proto == L4PROTO_TYPE_UDP) {
|
||||||
// DNS packet should go through control plane.
|
// DNS packet should go through control plane.
|
||||||
return OUTBOUND_CONTROL_PLANE_DIRECT;
|
return OUTBOUND_CONTROL_PLANE_DIRECT;
|
||||||
}
|
}
|
||||||
@ -879,7 +881,7 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
|||||||
bpf_printk(
|
bpf_printk(
|
||||||
"Did coder forget to sync common/consts/ebpf.go with enum ROUTING_TYPE?");
|
"Did coder forget to sync common/consts/ebpf.go with enum ROUTING_TYPE?");
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
#undef _network
|
#undef _l4proto
|
||||||
#undef _ip_version
|
#undef _ip_version
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,12 +920,12 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
|||||||
if (iph) {
|
if (iph) {
|
||||||
saddr[0] = 0;
|
saddr[0] = 0;
|
||||||
saddr[1] = 0;
|
saddr[1] = 0;
|
||||||
saddr[2] = bpf_ntohl(0xffff);
|
saddr[2] = bpf_htonl(0x0000ffff);
|
||||||
saddr[3] = iph->saddr;
|
saddr[3] = iph->saddr;
|
||||||
|
|
||||||
daddr[0] = 0;
|
daddr[0] = 0;
|
||||||
daddr[1] = 0;
|
daddr[1] = 0;
|
||||||
daddr[2] = bpf_ntohl(0xffff);
|
daddr[2] = bpf_htonl(0x0000ffff);
|
||||||
daddr[3] = iph->daddr;
|
daddr[3] = iph->daddr;
|
||||||
} else if (ipv6h) {
|
} else if (ipv6h) {
|
||||||
__builtin_memcpy(daddr, &ipv6h->daddr, IPV6_BYTE_LENGTH);
|
__builtin_memcpy(daddr, &ipv6h->daddr, IPV6_BYTE_LENGTH);
|
||||||
@ -968,15 +970,19 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
|||||||
if (unlikely(tcp_state_syn)) {
|
if (unlikely(tcp_state_syn)) {
|
||||||
// New TCP connection.
|
// New TCP connection.
|
||||||
// bpf_printk("[%X]New Connection", bpf_ntohl(tcph->seq));
|
// bpf_printk("[%X]New Connection", bpf_ntohl(tcph->seq));
|
||||||
__u8 flag[2] = {NETWORK_TYPE_TCP}; // TCP
|
__u8 flag[2] = {L4PROTO_TYPE_TCP}; // TCP
|
||||||
if (ipv6h) {
|
if (ipv6h) {
|
||||||
flag[1] = IPVERSION_6;
|
flag[1] = IPVERSION_6;
|
||||||
} else {
|
} else {
|
||||||
flag[1] = IPVERSION_4;
|
flag[1] = IPVERSION_4;
|
||||||
}
|
}
|
||||||
__be32 mac[4];
|
__be32 mac[4] = {
|
||||||
__builtin_memset(mac, 0, IPV6_BYTE_LENGTH);
|
0,
|
||||||
__builtin_memcpy(mac, ethh->h_source, sizeof(ethh->h_source));
|
0,
|
||||||
|
bpf_htonl((ethh->h_source[0] << 8) + (ethh->h_source[1])),
|
||||||
|
bpf_htonl((ethh->h_source[2] << 24) + (ethh->h_source[3] << 16) +
|
||||||
|
(ethh->h_source[4] << 8) + (ethh->h_source[5])),
|
||||||
|
};
|
||||||
if ((ret = routing(flag, tcph, saddr, daddr, mac)) < 0) {
|
if ((ret = routing(flag, tcph, saddr, daddr, mac)) < 0) {
|
||||||
bpf_printk("shot routing: %ld", ret);
|
bpf_printk("shot routing: %ld", ret);
|
||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
@ -1031,15 +1037,19 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
|||||||
new_hdr.port = udph->dest;
|
new_hdr.port = udph->dest;
|
||||||
|
|
||||||
// Routing. It decides if we redirect traffic to control plane.
|
// Routing. It decides if we redirect traffic to control plane.
|
||||||
__u8 flag[2] = {NETWORK_TYPE_UDP};
|
__u8 flag[2] = {L4PROTO_TYPE_UDP};
|
||||||
if (ipv6h) {
|
if (ipv6h) {
|
||||||
flag[1] = IPVERSION_6;
|
flag[1] = IPVERSION_6;
|
||||||
} else {
|
} else {
|
||||||
flag[1] = IPVERSION_4;
|
flag[1] = IPVERSION_4;
|
||||||
}
|
}
|
||||||
__be32 mac[4];
|
__be32 mac[4] = {
|
||||||
__builtin_memset(mac, 0, IPV6_BYTE_LENGTH);
|
0,
|
||||||
__builtin_memcpy(mac, ethh->h_source, sizeof(ethh->h_source));
|
0,
|
||||||
|
bpf_htonl((ethh->h_source[0] << 8) + (ethh->h_source[1])),
|
||||||
|
bpf_htonl((ethh->h_source[2] << 24) + (ethh->h_source[3] << 16) +
|
||||||
|
(ethh->h_source[4] << 8) + (ethh->h_source[5])),
|
||||||
|
};
|
||||||
if ((ret = routing(flag, udph, saddr, daddr, mac)) < 0) {
|
if ((ret = routing(flag, udph, saddr, daddr, mac)) < 0) {
|
||||||
bpf_printk("shot routing: %ld", ret);
|
bpf_printk("shot routing: %ld", ret);
|
||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
@ -1131,12 +1141,12 @@ int tproxy_egress(struct __sk_buff *skb) {
|
|||||||
if (iph) {
|
if (iph) {
|
||||||
saddr[0] = 0;
|
saddr[0] = 0;
|
||||||
saddr[1] = 0;
|
saddr[1] = 0;
|
||||||
saddr[2] = bpf_ntohl(0xffff);
|
saddr[2] = bpf_htonl(0x0000ffff);
|
||||||
saddr[3] = iph->saddr;
|
saddr[3] = iph->saddr;
|
||||||
|
|
||||||
daddr[0] = 0;
|
daddr[0] = 0;
|
||||||
daddr[1] = 0;
|
daddr[1] = 0;
|
||||||
daddr[2] = bpf_ntohl(0xffff);
|
daddr[2] = bpf_htonl(0x0000ffff);
|
||||||
daddr[3] = iph->daddr;
|
daddr[3] = iph->daddr;
|
||||||
} else if (ipv6h) {
|
} else if (ipv6h) {
|
||||||
__builtin_memcpy(daddr, ipv6h->daddr.in6_u.u6_addr32, IPV6_BYTE_LENGTH);
|
__builtin_memcpy(daddr, ipv6h->daddr.in6_u.u6_addr32, IPV6_BYTE_LENGTH);
|
||||||
|
@ -74,6 +74,27 @@ func (b *RoutingMatcherBuilder) AddDomain(key string, values []string, outbound
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *RoutingMatcherBuilder) AddMac(macAddrs [][6]byte, outbound string) {
|
||||||
|
if b.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var addr16 [16]byte
|
||||||
|
values := make([]netip.Prefix, 0, len(macAddrs))
|
||||||
|
for _, mac := range macAddrs {
|
||||||
|
copy(addr16[10:], mac[:])
|
||||||
|
prefix := netip.PrefixFrom(netip.AddrFrom16(addr16), 128)
|
||||||
|
values = append(values, prefix)
|
||||||
|
}
|
||||||
|
lpmTrieIndex := len(b.SimulatedLpmTries)
|
||||||
|
b.SimulatedLpmTries = append(b.SimulatedLpmTries, values)
|
||||||
|
b.rules = append(b.rules, bpfRouting{
|
||||||
|
Type: uint8(consts.RoutingType_Mac),
|
||||||
|
Value: uint32(lpmTrieIndex),
|
||||||
|
Outbound: b.OutboundToId(outbound),
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (b *RoutingMatcherBuilder) AddIp(values []netip.Prefix, outbound string) {
|
func (b *RoutingMatcherBuilder) AddIp(values []netip.Prefix, outbound string) {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return
|
return
|
||||||
@ -87,6 +108,41 @@ func (b *RoutingMatcherBuilder) AddIp(values []netip.Prefix, outbound string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *RoutingMatcherBuilder) AddSource(values []netip.Prefix, outbound string) {
|
||||||
|
if b.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lpmTrieIndex := len(b.SimulatedLpmTries)
|
||||||
|
b.SimulatedLpmTries = append(b.SimulatedLpmTries, values)
|
||||||
|
b.rules = append(b.rules, bpfRouting{
|
||||||
|
Type: uint8(consts.RoutingType_SourceIpSet),
|
||||||
|
Value: uint32(lpmTrieIndex),
|
||||||
|
Outbound: b.OutboundToId(outbound),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *RoutingMatcherBuilder) AddL4Proto(values consts.L4ProtoType, outbound string) {
|
||||||
|
if b.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.rules = append(b.rules, bpfRouting{
|
||||||
|
Type: uint8(consts.RoutingType_L4Proto),
|
||||||
|
Value: uint32(values),
|
||||||
|
Outbound: b.OutboundToId(outbound),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *RoutingMatcherBuilder) AddIpVersion(values consts.IpVersion, outbound string) {
|
||||||
|
if b.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.rules = append(b.rules, bpfRouting{
|
||||||
|
Type: uint8(consts.RoutingType_IpVersion),
|
||||||
|
Value: uint32(values),
|
||||||
|
Outbound: b.OutboundToId(outbound),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (b *RoutingMatcherBuilder) AddFinal(outbound string) {
|
func (b *RoutingMatcherBuilder) AddFinal(outbound string) {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return
|
return
|
||||||
|
@ -7,6 +7,7 @@ package routing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/v2rayA/dae/common"
|
||||||
"github.com/v2rayA/dae/common/consts"
|
"github.com/v2rayA/dae/common/consts"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
@ -20,7 +21,7 @@ type MatcherBuilder interface {
|
|||||||
AddPort(values [][2]int, outbound string)
|
AddPort(values [][2]int, outbound string)
|
||||||
AddSource(values []netip.Prefix, outbound string)
|
AddSource(values []netip.Prefix, outbound string)
|
||||||
AddSourcePort(values [][2]int, outbound string)
|
AddSourcePort(values [][2]int, outbound string)
|
||||||
AddNetwork(values consts.NetworkType, outbound string)
|
AddL4Proto(values consts.L4ProtoType, outbound string)
|
||||||
AddIpVersion(values consts.IpVersion, outbound string)
|
AddIpVersion(values consts.IpVersion, outbound string)
|
||||||
AddMac(values [][6]byte, outbound string)
|
AddMac(values [][6]byte, outbound string)
|
||||||
AddFinal(outbound string)
|
AddFinal(outbound string)
|
||||||
@ -66,14 +67,66 @@ func ApplyMatcherBuilder(builder MatcherBuilder, rules []RoutingRule, finalOutbo
|
|||||||
}
|
}
|
||||||
builder.AddAnyBefore(key, paramValueGroup, outbound)
|
builder.AddAnyBefore(key, paramValueGroup, outbound)
|
||||||
switch f.Name {
|
switch f.Name {
|
||||||
case "domain":
|
case consts.Function_Domain:
|
||||||
builder.AddDomain(key, paramValueGroup, outbound)
|
builder.AddDomain(key, paramValueGroup, outbound)
|
||||||
case "ip":
|
case consts.Function_Ip, consts.Function_SourceIp:
|
||||||
cidrs, err := ParsePrefixes(paramValueGroup)
|
cidrs, err := ParsePrefixes(paramValueGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
builder.AddIp(cidrs, outbound)
|
if f.Name == consts.Function_Ip {
|
||||||
|
builder.AddIp(cidrs, outbound)
|
||||||
|
} else {
|
||||||
|
builder.AddSource(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.AddMac(macAddrs, outbound)
|
||||||
|
case consts.Function_Port, consts.Function_SourcePort:
|
||||||
|
var portRanges [][2]int
|
||||||
|
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(portRanges, outbound)
|
||||||
|
} else {
|
||||||
|
builder.AddSourcePort(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(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(ipVersion, outbound)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported function name: %v", f.Name)
|
||||||
}
|
}
|
||||||
builder.AddAnyAfter(key, paramValueGroup, outbound)
|
builder.AddAnyAfter(key, paramValueGroup, outbound)
|
||||||
}
|
}
|
||||||
@ -92,7 +145,7 @@ func (d *DefaultMatcherBuilder) AddIp(values []netip.Prefix, outbound string)
|
|||||||
func (d *DefaultMatcherBuilder) AddPort(values [][2]int, outbound string) {}
|
func (d *DefaultMatcherBuilder) AddPort(values [][2]int, outbound string) {}
|
||||||
func (d *DefaultMatcherBuilder) AddSource(values []netip.Prefix, outbound string) {}
|
func (d *DefaultMatcherBuilder) AddSource(values []netip.Prefix, outbound string) {}
|
||||||
func (d *DefaultMatcherBuilder) AddSourcePort(values [][2]int, outbound string) {}
|
func (d *DefaultMatcherBuilder) AddSourcePort(values [][2]int, outbound string) {}
|
||||||
func (d *DefaultMatcherBuilder) AddNetwork(values consts.NetworkType, outbound string) {}
|
func (d *DefaultMatcherBuilder) AddL4Proto(values consts.L4ProtoType, outbound string) {}
|
||||||
func (d *DefaultMatcherBuilder) AddIpVersion(values consts.IpVersion, outbound string) {}
|
func (d *DefaultMatcherBuilder) AddIpVersion(values consts.IpVersion, outbound string) {}
|
||||||
func (d *DefaultMatcherBuilder) AddMac(values [][6]byte, outbound string) {}
|
func (d *DefaultMatcherBuilder) AddMac(values [][6]byte, outbound string) {}
|
||||||
func (d *DefaultMatcherBuilder) AddFinal(outbound string) {}
|
func (d *DefaultMatcherBuilder) AddFinal(outbound string) {}
|
||||||
|
@ -131,11 +131,10 @@ func (s *RoutingAWalker) parseFunctionPrototype(ctx *routingA.FunctionPrototypeC
|
|||||||
// Validate function name and param keys.
|
// Validate function name and param keys.
|
||||||
for _, param := range params {
|
for _, param := range params {
|
||||||
switch funcName {
|
switch funcName {
|
||||||
case "domain":
|
case consts.Function_Domain:
|
||||||
switch param.Key {
|
switch param.Key {
|
||||||
case "", "domain", consts.RoutingDomain_Suffix,
|
case "", consts.RoutingDomain_Suffix,
|
||||||
consts.RoutingDomain_Keyword,
|
consts.RoutingDomain_Keyword,
|
||||||
"contains",
|
|
||||||
consts.RoutingDomain_Full,
|
consts.RoutingDomain_Full,
|
||||||
consts.RoutingDomain_Regex,
|
consts.RoutingDomain_Regex,
|
||||||
"geosite":
|
"geosite":
|
||||||
@ -143,14 +142,14 @@ func (s *RoutingAWalker) parseFunctionPrototype(ctx *routingA.FunctionPrototypeC
|
|||||||
s.reportKeyUnsupportedError(ctx, param.Key, funcName)
|
s.reportKeyUnsupportedError(ctx, param.Key, funcName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case "ip":
|
case consts.Function_Ip, consts.Function_SourceIp:
|
||||||
switch param.Key {
|
switch param.Key {
|
||||||
case "", "geoip":
|
case "", "geoip":
|
||||||
default:
|
default:
|
||||||
s.reportKeyUnsupportedError(ctx, param.Key, funcName)
|
s.reportKeyUnsupportedError(ctx, param.Key, funcName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case "port", "source", "sourcePort", "network", "ipVersion":
|
case consts.Function_Port, consts.Function_SourcePort, consts.Function_Mac, consts.Function_L4Proto, consts.Function_IpVersion:
|
||||||
if param.Key != "" {
|
if param.Key != "" {
|
||||||
s.reportKeyUnsupportedError(ctx, param.Key, funcName)
|
s.reportKeyUnsupportedError(ctx, param.Key, funcName)
|
||||||
return nil
|
return nil
|
||||||
|
6
main.go
6
main.go
@ -26,10 +26,14 @@ func main() {
|
|||||||
log.Println("Running")
|
log.Println("Running")
|
||||||
t, err := control.NewControlPlane(log, `
|
t, err := control.NewControlPlane(log, `
|
||||||
default:proxy
|
default:proxy
|
||||||
|
#sip(172.17.0.2)->proxy
|
||||||
|
#mac("02:42:ac:11:00:02")->proxy
|
||||||
|
#ipversion(4)->proxy
|
||||||
|
#l4proto(tcp)->proxy
|
||||||
ip(119.29.29.29) -> proxy
|
ip(119.29.29.29) -> proxy
|
||||||
ip(223.5.5.5) -> direct
|
ip(223.5.5.5) -> direct
|
||||||
ip(geoip:cn) -> direct
|
ip(geoip:cn) -> direct
|
||||||
domain(geosite:cn, domain:"ip.sb") -> direct
|
domain(geosite:cn, suffix:"ip.sb") -> direct
|
||||||
ip("91.105.192.0/23","91.108.4.0/22","91.108.8.0/21","91.108.16.0/21","91.108.56.0/22","95.161.64.0/20","149.154.160.0/20","185.76.151.0/24")->proxy
|
ip("91.105.192.0/23","91.108.4.0/22","91.108.8.0/21","91.108.16.0/21","91.108.56.0/22","95.161.64.0/20","149.154.160.0/20","185.76.151.0/24")->proxy
|
||||||
domain(geosite:category-scholar-!cn, geosite:category-scholar-cn)->direct
|
domain(geosite:category-scholar-!cn, geosite:category-scholar-cn)->direct
|
||||||
`)
|
`)
|
||||||
|
Loading…
Reference in New Issue
Block a user