From 1281e1572c1fdcffd9f6b8886dd98ac015de5591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Mon, 24 Jun 2024 19:35:03 +0800 Subject: [PATCH] Avoid hijack DNS requests send to loopback --- redirect_nftables_rules.go | 97 +++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 34 deletions(-) diff --git a/redirect_nftables_rules.go b/redirect_nftables_rules.go index 8cb78e5..e6c171f 100644 --- a/redirect_nftables_rules.go +++ b/redirect_nftables_rules.go @@ -537,51 +537,80 @@ func (r *autoRedirect) nftablesCreateDNSHijackRulesForFamily( dnsServer = r.tunOptions.Inet6Address[0].Addr().Next() } } - nft.AddRule(&nftables.Rule{ - Table: table, - Chain: chain, - Exprs: []expr.Any{ - &expr.Meta{ - Key: expr.MetaKeyNFPROTO, - Register: 1, + exprs := []expr.Any{ + &expr.Meta{ + Key: expr.MetaKeyNFPROTO, + Register: 1, + }, + &expr.Cmp{ + Op: expr.CmpOpEq, + Register: 1, + Data: []byte{uint8(family)}, + }, + } + if chain.Hooknum == nftables.ChainHookOutput { + // It looks like we can't hijack DNS requests sent to loopback. + // https://serverfault.com/questions/363899/iptables-dnat-from-loopback + // and tproxy is not available in output + exprs = append(exprs, + /*&expr.Fib{ + Register: 1, + FlagDADDR: true, + ResultADDRTYPE: true, }, &expr.Cmp{ Op: expr.CmpOpEq, Register: 1, - Data: []byte{uint8(family)}, - }, + Data: []byte{unix.RTN_UNICAST}, + },*/ &expr.Meta{ - Key: expr.MetaKeyL4PROTO, + Key: expr.MetaKeyOIFNAME, Register: 1, }, - &expr.Lookup{ - SourceRegister: 1, - SetID: ipProto.ID, - SetName: ipProto.Name, - }, - &expr.Payload{ - OperationType: expr.PayloadLoad, - DestRegister: 1, - Base: expr.PayloadBaseTransportHeader, - Offset: 2, - Len: 2, - }, &expr.Cmp{ - Op: expr.CmpOpEq, - Register: 1, - Data: binaryutil.BigEndian.PutUint16(53), - }, - &expr.Counter{}, - &expr.Immediate{ + Op: expr.CmpOpNeq, Register: 1, - Data: dnsServer.AsSlice(), - }, - &expr.NAT{ - Type: expr.NATTypeDestNAT, - Family: uint32(family), - RegAddrMin: 1, + Data: nftablesIfname("lo"), }, + ) + } + exprs = append(exprs, + &expr.Meta{ + Key: expr.MetaKeyL4PROTO, + Register: 1, + }, + &expr.Lookup{ + SourceRegister: 1, + SetID: ipProto.ID, + SetName: ipProto.Name, }, + &expr.Payload{ + OperationType: expr.PayloadLoad, + DestRegister: 1, + Base: expr.PayloadBaseTransportHeader, + Offset: 2, + Len: 2, + }, + &expr.Cmp{ + Op: expr.CmpOpEq, + Register: 1, + Data: binaryutil.BigEndian.PutUint16(53), + }, + &expr.Immediate{ + Register: 1, + Data: dnsServer.AsSlice(), + }, + &expr.NAT{ + Type: expr.NATTypeDestNAT, + Family: uint32(family), + RegAddrMin: 1, + }, + &expr.Counter{}, + ) + nft.AddRule(&nftables.Rule{ + Table: table, + Chain: chain, + Exprs: exprs, }) return nil }