diff --git a/README.md b/README.md index 3db490f..29e3219 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,10 @@ make Run: ```shell -./dae run -c example.conf +./dae run -c example.dae ``` -See [example.conf](https://github.com/v2rayA/dae/blob/main/example.conf). +See [example.dae](https://github.com/v2rayA/dae/blob/main/example.dae). ## TODO diff --git a/cmd/run.go b/cmd/run.go index a61ef32..4a7f836 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -29,7 +29,7 @@ var ( ) func init() { - runCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "dae.conf", "config file") + runCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "config.dae", "config file") } func Run() (err error) { diff --git a/common/consts/ebpf.go b/common/consts/ebpf.go index 744aea0..395fd18 100644 --- a/common/consts/ebpf.go +++ b/common/consts/ebpf.go @@ -29,7 +29,7 @@ const ( DisableL4ChecksumPolicy_SetZero ) -type RoutingType uint32 +type RoutingType uint8 const ( RoutingType_DomainSet RoutingType = iota diff --git a/component/control/control_plane.go b/component/control/control_plane.go index d4230f8..47be8ff 100644 --- a/component/control/control_plane.go +++ b/component/control/control_plane.go @@ -11,6 +11,7 @@ import ( "fmt" "github.com/cilium/ebpf" "github.com/cilium/ebpf/rlimit" + "github.com/mzz2017/softwind/pool" "github.com/sirupsen/logrus" "github.com/v2rayA/dae/common" "github.com/v2rayA/dae/common/consts" @@ -19,7 +20,6 @@ import ( "github.com/v2rayA/dae/component/routing" "github.com/v2rayA/dae/config" "github.com/v2rayA/dae/pkg/config_parser" - "github.com/v2rayA/dae/pkg/pool" "github.com/vishvananda/netlink" "golang.org/x/sys/unix" "net" diff --git a/component/control/kern/tproxy.c b/component/control/kern/tproxy.c index c5e67dd..afba67a 100644 --- a/component/control/kern/tproxy.c +++ b/component/control/kern/tproxy.c @@ -33,10 +33,10 @@ #define MAX_PARAM_LEN 16 #define MAX_INTERFACE_NUM 128 -#define MAX_ROUTING_LEN (32 * 3) +#define MAX_MATCH_SET_LEN (32 * 3) #define MAX_LPM_SIZE 20480 //#define MAX_LPM_SIZE 20480 -#define MAX_LPM_NUM (MAX_ROUTING_LEN + 8) +#define MAX_LPM_NUM (MAX_MATCH_SET_LEN + 8) #define MAX_DEST_MAPPING_NUM (65536 * 2) #define IPV6_MAX_EXTENSIONS 4 @@ -48,9 +48,9 @@ #define OUTBOUND_LOGICAL_MASK 0xFE enum { - DISABLE_L4_CHECKSUM_POLICY_ENABLE_L4_CHECKSUM, - DISABLE_L4_CHECKSUM_POLICY_RESTORE, - DISABLE_L4_CHECKSUM_POLICY_SET_ZERO, + DisableL4ChecksumPolicy_EnableL4Checksum, + DisableL4ChecksumPolicy_Restore, + DisableL4ChecksumPolicy_SetZero, }; // Param keys: @@ -182,28 +182,27 @@ struct { __array(values, struct map_lpm_type); } lpm_array_map SEC(".maps"); -// Array of routing: -enum ROUTING_TYPE { +enum __attribute__((packed)) MatchType { /// WARNING: MUST SYNC WITH common/consts/ebpf.go. - ROUTING_TYPE_DOMAIN_SET, - ROUTING_TYPE_IP_SET, - ROUTING_TYPE_SOURCE_IP_SET, - ROUTING_TYPE_PORT, - ROUTING_TYPE_SOURCE_PORT, - ROUTING_TYPE_L4PROTO, - ROUTING_TYPE_IPVERSION, - ROUTING_TYPE_MAC, - ROUTING_TYPE_FINAL, + MatchType_DomainSet, + MatchType_IpSet, + MatchType_SourceIpSet, + MatchType_Port, + MatchType_SourcePort, + MatchType_L4Proto, + MatchType_IpVersion, + MatchType_Mac, + MatchType_Final, }; -enum L4PROTO_TYPE { - L4PROTO_TYPE_TCP = 1, - L4PROTO_TYPE_UDP = 2, - L4PROTO_TYPE_TCP_UDP = 3, +enum L4ProtoType { + L4ProtoType_TCP = 1, + L4ProtoType_UDP = 2, + L4ProtoType_X = 3, }; -enum IP_VERSION { - IPVERSION_4 = 1, - IPVERSION_6 = 2, - IPVERSION_X = 3, +enum IpVersion { + IpVersion_4 = 1, + IpVersion_6 = 2, + IpVersion_X = 3, }; struct port_range { __u16 port_start; @@ -211,7 +210,7 @@ struct port_range { }; /* - Look at following rule: + Rule is like as following: domain(geosite:cn, suffix: google.com) && l4proto(tcp) -> my_group @@ -225,10 +224,10 @@ struct match_set { __u32 index; struct port_range port_range; - enum L4PROTO_TYPE l4proto_type; - enum IP_VERSION ip_version; + enum L4ProtoType l4proto_type; + enum IpVersion ip_version; }; - enum ROUTING_TYPE type; + enum MatchType type; bool not ; // A subrule flag (this is not a match_set flag). __u8 outbound; // User-defined value range is [0, 252]. }; @@ -236,12 +235,12 @@ struct { __uint(type, BPF_MAP_TYPE_ARRAY); __type(key, __u32); __type(value, struct match_set); - __uint(max_entries, MAX_ROUTING_LEN); + __uint(max_entries, MAX_MATCH_SET_LEN); // __uint(pinning, LIBBPF_PIN_BY_NAME); } routing_map SEC(".maps"); struct domain_routing { - __u32 bitmap[MAX_ROUTING_LEN / 32]; + __u32 bitmap[MAX_MATCH_SET_LEN / 32]; }; struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); @@ -773,13 +772,13 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4], #define _ipversion flag[1] #define _hash flag[2] /// TODO: BPF_MAP_UPDATE_BATCH ? - __u32 key = ROUTING_TYPE_L4PROTO; + __u32 key = MatchType_L4Proto; int ret; if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_l4proto, BPF_ANY))) { return ret; }; - key = ROUTING_TYPE_IPVERSION; + key = MatchType_IpVersion; if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_ipversion, BPF_ANY))) { return ret; @@ -788,24 +787,24 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4], // Define variables for further use. __u16 h_dport; __u16 h_sport; - if (_l4proto == L4PROTO_TYPE_TCP) { + if (_l4proto == L4ProtoType_TCP) { h_dport = bpf_ntohs(((struct tcphdr *)l4_hdr)->dest); h_sport = bpf_ntohs(((struct tcphdr *)l4_hdr)->source); } else { h_dport = bpf_ntohs(((struct udphdr *)l4_hdr)->dest); h_sport = bpf_ntohs(((struct udphdr *)l4_hdr)->source); } - key = ROUTING_TYPE_SOURCE_PORT; + key = MatchType_SourcePort; if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_sport, BPF_ANY))) { return ret; }; - key = ROUTING_TYPE_PORT; + key = MatchType_Port; 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) { + if (h_dport == 53 && _l4proto == L4ProtoType_UDP) { struct ip_port *upstream = bpf_map_lookup_elem(&dns_upstream_map, &zero_key); if (!upstream) { @@ -822,17 +821,17 @@ static int 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 = ROUTING_TYPE_IP_SET; + key = MatchType_IpSet; if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_daddr, BPF_ANY))) { return ret; }; - key = ROUTING_TYPE_SOURCE_IP_SET; + key = MatchType_SourceIpSet; if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_saddr, BPF_ANY))) { return ret; }; - key = ROUTING_TYPE_MAC; + key = MatchType_Mac; if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_mac, BPF_ANY))) { return ret; }; @@ -849,7 +848,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4], __u16 *p_u16; #pragma unroll - for (__u32 i = 0; i < MAX_ROUTING_LEN; i++) { + for (__u32 i = 0; i < MAX_MATCH_SET_LEN; i++) { __u32 k = i; // Clone to pass code checker. match_set = bpf_map_lookup_elem(&routing_map, &k); if (!match_set) { @@ -896,7 +895,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4], if (*p_u32 & match_set->__value) { good_subrule = true; } - } else if (match_set->type == ROUTING_TYPE_DOMAIN_SET) { + } else if (match_set->type == MatchType_DomainSet) { // bpf_printk("CHECK: domain, match_set->type: %u, not: %d, " // "outbound: %u", // match_set->type, match_set->not, match_set->outbound); @@ -914,7 +913,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4], if ((domain_routing->bitmap[i / 32] >> (i % 32)) & 1) { good_subrule = true; } - } else if (match_set->type == ROUTING_TYPE_FINAL) { + } else if (match_set->type == MatchType_Final) { // bpf_printk("CHECK: hit final"); good_subrule = true; } else { @@ -947,7 +946,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4], // 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) { + _l4proto == L4ProtoType_UDP) { // DNS packet should go through control plane. return OUTBOUND_CONTROL_PLANE_DIRECT; } @@ -1044,11 +1043,11 @@ int tproxy_ingress(struct __sk_buff *skb) { if (unlikely(tcp_state_syn)) { // New TCP connection. // bpf_printk("[%X]New Connection", bpf_ntohl(tcph->seq)); - __u32 flag[3] = {L4PROTO_TYPE_TCP}; // TCP + __u32 flag[3] = {L4ProtoType_TCP}; // TCP if (ipv6h) { - flag[1] = IPVERSION_6; + flag[1] = IpVersion_6; } else { - flag[1] = IPVERSION_4; + flag[1] = IpVersion_4; } flag[2] = skb->hash; __be32 mac[4] = { @@ -1117,11 +1116,11 @@ int tproxy_ingress(struct __sk_buff *skb) { new_hdr.port = udph->dest; // Routing. It decides if we redirect traffic to control plane. - __u32 flag[3] = {L4PROTO_TYPE_UDP}; + __u32 flag[3] = {L4ProtoType_UDP}; if (ipv6h) { - flag[1] = IPVERSION_6; + flag[1] = IpVersion_6; } else { - flag[1] = IPVERSION_4; + flag[1] = IpVersion_4; } flag[2] = skb->hash; __be32 mac[4] = { @@ -1183,7 +1182,7 @@ int tproxy_ingress(struct __sk_buff *skb) { if (*disable_l4_checksum) { __u32 l4_cksm_off = l4_checksum_off(l4_proto, ihl); // Restore the checksum or set it zero. - if (*disable_l4_checksum == DISABLE_L4_CHECKSUM_POLICY_SET_ZERO) { + if (*disable_l4_checksum == DisableL4ChecksumPolicy_SetZero) { bak_cksm = 0; } bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0); @@ -1351,7 +1350,7 @@ int tproxy_egress(struct __sk_buff *skb) { if (*disable_l4_checksum) { __u32 l4_cksm_off = l4_checksum_off(l4_proto, ihl); // Restore the checksum or set it zero. - if (*disable_l4_checksum == DISABLE_L4_CHECKSUM_POLICY_SET_ZERO) { + if (*disable_l4_checksum == DisableL4ChecksumPolicy_SetZero) { bak_cksm = 0; } bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0); diff --git a/component/control/routing_matcher_builder.go b/component/control/routing_matcher_builder.go index d622d0c..6483e21 100644 --- a/component/control/routing_matcher_builder.go +++ b/component/control/routing_matcher_builder.go @@ -74,7 +74,7 @@ func (b *RoutingMatcherBuilder) AddDomain(f *config_parser.Function, key string, Domains: values, }) b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_DomainSet), + Type: uint8(consts.RoutingType_DomainSet), Not: f.Not, Outbound: b.OutboundToId(outbound), }) @@ -94,7 +94,7 @@ func (b *RoutingMatcherBuilder) AddSourceMac(f *config_parser.Function, macAddrs lpmTrieIndex := len(b.SimulatedLpmTries) b.SimulatedLpmTries = append(b.SimulatedLpmTries, values) b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_Mac), + Type: uint8(consts.RoutingType_Mac), Value: uint32(lpmTrieIndex), Not: f.Not, Outbound: b.OutboundToId(outbound), @@ -109,7 +109,7 @@ func (b *RoutingMatcherBuilder) AddIp(f *config_parser.Function, values []netip. lpmTrieIndex := len(b.SimulatedLpmTries) b.SimulatedLpmTries = append(b.SimulatedLpmTries, values) b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_IpSet), + Type: uint8(consts.RoutingType_IpSet), Value: uint32(lpmTrieIndex), Not: f.Not, Outbound: b.OutboundToId(outbound), @@ -123,7 +123,7 @@ func (b *RoutingMatcherBuilder) AddPort(f *config_parser.Function, values [][2]u outbound = _outbound } b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_Port), + Type: uint8(consts.RoutingType_Port), Value: _bpfPortRange{ PortStart: value[0], PortEnd: value[1], @@ -141,7 +141,7 @@ func (b *RoutingMatcherBuilder) AddSourceIp(f *config_parser.Function, values [] lpmTrieIndex := len(b.SimulatedLpmTries) b.SimulatedLpmTries = append(b.SimulatedLpmTries, values) b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_SourceIpSet), + Type: uint8(consts.RoutingType_SourceIpSet), Value: uint32(lpmTrieIndex), Not: f.Not, Outbound: b.OutboundToId(outbound), @@ -155,7 +155,7 @@ func (b *RoutingMatcherBuilder) AddSourcePort(f *config_parser.Function, values outbound = _outbound } b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_SourcePort), + Type: uint8(consts.RoutingType_SourcePort), Value: _bpfPortRange{ PortStart: value[0], PortEnd: value[1], @@ -171,7 +171,7 @@ func (b *RoutingMatcherBuilder) AddL4Proto(f *config_parser.Function, values con return } b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_L4Proto), + Type: uint8(consts.RoutingType_L4Proto), Value: uint32(values), Not: f.Not, Outbound: b.OutboundToId(outbound), @@ -183,7 +183,7 @@ func (b *RoutingMatcherBuilder) AddIpVersion(f *config_parser.Function, values c return } b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_IpVersion), + Type: uint8(consts.RoutingType_IpVersion), Value: uint32(values), Not: f.Not, Outbound: b.OutboundToId(outbound), @@ -196,7 +196,7 @@ func (b *RoutingMatcherBuilder) AddFinal(outbound string) { } b.Final = outbound b.rules = append(b.rules, bpfMatchSet{ - Type: uint32(consts.RoutingType_Final), + Type: uint8(consts.RoutingType_Final), Outbound: b.OutboundToId(outbound), }) } @@ -226,7 +226,7 @@ func (b *RoutingMatcherBuilder) Build() (err error) { } // Write routings. // Final rule MUST be the last. - if b.rules[len(b.rules)-1].Type != uint32(consts.RoutingType_Final) { + if b.rules[len(b.rules)-1].Type != uint8(consts.RoutingType_Final) { b.err = fmt.Errorf("final rule MUST be the last") return b.err } @@ -239,4 +239,3 @@ func (b *RoutingMatcherBuilder) Build() (err error) { } return nil } - diff --git a/component/control/udp.go b/component/control/udp.go index 589c663..490cad7 100644 --- a/component/control/udp.go +++ b/component/control/udp.go @@ -8,8 +8,8 @@ package control import ( "encoding/binary" "fmt" + "github.com/mzz2017/softwind/pool" "github.com/v2rayA/dae/common/consts" - "github.com/v2rayA/dae/pkg/pool" "golang.org/x/net/dns/dnsmessage" "net" "net/netip" diff --git a/component/control/udp_endpoint.go b/component/control/udp_endpoint.go index 55b756e..347fb2e 100644 --- a/component/control/udp_endpoint.go +++ b/component/control/udp_endpoint.go @@ -7,7 +7,7 @@ package control import ( "fmt" - "github.com/v2rayA/dae/pkg/pool" + "github.com/mzz2017/softwind/pool" "golang.org/x/net/proxy" "net" "net/netip" diff --git a/example.conf b/example.dae similarity index 100% rename from example.conf rename to example.dae diff --git a/pkg/pool/pool.go b/pkg/pool/pool.go deleted file mode 100644 index 3cb0091..0000000 --- a/pkg/pool/pool.go +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SPDX-License-Identifier: AGPL-3.0-only - * Copyright (c) since 2022, v2rayA Organization - */ - -// modified from https://github.com/nadoo/glider/blob/master/pool/buffer.go - -package pool - -import ( - "math/bits" - "sync" -) - -const ( - // number of pools. - num = 17 - maxsize = 1 << (num - 1) -) - -var ( - sizes [num]int - pools [num]sync.Pool -) - -func init() { - for i := 0; i < num; i++ { - size := 1 << i - sizes[i] = size - pools[i].New = func() interface{} { - return make([]byte, size) - } - } -} - -func GetClosestN(need int) (n int) { - // if need is exactly 2^n, return n-1 - if need&(need-1) == 0 { - return bits.Len32(uint32(need)) - 1 - } - // or return its closest n - return bits.Len32(uint32(need)) -} - -// Get gets a buffer from pool, size should in range: [1, 65536], -// otherwise, this function will call make([]byte, size) directly. -func Get(size int) []byte { - if size >= 1 && size <= maxsize { - i := GetClosestN(size) - return pools[i].Get().([]byte)[:size] - } - return make([]byte, size) -} - -// GetZero returns buffer and set all the values to 0 -func GetZero(size int) []byte { - b := Get(size) - for i := range b { - b[i] = 0 - } - return b -} - -// Put puts a buffer into pool. -func Put(buf []byte) { - if size := cap(buf); size >= 1 && size <= maxsize { - i := GetClosestN(size) - if i < num { - pools[i].Put(buf) - } - } -}