diff --git a/component/control/bpf_utils.go b/component/control/bpf_utils.go index b2540ac..3b4bff1 100644 --- a/component/control/bpf_utils.go +++ b/component/control/bpf_utils.go @@ -18,6 +18,7 @@ import ( "os" "reflect" "strings" + "sync" ) type _bpfLpmKey struct { @@ -67,16 +68,22 @@ func cidrToBpfLpmKey(prefix netip.Prefix) _bpfLpmKey { } } +var ( + CheckBatchUpdateFeatureOnce sync.Once + SimulateBatchUpdate bool +) + func BatchUpdate(m *ebpf.Map, keys interface{}, values interface{}, opts *ebpf.BatchOptions) (n int, err error) { - var old bool - version, e := internal.KernelVersion() - if e != nil || version.Less(consts.UserspaceBatchUpdateFeatureVersion) { - old = true - } - if m.Type() == ebpf.LPMTrie && version.Less(consts.UserspaceBatchUpdateLpmTrieFeatureVersion) { - old = true - } - if !old { + CheckBatchUpdateFeatureOnce.Do(func() { + version, e := internal.KernelVersion() + if e != nil || version.Less(consts.UserspaceBatchUpdateFeatureVersion) { + SimulateBatchUpdate = true + } + if m.Type() == ebpf.LPMTrie && version.Less(consts.UserspaceBatchUpdateLpmTrieFeatureVersion) { + SimulateBatchUpdate = true + } + }) + if !SimulateBatchUpdate { return m.BatchUpdate(keys, values, opts) } else { vKeys := reflect.ValueOf(keys) diff --git a/component/control/control_plane.go b/component/control/control_plane.go index da0ee65..7116627 100644 --- a/component/control/control_plane.go +++ b/component/control/control_plane.go @@ -90,7 +90,7 @@ func NewControlPlane( log.Infof("Loading eBPF programs and maps into the kernel") var bpf bpfObjects var ProgramOptions ebpf.ProgramOptions - if log.IsLevelEnabled(logrus.TraceLevel) { + if log.Level == logrus.PanicLevel { ProgramOptions = ebpf.ProgramOptions{ LogLevel: ebpf.LogLevelBranch | ebpf.LogLevelStats, //LogLevel: ebpf.LogLevelInstruction | ebpf.LogLevelStats, @@ -127,11 +127,11 @@ retryLoadBpf: goto retryLoadBpf } // Get detailed log from ebpf.internal.(*VerifierError) - if log.IsLevelEnabled(logrus.TraceLevel) { + if log.Level == logrus.PanicLevel { if v := reflect.Indirect(reflect.ValueOf(errors.Unwrap(errors.Unwrap(err)))); v.Kind() == reflect.Struct { if _log := v.FieldByName("Log"); _log.IsValid() { if strSlice, ok := _log.Interface().([]string); ok { - log.Traceln(strings.Join(strSlice, "\n")) + log.Panicln(strings.Join(strSlice, "\n")) } } } diff --git a/component/control/dns.go b/component/control/dns.go index 9b10733..71d6c04 100644 --- a/component/control/dns.go +++ b/component/control/dns.go @@ -9,6 +9,8 @@ import ( "encoding/binary" "fmt" "github.com/cilium/ebpf" + "github.com/mohae/deepcopy" + "github.com/sirupsen/logrus" "github.com/v2rayA/dae/common" "github.com/v2rayA/dae/common/consts" "golang.org/x/net/dns/dnsmessage" @@ -26,7 +28,15 @@ type dnsCache struct { } func (c *dnsCache) FillInto(req *dnsmessage.Message) { - req.Answers = c.Answers + req.Answers = deepcopy.Copy(c.Answers).([]dnsmessage.Resource) + // Align question and answer Name. + if len(req.Questions) > 0 { + q := req.Questions[0] + if len(req.Answers) > 0 && + strings.EqualFold(req.Answers[0].Header.Name.String(), q.Name.String()) { + req.Answers[0].Header.Name.Data = q.Name.Data + } + } req.RCode = dnsmessage.RCodeSuccess req.Response = true req.RecursionAvailable = true @@ -137,9 +147,8 @@ func (c *ControlPlane) DnsRespHandler(data []byte) (newData []byte, err error) { return data, nil } q := msg.Questions[0] - // If first answer is CNAME type, replace the Name with flipping-backed Name. + // Align question and answer Name. if len(msg.Answers) > 0 && - msg.Answers[0].Header.Type == dnsmessage.TypeCNAME && strings.EqualFold(msg.Answers[0].Header.Name.String(), q.Name.String()) { msg.Answers[0].Header.Name.Data = q.Name.Data } @@ -174,6 +183,10 @@ func (c *ControlPlane) DnsRespHandler(data []byte) (newData []byte, err error) { } // Update dnsCache. + c.log.WithFields(logrus.Fields{ + "qname": q.Name, + "ans": msg.Answers, + }).Tracef("Update DNS record cache") c.mutex.Lock() fqdn := strings.ToLower(q.Name.String()) cacheKey := fqdn + q.Type.String() diff --git a/example.dae b/example.dae index 8abc817..81cca35 100644 --- a/example.dae +++ b/example.dae @@ -8,6 +8,7 @@ global { # Now only support UDP and IP:Port. # Please make sure DNS traffic will go through and be forwarded by dae. + # The upstream DNS answer MUST NOT be polluted. # The request to dns upstream follows routing defined below. dns_upstream: '8.8.8.8:53' @@ -62,7 +63,7 @@ group { routing { # See routing.md for full examples. - ip(8.8.8.8) && port(53) -> direct + ip(8.8.8.8, 1.1.1.1) && port(53) -> my_group pname(firefox) && domain(ip.sb) -> direct pname(curl) && domain(ip.sb) -> my_group