mirror of
https://github.com/daeuniverse/dae.git
synced 2025-02-02 04:14:31 +07:00
fix: routing problems
This commit is contained in:
parent
c8d11cbecf
commit
e4996ace25
@ -27,8 +27,8 @@ type _bpfPortRange struct {
|
||||
|
||||
func (r _bpfPortRange) Encode() uint32 {
|
||||
var b [4]byte
|
||||
binary.LittleEndian.PutUint16(b[:2], r.PortStart)
|
||||
binary.LittleEndian.PutUint16(b[2:], r.PortEnd)
|
||||
binary.BigEndian.PutUint16(b[:2], r.PortStart)
|
||||
binary.BigEndian.PutUint16(b[2:], r.PortEnd)
|
||||
return binary.BigEndian.Uint32(b[:])
|
||||
}
|
||||
|
||||
|
@ -93,10 +93,10 @@ retryLoadBpf:
|
||||
}
|
||||
mapName, _, _ := strings.Cut(after, ":")
|
||||
_ = os.Remove(filepath.Join(pinPath, mapName))
|
||||
log.Warnf("New map format was incompatible with existing map %v, and the old one was removed.", mapName)
|
||||
log.Infof("Incompatible new map format with existing map %v detected; removed the old one.", mapName)
|
||||
goto retryLoadBpf
|
||||
}
|
||||
// Get detailed log from ebpf.internal.*VerifierError
|
||||
// Get detailed log from ebpf.internal.(*VerifierError)
|
||||
if log.IsLevelEnabled(logrus.TraceLevel) {
|
||||
if v := reflect.Indirect(reflect.ValueOf(errors.Unwrap(errors.Unwrap(err)))); v.Kind() == reflect.Struct {
|
||||
if log := v.FieldByName("Log"); log.IsValid() {
|
||||
@ -199,12 +199,12 @@ retryLoadBpf:
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("ApplyRulesOptimizers error: \n %w", err)
|
||||
}
|
||||
if log.IsLevelEnabled(logrus.TraceLevel) {
|
||||
if log.IsLevelEnabled(logrus.DebugLevel) {
|
||||
var debugBuilder strings.Builder
|
||||
for _, rule := range rules {
|
||||
debugBuilder.WriteString(rule.String(true) + "\n")
|
||||
}
|
||||
log.Tracef("RoutingA:\n%vfinal: %v\n", debugBuilder.String(), routingA.Final)
|
||||
log.Debugf("RoutingA:\n%vfinal: %v\n", debugBuilder.String(), routingA.Final)
|
||||
}
|
||||
if err = routing.ApplyMatcherBuilder(builder, rules, routingA.Final); err != nil {
|
||||
return nil, fmt.Errorf("ApplyMatcherBuilder: %w", err)
|
||||
|
@ -104,7 +104,7 @@ struct {
|
||||
|
||||
// LPM key:
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
|
||||
__type(key, __u32);
|
||||
__type(value, struct lpm_key);
|
||||
__uint(max_entries, 3);
|
||||
@ -113,17 +113,17 @@ struct {
|
||||
|
||||
// h_sport, h_dport:
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
|
||||
__type(key, __u32);
|
||||
__type(value, __u32);
|
||||
__type(value, __u16);
|
||||
__uint(max_entries, 2);
|
||||
__uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
} h_port_map SEC(".maps");
|
||||
|
||||
// l4proto, ipversion:
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__type(key, __u64);
|
||||
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
|
||||
__type(key, __u32);
|
||||
__type(value, __u32);
|
||||
__uint(max_entries, 2);
|
||||
__uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
@ -277,9 +277,9 @@ static __always_inline __u32 l4_checksum_off(__u8 proto, __u8 ihl) {
|
||||
return ETH_HLEN + ihl * 4 + l4_checksum_rel_off(proto);
|
||||
}
|
||||
|
||||
static __always_inline long rewrite_ip(struct __sk_buff *skb, bool is_ipv6,
|
||||
__u8 proto, __u8 ihl, __be32 old_ip[4],
|
||||
__be32 new_ip[4], bool is_dest) {
|
||||
static __always_inline int rewrite_ip(struct __sk_buff *skb, bool is_ipv6,
|
||||
__u8 proto, __u8 ihl, __be32 old_ip[4],
|
||||
__be32 new_ip[4], bool is_dest) {
|
||||
// Nothing to do.
|
||||
if (equal_ipv6_format(old_ip, new_ip)) {
|
||||
return 0;
|
||||
@ -287,7 +287,7 @@ static __always_inline long rewrite_ip(struct __sk_buff *skb, bool is_ipv6,
|
||||
// bpf_printk("%pI6->%pI6", old_ip, new_ip);
|
||||
|
||||
__u32 l4_cksm_off = l4_checksum_off(proto, ihl);
|
||||
long ret;
|
||||
int ret;
|
||||
// BPF_F_PSEUDO_HDR indicates the part we want to modify is part of the
|
||||
// pseudo header.
|
||||
__u32 l4flags = BPF_F_PSEUDO_HDR;
|
||||
@ -309,7 +309,7 @@ static __always_inline long rewrite_ip(struct __sk_buff *skb, bool is_ipv6,
|
||||
sizeof(_new_ip)))) {
|
||||
return ret;
|
||||
}
|
||||
bpf_printk("%pI4 -> %pI4", &_old_ip, &_new_ip);
|
||||
// bpf_printk("%pI4 -> %pI4", &_old_ip, &_new_ip);
|
||||
|
||||
ret = bpf_skb_store_bytes(skb, is_dest ? IPV4_DST_OFF : IPV4_SRC_OFF,
|
||||
&_new_ip, sizeof(_new_ip), 0);
|
||||
@ -324,7 +324,7 @@ static __always_inline long rewrite_ip(struct __sk_buff *skb, bool is_ipv6,
|
||||
bpf_printk("bpf_l4_csum_replace: %ld", ret);
|
||||
return ret;
|
||||
}
|
||||
bpf_printk("%pI6 -> %pI6", old_ip, new_ip);
|
||||
// bpf_printk("%pI6 -> %pI6", old_ip, new_ip);
|
||||
|
||||
ret = bpf_skb_store_bytes(skb, is_dest ? IPV6_DST_OFF : IPV6_SRC_OFF,
|
||||
new_ip, IPV6_BYTE_LENGTH, 0);
|
||||
@ -337,9 +337,9 @@ static __always_inline long rewrite_ip(struct __sk_buff *skb, bool is_ipv6,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline long rewrite_port(struct __sk_buff *skb, __u8 proto,
|
||||
__u8 ihl, __be16 old_port,
|
||||
__be16 new_port, bool is_dest) {
|
||||
static __always_inline int rewrite_port(struct __sk_buff *skb, __u8 proto,
|
||||
__u8 ihl, __be16 old_port,
|
||||
__be16 new_port, bool is_dest) {
|
||||
// Nothing to do.
|
||||
if (old_port == new_port) {
|
||||
return 0;
|
||||
@ -370,7 +370,7 @@ static __always_inline long rewrite_port(struct __sk_buff *skb, __u8 proto,
|
||||
|
||||
// bpf_printk("%u -> %u", bpf_ntohs(old_port), bpf_ntohs(new_port));
|
||||
|
||||
long ret;
|
||||
int ret;
|
||||
if ((ret = bpf_l4_csum_replace(skb, cksm_off, old_port, new_port,
|
||||
l4flags | sizeof(new_port)))) {
|
||||
bpf_printk("bpf_l4_csum_replace: %ld", ret);
|
||||
@ -385,7 +385,7 @@ static __always_inline long rewrite_port(struct __sk_buff *skb, __u8 proto,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline long
|
||||
static __always_inline int
|
||||
handle_ipv6_extensions(void *data, void *data_end, __u32 hdr,
|
||||
struct tcphdr **tcph, struct udphdr **udph, __u8 *ihl) {
|
||||
__u8 hdr_length = 0;
|
||||
@ -454,7 +454,7 @@ handle_ipv6_extensions(void *data, void *data_end, __u32 hdr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __always_inline long
|
||||
static __always_inline int
|
||||
parse_transport(struct __sk_buff *skb, struct ethhdr **ethh, struct iphdr **iph,
|
||||
struct ipv6hdr **ipv6h, struct tcphdr **tcph,
|
||||
struct udphdr **udph, __u8 *ihl) {
|
||||
@ -517,8 +517,8 @@ parse_transport(struct __sk_buff *skb, struct ethhdr **ethh, struct iphdr **iph,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __always_inline long ip_is_host(bool is_ipv6, __u32 ifindex,
|
||||
__be32 ip[4], __be32 tproxy_ip[4]) {
|
||||
static __always_inline int ip_is_host(bool is_ipv6, __u32 ifindex, __be32 ip[4],
|
||||
__be32 tproxy_ip[4]) {
|
||||
if (tproxy_ip) {
|
||||
struct if_ip *if_ip = bpf_map_lookup_elem(&ifindex_tproxy_ip_map, &ifindex);
|
||||
if (unlikely(!if_ip)) {
|
||||
@ -540,8 +540,8 @@ static __always_inline long ip_is_host(bool is_ipv6, __u32 ifindex,
|
||||
return bpf_map_lookup_elem(&host_ip_lpm, &lpm_key) ? 1 : 0;
|
||||
}
|
||||
|
||||
static __always_inline long adjust_udp_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
__u32 ihl, __u16 len_diff) {
|
||||
static __always_inline int adjust_udp_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
__u32 ihl, __u16 len_diff) {
|
||||
if (unlikely(!len_diff)) {
|
||||
return 0;
|
||||
}
|
||||
@ -561,7 +561,7 @@ static __always_inline long adjust_udp_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
__be16 newlen = bpf_htons(bpf_ntohs(oldlen) + len_diff);
|
||||
|
||||
// Calculate checksum and store the new value.
|
||||
long ret;
|
||||
int ret;
|
||||
|
||||
__u32 udp_csum_off = l4_checksum_off(IPPROTO_UDP, ihl);
|
||||
// replace twice because len exists both pseudo hdr and hdr.
|
||||
@ -586,8 +586,8 @@ static __always_inline long adjust_udp_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline long adjust_ipv4_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
__u16 len_diff) {
|
||||
static __always_inline int adjust_ipv4_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
__u16 len_diff) {
|
||||
if (unlikely(!len_diff)) {
|
||||
return 0;
|
||||
}
|
||||
@ -607,7 +607,7 @@ static __always_inline long adjust_ipv4_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
__be16 newlen = bpf_htons(bpf_ntohs(oldlen) + len_diff);
|
||||
|
||||
// Calculate checksum and store the new value.
|
||||
long ret;
|
||||
int ret;
|
||||
if ((ret = bpf_l3_csum_replace(skb, IPV4_CSUM_OFF, oldlen, newlen,
|
||||
sizeof(oldlen)))) {
|
||||
bpf_printk("bpf_l3_csum_replace newudplen: %ld", ret);
|
||||
@ -622,10 +622,10 @@ static __always_inline long adjust_ipv4_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline long encap_after_udp_hdr(struct __sk_buff *skb,
|
||||
bool is_ipv6, __u8 ihl,
|
||||
__be16 iphdr_tot_len,
|
||||
void *newhdr, __u32 newhdrlen) {
|
||||
static __always_inline int encap_after_udp_hdr(struct __sk_buff *skb,
|
||||
bool is_ipv6, __u8 ihl,
|
||||
__be16 iphdr_tot_len,
|
||||
void *newhdr, __u32 newhdrlen) {
|
||||
if (unlikely(newhdrlen % 4 != 0)) {
|
||||
bpf_printk("encap_after_udp_hdr: unexpected newhdrlen value %u :must "
|
||||
"be a multiple of 4",
|
||||
@ -633,7 +633,7 @@ static __always_inline long encap_after_udp_hdr(struct __sk_buff *skb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
long ret = 0;
|
||||
int ret = 0;
|
||||
long ip_off = ETH_HLEN;
|
||||
// Calculate offsets using add instead of subtract to avoid verifier problems.
|
||||
long ipp_len = ihl * 4;
|
||||
@ -699,7 +699,7 @@ static __always_inline int decap_after_udp_hdr(struct __sk_buff *skb,
|
||||
decap_hdrlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
long ret = 0;
|
||||
int ret = 0;
|
||||
long ip_off = ETH_HLEN;
|
||||
// Calculate offsets using add instead of subtract to avoid verifier problems.
|
||||
long ipp_len = ihl * 4;
|
||||
@ -767,17 +767,23 @@ static __always_inline int decap_after_udp_hdr(struct __sk_buff *skb,
|
||||
}
|
||||
|
||||
// Do not use __always_inline here because this function is too heavy.
|
||||
static long routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
|
||||
__be32 daddr[4], __be32 mac[4]) {
|
||||
static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
|
||||
__be32 daddr[4], __be32 mac[4]) {
|
||||
#define _l4proto flag[0]
|
||||
#define _ipversion flag[1]
|
||||
#define _hash flag[2]
|
||||
/// TODO: BPF_MAP_UPDATE_BATCH
|
||||
// To avoid racing.
|
||||
__u64 key = ((__u64)_hash << 32) + ROUTING_TYPE_L4PROTO;
|
||||
bpf_map_update_elem(&l4proto_ipversion_map, &key, &_l4proto, BPF_ANY);
|
||||
/// TODO: BPF_MAP_UPDATE_BATCH ?
|
||||
__u32 key = ROUTING_TYPE_L4PROTO;
|
||||
int ret;
|
||||
if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_l4proto,
|
||||
BPF_ANY))) {
|
||||
return ret;
|
||||
};
|
||||
key = ROUTING_TYPE_IPVERSION;
|
||||
bpf_map_update_elem(&l4proto_ipversion_map, &key, &_ipversion, BPF_ANY);
|
||||
if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_ipversion,
|
||||
BPF_ANY))) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Define variables for further use.
|
||||
__u16 h_dport;
|
||||
@ -790,9 +796,13 @@ static long routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
|
||||
h_sport = bpf_ntohs(((struct udphdr *)l4_hdr)->source);
|
||||
}
|
||||
key = ROUTING_TYPE_SOURCE_PORT;
|
||||
bpf_map_update_elem(&h_port_map, &key, &h_sport, BPF_ANY);
|
||||
if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_sport, BPF_ANY))) {
|
||||
return ret;
|
||||
};
|
||||
key = ROUTING_TYPE_PORT;
|
||||
bpf_map_update_elem(&h_port_map, &key, &h_dport, BPF_ANY);
|
||||
if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_dport, BPF_ANY))) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Modify DNS upstream for routing.
|
||||
if (h_dport == 53 && _l4proto == L4PROTO_TYPE_UDP) {
|
||||
@ -812,12 +822,20 @@ static long routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
|
||||
__builtin_memcpy(lpm_key_daddr.data, daddr, IPV6_BYTE_LENGTH);
|
||||
__builtin_memcpy(lpm_key_mac.data, mac, IPV6_BYTE_LENGTH);
|
||||
// bpf_printk("mac: %pI6", mac);
|
||||
key = (key & (__u32)0) | (__u32)ROUTING_TYPE_IP_SET;
|
||||
bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_daddr, BPF_ANY);
|
||||
key = (key & (__u32)0) | (__u32)ROUTING_TYPE_SOURCE_IP_SET;
|
||||
bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_saddr, BPF_ANY);
|
||||
key = (key & (__u32)0) | (__u32)ROUTING_TYPE_MAC;
|
||||
bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_mac, BPF_ANY);
|
||||
key = ROUTING_TYPE_IP_SET;
|
||||
if ((ret =
|
||||
bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_daddr, BPF_ANY))) {
|
||||
return ret;
|
||||
};
|
||||
key = ROUTING_TYPE_SOURCE_IP_SET;
|
||||
if ((ret =
|
||||
bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_saddr, BPF_ANY))) {
|
||||
return ret;
|
||||
};
|
||||
key = ROUTING_TYPE_MAC;
|
||||
if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_mac, BPF_ANY))) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
struct map_lpm_type *lpm;
|
||||
struct match_set *match_set;
|
||||
@ -828,6 +846,7 @@ static long routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
|
||||
bool good_subrule = false;
|
||||
struct domain_routing *domain_routing;
|
||||
__u32 *p_u32;
|
||||
__u16 *p_u16;
|
||||
|
||||
#pragma unroll
|
||||
for (__u32 i = 0; i < MAX_ROUTING_LEN; i++) {
|
||||
@ -837,10 +856,19 @@ static long routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
|
||||
return -EFAULT;
|
||||
}
|
||||
if (bad_rule || good_subrule) {
|
||||
key = match_set->type;
|
||||
// bpf_printk("key(match_set->type): %llu", key);
|
||||
// bpf_printk("Skip to judge. bad_rule: %d, good_subrule: %d", bad_rule,
|
||||
// good_subrule);
|
||||
goto before_next_loop;
|
||||
}
|
||||
key = (key & (__u32)0) | (__u32)match_set->type;
|
||||
key = match_set->type;
|
||||
// bpf_printk("key(match_set->type): %llu", key);
|
||||
if ((lpm_key = bpf_map_lookup_elem(&lpm_key_map, &key))) {
|
||||
// bpf_printk(
|
||||
// "CHECK: lpm_key_map, match_set->type: %u, not: %d, outbound: %u",
|
||||
// match_set->type, match_set->not, match_set->outbound);
|
||||
// bpf_printk("\tip: %pI6", lpm_key->data);
|
||||
lpm = bpf_map_lookup_elem(&lpm_array_map, &match_set->index);
|
||||
if (unlikely(!lpm)) {
|
||||
return -EFAULT;
|
||||
@ -849,16 +877,29 @@ static long routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
|
||||
// match_set hits.
|
||||
good_subrule = true;
|
||||
}
|
||||
} else if ((p_u32 = bpf_map_lookup_elem(&h_port_map, &key))) {
|
||||
if (*p_u32 >= match_set->port_range.port_start &&
|
||||
*p_u32 <= match_set->port_range.port_end) {
|
||||
} else if ((p_u16 = bpf_map_lookup_elem(&h_port_map, &key))) {
|
||||
// bpf_printk(
|
||||
// "CHECK: h_port_map, match_set->type: %u, not: %d, outbound: %u",
|
||||
// match_set->type, match_set->not, match_set->outbound);
|
||||
// bpf_printk("\tport: %u, range: [%u, %u]", *p_u16,
|
||||
// match_set->port_range.port_start,
|
||||
// match_set->port_range.port_end);
|
||||
if (*p_u16 >= match_set->port_range.port_start &&
|
||||
*p_u16 <= match_set->port_range.port_end) {
|
||||
good_subrule = true;
|
||||
}
|
||||
} else if ((p_u32 = bpf_map_lookup_elem(&l4proto_ipversion_map, &key))) {
|
||||
// bpf_printk("CHECK: l4proto_ipversion_map, match_set->type: %u, not: %d,
|
||||
// "
|
||||
// "outbound: %u",
|
||||
// match_set->type, match_set->not, match_set->outbound);
|
||||
if (*p_u32 & match_set->__value) {
|
||||
good_subrule = true;
|
||||
}
|
||||
} else if (match_set->type == ROUTING_TYPE_DOMAIN_SET) {
|
||||
// bpf_printk("CHECK: domain, match_set->type: %u, not: %d, "
|
||||
// "outbound: %u",
|
||||
// match_set->type, match_set->not, match_set->outbound);
|
||||
// Bottleneck of insns limit.
|
||||
// We fixed it by invoking bpf_map_lookup_elem here.
|
||||
|
||||
@ -874,37 +915,42 @@ static long routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
|
||||
good_subrule = true;
|
||||
}
|
||||
} else if (match_set->type == ROUTING_TYPE_FINAL) {
|
||||
// bpf_printk("CHECK: hit final");
|
||||
good_subrule = true;
|
||||
} else {
|
||||
// bpf_printk("CHECK: <unknown>, match_set->type: %u, not: %d, "
|
||||
// "outbound: %u",
|
||||
// match_set->type, match_set->not, match_set->outbound);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
before_next_loop:
|
||||
if (match_set->outbound != OUTBOUND_LOGICAL_OR && !bad_rule) {
|
||||
if (match_set->outbound != OUTBOUND_LOGICAL_OR) {
|
||||
// This match_set reaches the end of subrule.
|
||||
// We are now at end of rule, or next match_set belongs to another
|
||||
// subrule.
|
||||
|
||||
if (good_subrule == match_set->not ) {
|
||||
// This subrule does not hit.
|
||||
bad_rule = true;
|
||||
} else {
|
||||
// This subrule hits.
|
||||
// Reset the good_subrule flag.
|
||||
good_subrule = false;
|
||||
}
|
||||
|
||||
// Reset good_subrule.
|
||||
good_subrule = false;
|
||||
}
|
||||
|
||||
if ((match_set->outbound & OUTBOUND_LOGICAL_MASK) !=
|
||||
OUTBOUND_LOGICAL_MASK) {
|
||||
// Tail of a rule (line).
|
||||
// Decide whether to hit.
|
||||
if (!bad_rule) {
|
||||
// bpf_printk("MATCHED: match_set->type: %u, match_set->not: %d",
|
||||
// match_set->type, match_set->not );
|
||||
if (match_set->outbound == OUTBOUND_DIRECT && h_dport == 53 &&
|
||||
_l4proto == L4PROTO_TYPE_UDP) {
|
||||
// DNS packet should go through control plane.
|
||||
return OUTBOUND_CONTROL_PLANE_DIRECT;
|
||||
}
|
||||
// bpf_printk("match_set->type: %d, match_set->not: %d", match_set->type,
|
||||
// match_set->not );
|
||||
return match_set->outbound;
|
||||
}
|
||||
bad_rule = false;
|
||||
@ -928,7 +974,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
__sum16 bak_cksm;
|
||||
__u8 ihl;
|
||||
bool tcp_state_syn;
|
||||
long ret = parse_transport(skb, ðh, &iph, &ipv6h, &tcph, &udph, &ihl);
|
||||
int ret = parse_transport(skb, ðh, &iph, &ipv6h, &tcph, &udph, &ihl);
|
||||
if (ret) {
|
||||
bpf_printk("parse_transport: %ld", ret);
|
||||
return TC_ACT_OK;
|
||||
@ -965,7 +1011,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
|
||||
// If this packet is sent to this host, accept it.
|
||||
__u32 tproxy_ip[4];
|
||||
long to_host = ip_is_host(ipv6h, skb->ifindex, daddr, tproxy_ip);
|
||||
int to_host = ip_is_host(ipv6h, skb->ifindex, daddr, tproxy_ip);
|
||||
if (to_host < 0) { // error
|
||||
// bpf_printk("to_host: %ld", to_host);
|
||||
return TC_ACT_OK;
|
||||
@ -1018,6 +1064,9 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
}
|
||||
|
||||
outbound = ret;
|
||||
|
||||
// Print only new connection.
|
||||
bpf_printk("tcp: outbound: %u, %pI6", outbound, daddr);
|
||||
} else {
|
||||
// bpf_printk("[%X]Old Connection", bpf_ntohl(tcph->seq));
|
||||
// The TCP connection exists.
|
||||
@ -1029,7 +1078,6 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
outbound = dst->outbound;
|
||||
}
|
||||
|
||||
bpf_printk("tcp: outbound: %u, %pI6", outbound, daddr);
|
||||
if (outbound == OUTBOUND_DIRECT) {
|
||||
return TC_ACT_OK;
|
||||
} else if (unlikely(outbound == OUTBOUND_BLOCK)) {
|
||||
@ -1165,7 +1213,7 @@ int tproxy_egress(struct __sk_buff *skb) {
|
||||
__sum16 bak_cksm;
|
||||
__u8 l4_proto;
|
||||
__u8 ihl;
|
||||
long ret = parse_transport(skb, ðh, &iph, &ipv6h, &tcph, &udph, &ihl);
|
||||
int ret = parse_transport(skb, ðh, &iph, &ipv6h, &tcph, &udph, &ihl);
|
||||
if (ret) {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
@ -116,8 +116,12 @@ func (b *RoutingMatcherBuilder) AddIp(f *config_parser.Function, values []netip.
|
||||
})
|
||||
}
|
||||
|
||||
func (b *RoutingMatcherBuilder) AddPort(f *config_parser.Function, values [][2]uint16, outbound string) {
|
||||
for _, value := range values {
|
||||
func (b *RoutingMatcherBuilder) AddPort(f *config_parser.Function, values [][2]uint16, _outbound string) {
|
||||
for i, value := range values {
|
||||
outbound := routing.FakeOutbound_OR
|
||||
if i == len(values)-1 {
|
||||
outbound = _outbound
|
||||
}
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
Type: uint32(consts.RoutingType_Port),
|
||||
Value: _bpfPortRange{
|
||||
@ -144,8 +148,12 @@ func (b *RoutingMatcherBuilder) AddSourceIp(f *config_parser.Function, values []
|
||||
})
|
||||
}
|
||||
|
||||
func (b *RoutingMatcherBuilder) AddSourcePort(f *config_parser.Function, values [][2]uint16, outbound string) {
|
||||
for _, value := range values {
|
||||
func (b *RoutingMatcherBuilder) AddSourcePort(f *config_parser.Function, values [][2]uint16, _outbound string) {
|
||||
for i, value := range values {
|
||||
outbound := routing.FakeOutbound_OR
|
||||
if i == len(values)-1 {
|
||||
outbound = _outbound
|
||||
}
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
Type: uint32(consts.RoutingType_SourcePort),
|
||||
Value: _bpfPortRange{
|
||||
@ -232,6 +240,3 @@ func (b *RoutingMatcherBuilder) Build() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (b *RoutingMatcherBuilder) AddAnyBefore(f *config_parser.Function, key string, values []string, outbound string) {
|
||||
// logrus.Debugln(f.Not, f.Name, key, outbound)
|
||||
//}
|
||||
|
@ -145,7 +145,11 @@ func (a *AliveDialerSet) SetAlive(dialer *Dialer, alive bool) {
|
||||
a.calcMinLatency()
|
||||
}
|
||||
if a.minLatency.dialer != oldBestDialer {
|
||||
a.log.Infof("Group [%v] switched dialer to <%v> (%v): %v", a.dialerGroupName, a.minLatency.dialer.Name(), a.selectionPolicy, a.minLatency.latency)
|
||||
newDialerName := "<null>"
|
||||
if a.minLatency.dialer != nil {
|
||||
newDialerName = a.minLatency.dialer.Name()
|
||||
}
|
||||
a.log.Infof("Group [%v] switched dialer to <%v> (%v): %v", a.dialerGroupName, newDialerName, a.selectionPolicy, a.minLatency.latency)
|
||||
}
|
||||
} else {
|
||||
if alive && minPolicy && a.minLatency.dialer == nil {
|
||||
|
@ -7,6 +7,7 @@ package routing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
"github.com/v2rayA/dae/pkg/config_parser"
|
||||
@ -60,6 +61,8 @@ func ParsePrefixes(values []string) (cidrs []netip.Prefix, err error) {
|
||||
|
||||
func ApplyMatcherBuilder(builder MatcherBuilder, rules []*config_parser.RoutingRule, finalOutbound string) (err error) {
|
||||
for _, rule := range rules {
|
||||
logrus.Debugln("[rule]", rule.String(true))
|
||||
|
||||
// rule is like: domain(domain:baidu.com) && port(443) -> proxy
|
||||
for iFunc, f := range rule.AndFunctions {
|
||||
// f is like: domain(domain:baidu.com)
|
||||
@ -75,6 +78,15 @@ func ApplyMatcherBuilder(builder MatcherBuilder, rules []*config_parser.RoutingR
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Debug
|
||||
symNot := ""
|
||||
if f.Not {
|
||||
symNot = "!"
|
||||
}
|
||||
logrus.Debugf("\t%v%v(%v) -> %v", symNot, f.Name, key, outbound)
|
||||
}
|
||||
|
||||
builder.AddAnyBefore(f, key, paramValueGroup, outbound)
|
||||
switch f.Name {
|
||||
case consts.Function_Domain:
|
||||
|
@ -58,9 +58,9 @@ group {
|
||||
|
||||
routing {
|
||||
#ip(geoip:private)->direct
|
||||
!port(443) -> direct
|
||||
!port(80) -> my_group
|
||||
sport(123) -> direct
|
||||
!sip(192.168.0.252/30) -> direct
|
||||
sip(192.168.0.0/24) && !sip(192.168.0.252/30) -> direct
|
||||
domain(geosite:category-ads) -> block
|
||||
l4proto(udp) && mac('02:42:ac:11:00:03') -> my_group
|
||||
domain(geosite:disney) -> disney
|
||||
|
2
go.mod
2
go.mod
@ -12,7 +12,7 @@ require (
|
||||
github.com/mzz2017/softwind v0.0.0-20230127172609-05c5264aa6a4
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230127154011-4f61520cc0b7
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230129030458-867b50f6cc67
|
||||
github.com/v2rayA/shadowsocksR v1.0.4
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
golang.org/x/net v0.5.0
|
||||
|
4
go.sum
4
go.sum
@ -76,8 +76,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230127154011-4f61520cc0b7 h1:o7BGW7hcNACMtpeXvXG9epG/2napoDGLluldZ0NE0XI=
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230127154011-4f61520cc0b7/go.mod h1:JiTWeZybOkBfCqv/fy5jbFhXTxuLlyrI76gRNazz2sU=
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230129030458-867b50f6cc67 h1:BKYTwtvnzg/QQG5uQmWNHDu07KmkrfdpZ98pAOvZf0g=
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230129030458-867b50f6cc67/go.mod h1:JiTWeZybOkBfCqv/fy5jbFhXTxuLlyrI76gRNazz2sU=
|
||||
github.com/v2rayA/shadowsocksR v1.0.4 h1:65Ltdy+I/DnlkQTJj+R+X85zhZ63ORE1Roy+agAcF/s=
|
||||
github.com/v2rayA/shadowsocksR v1.0.4/go.mod h1:CyOhDLy8/AKedsi16xRYAMmkxSCH1ukJPaacaTdRfQg=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
|
@ -74,6 +74,8 @@ group {
|
||||
}
|
||||
|
||||
routing {
|
||||
sip(192.168.0.0/24) && !sip(192.168.0.252/30) -> direct
|
||||
|
||||
domain(geosite:category-ads) -> block
|
||||
domain(geosite:disney) -> disney
|
||||
domain(geosite:netflix) -> netflix
|
||||
|
@ -135,6 +135,9 @@ type Function struct {
|
||||
|
||||
func (f *Function) String(compact bool) string {
|
||||
var builder strings.Builder
|
||||
if f.Not {
|
||||
builder.WriteString("!")
|
||||
}
|
||||
builder.WriteString(f.Name + "(")
|
||||
var strParamList []string
|
||||
for _, p := range f.Params {
|
||||
@ -181,27 +184,28 @@ type RoutingRule struct {
|
||||
func (r *RoutingRule) String(calcN bool) string {
|
||||
var builder strings.Builder
|
||||
var n int
|
||||
for _, f := range r.AndFunctions {
|
||||
if builder.Len() != 0 {
|
||||
for i, f := range r.AndFunctions {
|
||||
if i != 0 {
|
||||
builder.WriteString(" && ")
|
||||
}
|
||||
var paramBuilder strings.Builder
|
||||
n += len(f.Params)
|
||||
for _, p := range f.Params {
|
||||
if paramBuilder.Len() != 0 {
|
||||
paramBuilder.WriteString(", ")
|
||||
}
|
||||
if p.Key != "" {
|
||||
paramBuilder.WriteString(p.Key + ": " + p.Val)
|
||||
} else {
|
||||
paramBuilder.WriteString(p.Val)
|
||||
if calcN {
|
||||
paramBuilder.WriteString("[n = " + strconv.Itoa(n) + "]")
|
||||
} else {
|
||||
for j, param := range f.Params {
|
||||
if j != 0 {
|
||||
paramBuilder.WriteString(", ")
|
||||
}
|
||||
paramBuilder.WriteString(param.String(false))
|
||||
}
|
||||
}
|
||||
builder.WriteString(fmt.Sprintf("%v(%v)", f.Name, paramBuilder.String()))
|
||||
symNot := ""
|
||||
if f.Not {
|
||||
symNot = "!"
|
||||
}
|
||||
builder.WriteString(fmt.Sprintf("%v%v(%v)", symNot, f.Name, paramBuilder.String()))
|
||||
}
|
||||
builder.WriteString(" -> " + r.Outbound)
|
||||
if calcN {
|
||||
builder.WriteString(" [n = " + strconv.Itoa(n) + "]")
|
||||
}
|
||||
return builder.String()
|
||||
}
|
||||
|
@ -185,20 +185,16 @@ func (w *Walker) parseFunctionPrototypeExpression(ctx dae_config.IFunctionProtot
|
||||
func (w *Walker) parseRoutingRule(ctx dae_config.IRoutingRuleContext) *RoutingRule {
|
||||
children := ctx.GetChildren()
|
||||
//logrus.Debugln(ctx.GetText(), children)
|
||||
left, ok := children[0].(*dae_config.RoutingRuleLeftContext)
|
||||
if !ok {
|
||||
w.ReportError(ctx, ErrorType_Unsupported, "not *RoutingRuleLeftContext: "+ctx.GetText())
|
||||
return nil
|
||||
}
|
||||
outbound := children[2].(*dae_config.Bare_literalContext).GetText()
|
||||
// Parse functions.
|
||||
children = left.GetChildren()
|
||||
functionList, ok := children[1].(*dae_config.FunctionPrototypeExpressionContext)
|
||||
functionList, ok := children[0].(*dae_config.FunctionPrototypeExpressionContext)
|
||||
if !ok {
|
||||
w.ReportError(ctx, ErrorType_Unsupported, "not *FunctionPrototypeExpressionContext: "+ctx.GetText())
|
||||
return nil
|
||||
}
|
||||
// Parse functions.
|
||||
andFunctions := w.parseFunctionPrototypeExpression(functionList, nil)
|
||||
|
||||
// Parse outbound.
|
||||
outbound := children[2].(*dae_config.Bare_literalContext).GetText()
|
||||
return &RoutingRule{
|
||||
AndFunctions: andFunctions,
|
||||
Outbound: outbound,
|
||||
|
Loading…
Reference in New Issue
Block a user