Skip to content

Instantly share code, notes, and snippets.

@njhsi
Created November 1, 2025 15:24
Show Gist options
  • Select an option

  • Save njhsi/82e6033e40fa71534b09fedf0bf2ea63 to your computer and use it in GitHub Desktop.

Select an option

Save njhsi/82e6033e40fa71534b09fedf0bf2ea63 to your computer and use it in GitHub Desktop.
using Dnsmasq "--add-mac" to send client ip address to AdGuard Home
diff --git a/internal/dnsforward/process.go b/internal/dnsforward/process.go
index d2d8529..535dc04 100644
--- a/internal/dnsforward/process.go
+++ b/internal/dnsforward/process.go
@@ -156,7 +156,27 @@ func (s *Server) processInitial(ctx context.Context, dctx *dnsContext) (rc resul
defer s.logger.DebugContext(ctx, "finished processing initial")
pctx := dctx.proxyCtx
- s.processClientIP(ctx, pctx.Addr.Addr())
+
+ var mac2Addr netip.Addr
+ if opt := pctx.Req.IsEdns0(); opt != nil {
+ for _, o := range opt.Option {
+ if lo,ok := o.(*dns.EDNS0_LOCAL); ok {
+ s.logger.DebugContext(ctx, "bynj/process/processInitial", lo) //Code uint16, Data []byte
+ if lo.Code==65001 && len(lo.Data)>=4 {
+ mac2Addr,_ = netip.AddrFromSlice(lo.Data[:4])
+ s.logger.DebugContext(ctx, "bynj/process/processInitial", mac2Addr)
+ }
+ }
+ }
+ }
+
+// if mac2Addr.IsValid() && netutil.IsSpecialPurpose(mac2Addr) {
+ if mac2Addr.IsValid() {
+ s.logger.DebugContext(ctx, "bynj/process/processInitial: processClientIP ", mac2Addr)
+ s.processClientIP(ctx,mac2Addr)
+ } else {
+ s.processClientIP(ctx, pctx.Addr.Addr())
+ }
q := pctx.Req.Question[0]
qt := q.Qtype
diff --git a/internal/dnsforward/stats.go b/internal/dnsforward/stats.go
index 9059045..81cfe4d 100644
--- a/internal/dnsforward/stats.go
+++ b/internal/dnsforward/stats.go
@@ -3,6 +3,7 @@ package dnsforward
import (
"context"
"net"
+ "net/netip"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
@@ -23,7 +24,28 @@ func (s *Server) processQueryLogsAndStats(ctx context.Context, dctx *dnsContext)
host := aghnet.NormalizeDomain(q.Name)
processingTime := time.Since(dctx.startTime)
- ip := pctx.Addr.Addr().AsSlice()
+ var ip []byte
+ var mac2Addr netip.Addr
+ if opt := pctx.Req.IsEdns0(); opt != nil {
+ for _, o := range opt.Option {
+ if lo,ok := o.(*dns.EDNS0_LOCAL); ok {
+ s.logger.DebugContext(ctx, "bynj/process/processInitial", lo) //Code uint16, Data []byte
+ if lo.Code==65001 && len(lo.Data)>=4 {
+ mac2Addr,_ = netip.AddrFromSlice(lo.Data[:4])
+ s.logger.DebugContext(ctx, "bynj/process/processInitial", mac2Addr)
+ }
+ }
+ }
+ }
+
+// if mac2Addr.IsValid() && netutil.IsSpecialPurpose(mac2Addr) {
+ if mac2Addr.IsValid() {
+ s.logger.DebugContext(ctx, "bynj/stats/processQueryLogsAndStats", mac2Addr)
+ ip = mac2Addr.AsSlice()
+ } else {
+ ip = pctx.Addr.Addr().AsSlice()
+ }
+
s.anonymizer.Load()(ip)
ipStr := net.IP(ip).String()
diff --git a/src/edns0.c b/src/edns0.c
index e867d54..e9fd82f 100644
--- a/src/edns0.c
+++ b/src/edns0.c
@@ -540,6 +540,29 @@ static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned
return add_pseudoheader(header, plen, (unsigned char *)limit, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, u - (u8 *)&opt, 0, 1);
}
+// use EDNS0_OPTION_MAC to send client addr for adguardhome
+static size_t add_mac_bynj(struct dns_header *header, size_t plen, unsigned char *limit,
+ union mysockaddr *l3, time_t now, int *cacheablep)
+{
+ int len = 0, replace = 0;
+ char src_addr[4];
+ if (option_bool(OPT_ADD_MAC) && l3 && l3->sa.sa_family == AF_INET)
+ {
+ len = 4;
+ memcpy(src_addr, &l3->in.sin_addr, len);
+ *cacheablep = 0;
+ if (option_bool(OPT_STRIP_MAC))
+ replace = 1;
+ }
+ else if (option_bool(OPT_STRIP_MAC))
+ replace = 2;
+
+ if (replace != 0 || len != 0)
+ plen = add_pseudoheader(header, plen, (unsigned char *)limit, EDNS0_OPTION_MAC, src_addr, len, 0, replace);
+
+ return plen;
+}
+
/* Set *check_subnet if we add a client subnet option, which needs to checked
in the reply. Set *cacheable to zero if we add an option which the answer
may depend on. */
@@ -548,7 +571,7 @@ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l
{
*cacheable = 1;
- plen = add_mac(header, plen, limit, source, now, cacheable);
+ plen = add_mac_bynj(header, plen, limit, source, now, cacheable);
plen = add_dns_client(header, plen, limit, source, now, cacheable);
if (daemon->dns_client_id)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment