fix: ip matching problem and add control plane direct

This commit is contained in:
mzz2017 2023-01-24 16:27:19 +08:00
parent 799cd006c0
commit 14b215752f
9 changed files with 63 additions and 47 deletions

View File

@ -10,8 +10,7 @@ As a successor of [v2rayA](https://github.com/v2rayA/v2rayA), dae abandoned v2ra
## TODO
1. Control plane does support MAC and other matching yet.
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. Control plane route.
1. Routing performance optimization.
1. ...
1. ...

View File

@ -50,17 +50,17 @@ const (
type OutboundIndex uint8
const (
OutboundDirect OutboundIndex = 0
OutboundControlPlaneRoute OutboundIndex = 0xFE
OutboundLogicalAnd OutboundIndex = 0xFF
OutboundDirect OutboundIndex = 0
OutboundControlPlaneDirect OutboundIndex = 0xFE
OutboundLogicalAnd OutboundIndex = 0xFF
)
func (i OutboundIndex) String() string {
switch i {
case OutboundDirect:
return "direct"
case OutboundControlPlaneRoute:
return "<Control Plane Route>"
case OutboundControlPlaneDirect:
return "<Control Plane Direct>"
case OutboundLogicalAnd:
return "<AND>"
default:

View File

@ -111,26 +111,6 @@ retry_load:
//}
/**/
rules, final, err := routing.Parse(routingA)
if err != nil {
return nil, fmt.Errorf("routingA error:\n%w", err)
}
if rules, err = routing.ApplyRulesOptimizers(rules,
&routing.RefineFunctionParamKeyOptimizer{},
&routing.DatReaderOptimizer{Logger: log},
&routing.MergeAndSortRulesOptimizer{},
&routing.DeduplicateParamsOptimizer{},
); err != nil {
return nil, fmt.Errorf("ApplyRulesOptimizers error: \n %w", err)
}
if log.IsLevelEnabled(logrus.TraceLevel) {
var debugBuilder strings.Builder
for _, rule := range rules {
debugBuilder.WriteString(rule.String(true))
}
log.Tracef("RoutingA:\n%vfinal: %v\n", debugBuilder.String(), final)
}
// TODO:
d, err := dialer.NewFromLink("socks5://localhost:1080#proxy")
if err != nil {
@ -158,6 +138,27 @@ retry_load:
outboundName2Id[o.Name] = uint8(i)
}
builder := NewRoutingMatcherBuilder(outboundName2Id, &bpf)
// Routing.
rules, final, err := routing.Parse(routingA)
if err != nil {
return nil, fmt.Errorf("routingA error:\n%w", err)
}
if rules, err = routing.ApplyRulesOptimizers(rules,
&routing.RefineFunctionParamKeyOptimizer{},
&routing.DatReaderOptimizer{Logger: log},
&routing.MergeAndSortRulesOptimizer{},
&routing.DeduplicateParamsOptimizer{},
); err != nil {
return nil, fmt.Errorf("ApplyRulesOptimizers error: \n %w", err)
}
if log.IsLevelEnabled(logrus.TraceLevel) {
var debugBuilder strings.Builder
for _, rule := range rules {
debugBuilder.WriteString(rule.String(true))
}
log.Tracef("RoutingA:\n%vfinal: %v\n", debugBuilder.String(), final)
}
if err := routing.ApplyMatcherBuilder(builder, rules, final); err != nil {
return nil, fmt.Errorf("ApplyMatcherBuilder: %w", err)
}

View File

@ -47,7 +47,7 @@
#define IPV6_MAX_EXTENSIONS 4
#define OUTBOUND_DIRECT 0
#define OUTBOUND_CONTROL_PLANE_ROUTE 0xFE
#define OUTBOUND_CONTROL_PLANE_DIRECT 0xFE
#define OUTBOUND_LOGICAL_AND 0xFF
enum {
@ -753,10 +753,6 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
h_dport = bpf_ntohs(((struct udphdr *)l4_hdr)->dest);
h_sport = bpf_ntohs(((struct udphdr *)l4_hdr)->source);
}
// Redirect all DNS packet to control plane.
if (_network == NETWORK_TYPE_UDP && h_dport == 53) {
return OUTBOUND_CONTROL_PLANE_ROUTE;
}
struct lpm_key lpm_key_saddr, lpm_key_daddr, lpm_key_mac, *lpm_key;
lpm_key_saddr.trie_key.prefixlen = IPV6_BYTE_LENGTH * 8;
lpm_key_daddr.trie_key.prefixlen = IPV6_BYTE_LENGTH * 8;
@ -775,7 +771,7 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
/// this branch will never hit.
// if (domain_routing && domain_routing->epoch != *epoch) {
// // Dirty (epoch dismatch) traffic should be routed by the control plane.
// return OUTBOUND_CONTROL_PLANE_ROUTE;
// return OUTBOUND_CONTROL_PLANE_DIRECT;
// }
#pragma unroll
@ -790,10 +786,10 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
}
/// NOTICE: switch is not implemented efficiently by clang yet.
if (likely(routing->type == ROUTING_TYPE_IP_SET)) {
lpm_key = &lpm_key_saddr;
lpm_key = &lpm_key_daddr;
goto lookup_lpm;
} else if (routing->type == ROUTING_TYPE_SOURCE_IP_SET) {
lpm_key = &lpm_key_daddr;
lpm_key = &lpm_key_saddr;
lookup_lpm:
lpm = bpf_map_lookup_elem(&lpm_array_map, &routing->index);
if (unlikely(!lpm)) {
@ -802,6 +798,9 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
if (!bpf_map_lookup_elem(lpm, lpm_key)) {
// Routing not hit.
bad_rule = true;
bpf_printk("index: %u not hit", routing->index);
} else {
bpf_printk("index: %u hit", routing->index);
}
} else if (routing->type == ROUTING_TYPE_DOMAIN_SET) {
// Bottleneck of insns limit.
@ -842,7 +841,8 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
lpm_key = &lpm_key_mac;
goto lookup_lpm;
} else if (routing->type == ROUTING_TYPE_FINAL) {
return routing->outbound;
// Redirect all DNS packet to control plane.
bad_rule = false;
} else {
return -EINVAL;
}
@ -852,11 +852,18 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
// Tail of a rule (line).
// Decide whether to hit.
if (!bad_rule) {
if (routing->outbound == OUTBOUND_DIRECT && h_dport == 53 &&
_network == NETWORK_TYPE_UDP) {
// DNS packet should go through control plane.
return OUTBOUND_CONTROL_PLANE_DIRECT;
}
return routing->outbound;
}
bad_rule = false;
}
}
bpf_printk(
"Did coder forget to sync common/consts/ebpf.go with enum ROUTING_TYPE?");
return -EPERM;
#undef _network
#undef _ip_version

View File

@ -7,10 +7,10 @@ package control
import (
"fmt"
"github.com/cilium/ebpf"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/common/consts"
"github.com/v2rayA/dae/component/routing"
"github.com/cilium/ebpf"
"net/netip"
"strconv"
)
@ -88,6 +88,9 @@ func (b *RoutingMatcherBuilder) AddIp(values []netip.Prefix, outbound string) {
}
func (b *RoutingMatcherBuilder) AddFinal(outbound string) {
if b.err != nil {
return
}
b.Final = outbound
b.rules = append(b.rules, bpfRouting{
Type: uint8(consts.RoutingType_Final),

View File

@ -37,11 +37,10 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
switch consts.OutboundIndex(value.Outbound) {
case consts.OutboundDirect:
case consts.OutboundControlPlaneRoute:
// FIXME: check and re-route.
case consts.OutboundControlPlaneDirect:
value.Outbound = uint8(consts.OutboundDirect)
c.log.Debugf("outbound: %v => %v",
consts.OutboundControlPlaneRoute.String(),
consts.OutboundControlPlaneDirect.String(),
consts.OutboundIndex(value.Outbound).String(),
)
default:

View File

@ -91,12 +91,11 @@ func (c *ControlPlane) RelayToUDP(lConn *net.UDPConn, to netip.AddrPort, isDNS b
func (c *ControlPlane) handlePkt(data []byte, lConn *net.UDPConn, lAddrPort netip.AddrPort, addrHdr *AddrHdr) (err error) {
switch consts.OutboundIndex(addrHdr.Outbound) {
case consts.OutboundDirect:
case consts.OutboundControlPlaneRoute:
// FIXME: check and re-route.
case consts.OutboundControlPlaneDirect:
addrHdr.Outbound = uint8(consts.OutboundDirect)
c.log.Debugf("outbound: %v => %v",
consts.OutboundControlPlaneRoute.String(),
consts.OutboundControlPlaneDirect.String(),
consts.OutboundIndex(addrHdr.Outbound).String(),
)
default:

View File

@ -6,8 +6,8 @@
package control
import (
"github.com/v2rayA/dae/common"
"github.com/cilium/ebpf"
"github.com/v2rayA/dae/common"
"net/netip"
)
@ -17,7 +17,13 @@ type bpfLpmKey struct {
}
func (o *bpfObjects) NewLpmMap(keys []bpfLpmKey, values []uint32) (m *ebpf.Map, err error) {
m, err = o.UnusedLpmType.Clone()
m, err = ebpf.NewMap(&ebpf.MapSpec{
Type: ebpf.LPMTrie,
Flags: o.UnusedLpmType.Flags(),
MaxEntries: o.UnusedLpmType.MaxEntries(),
KeySize: o.UnusedLpmType.KeySize(),
ValueSize: o.UnusedLpmType.ValueSize(),
})
if err != nil {
return nil, err
}
@ -35,10 +41,10 @@ func swap16(a uint16) uint16 {
func cidrToBpfLpmKey(prefix netip.Prefix) bpfLpmKey {
bits := prefix.Bits()
ip := prefix.Addr().As16()
if prefix.Addr().Is4() {
bits += 96
}
ip := prefix.Addr().As16()
return bpfLpmKey{
PrefixLen: uint32(bits),
Data: common.Ipv6ByteSliceToUint32Array(ip[:]),

View File

@ -26,6 +26,8 @@ func main() {
log.Println("Running")
t, err := control.NewControlPlane(log, `
default:proxy
ip(119.29.29.29) -> proxy
ip(223.5.5.5) -> direct
ip(geoip:cn) -> direct
domain(geosite:cn, domain:"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