github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/dns/resolver/edns.go (about)

     1  package dns
     2  
     3  import (
     4  	"bytes"
     5  	"net"
     6  )
     7  
     8  type EDNSOPT [2]byte
     9  
    10  // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-11
    11  var (
    12  	Reserved         = EDNSOPT{0b00000000, 0b00000000} //0
    13  	LLQ              = EDNSOPT{0b00000000, 0b00000001} //1 Optional
    14  	UL               = EDNSOPT{0b00000000, 0b00000010} //2 On-hold
    15  	NSID             = EDNSOPT{0b00000000, 0b00000011} //3 Standard
    16  	Reserved2        = EDNSOPT{0b00000000, 0b00000100} //4
    17  	DAU              = EDNSOPT{0b00000000, 0b00000101} //5 Standard
    18  	DHU              = EDNSOPT{0b00000000, 0b00000110} //6 Standard
    19  	N3U              = EDNSOPT{0b00000000, 0b00000111} //7 Standard
    20  	EdnsClientSubnet = EDNSOPT{0b00000000, 0b00001000} //8 Optional
    21  	EDNSEXPIRE       = EDNSOPT{0b00000000, 0b00001001} //9 Optional
    22  	COOKIE           = EDNSOPT{0b00000000, 0b00001010} //10 Standard
    23  	TcpKeepalive     = EDNSOPT{0b00000000, 0b00001011} //11 Standard
    24  	Padding          = EDNSOPT{0b00000000, 0b00001100} //12 Standard
    25  	CHAIN            = EDNSOPT{0b00000000, 0b00001101} //13 Standard
    26  	KEYTAG           = EDNSOPT{0b00000000, 0b00001110} //14 Optional
    27  	ExtendedDNSError = EDNSOPT{0b00000000, 0b00001111} //15 Standard
    28  	EDNSClientTag    = EDNSOPT{0b00000000, 0b00010000} //16 Optional
    29  	EDNSServerTag    = EDNSOPT{0b00000000, 0b00010001} //17 Optional
    30  
    31  )
    32  
    33  type eDNSHeader struct {
    34  	DnsHeader   []byte
    35  	Name        [1]byte
    36  	Type        [2]byte
    37  	PayloadSize [2]byte
    38  	ExtendRCode [1]byte
    39  	EDNSVersion [1]byte
    40  	Z           [2]byte
    41  	Data        []byte
    42  }
    43  
    44  func createEDNSRequ(header eDNSHeader) []byte {
    45  	header.DnsHeader[10] = 0b00000000
    46  	header.DnsHeader[11] = 0b00000001
    47  	length := getLength(len(header.Data))
    48  	return bytes.Join([][]byte{header.DnsHeader, header.Name[:], header.Type[:], header.PayloadSize[:], header.ExtendRCode[:], header.EDNSVersion[:], header.Z[:], length[:], header.Data}, []byte{})
    49  }
    50  
    51  // https://tools.ietf.org/html/rfc7871
    52  // https://tools.ietf.org/html/rfc2671
    53  func createEDNSReq(domain string, reqType2 reqType, eDNS []byte) []byte {
    54  	data := bytes.NewBuffer(creatRequest(domain, reqType2, true))
    55  	data.WriteByte(0b00000000)                 // name
    56  	data.Write([]byte{0b00000000, 0b00101001}) // type 41
    57  	data.Write([]byte{0b00010000, 0b00000000}) // payloadSize 4096
    58  	data.WriteByte(0b00000000)                 // extendRcode
    59  	data.WriteByte(0b00000000)                 // EDNS Version
    60  	data.Write([]byte{0b00000000, 0b00000000}) // Z
    61  	data.Write(getLength(len(eDNS)))           // data length
    62  	data.Write(eDNS)                           // data
    63  	return data.Bytes()
    64  }
    65  
    66  func createEdnsClientSubnet(ip *net.IPNet) []byte {
    67  	optionData := bytes.NewBuffer(nil)
    68  	mask, _ := ip.Mask.Size()
    69  	subnet := ip.IP.To4()
    70  	if subnet == nil { // family https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml
    71  		optionData.Write([]byte{0b00000000, 0b00000010}) // family ipv6 2
    72  		subnet = ip.IP.To16()
    73  	} else {
    74  		optionData.Write([]byte{0b00000000, 0b00000001}) // family ipv4 1
    75  	}
    76  	optionData.WriteByte(byte(mask)) // mask
    77  	optionData.WriteByte(0b00000000) // 0 In queries, it MUST be set to 0.
    78  	optionData.Write(subnet)         // subnet IP
    79  
    80  	data := bytes.NewBuffer(nil)
    81  	data.Write([]byte{EdnsClientSubnet[0], EdnsClientSubnet[1]}) // option Code
    82  	data.Write(getLength(optionData.Len()))                      // option data length
    83  	data.Write(optionData.Bytes())                               // option data
    84  	return data.Bytes()
    85  }
    86  
    87  func getLength(length int) []byte {
    88  	return []byte{byte(length >> 8), byte(length - ((length >> 8) << 8))}
    89  }
    90  
    91  func resolveAdditional(b []byte, arCount int) {
    92  	for arCount != 0 {
    93  		arCount--
    94  		//name := b[:1]
    95  		b = b[1:] // name
    96  		typeE := b[:2]
    97  		b = b[2:] // type
    98  		b = b[2:] // payLoadSize
    99  		b = b[1:] // rCode
   100  		b = b[1:] // version
   101  		b = b[2:] // Z
   102  		dataLength := int(b[0])<<8 + int(b[1])
   103  		b = b[2:]
   104  		if typeE[0] != 0 || typeE[1] != 41 {
   105  			//optData := b[:dataLength]
   106  			b = b[dataLength:] // optData
   107  			continue
   108  		}
   109  
   110  		if dataLength == 0 {
   111  			continue
   112  		}
   113  		optCode := EDNSOPT{b[0], b[1]}
   114  		b = b[2:]
   115  		optionLength := int(b[0])<<8 + int(b[1])
   116  		b = b[2:]
   117  		switch optCode {
   118  		case EdnsClientSubnet:
   119  			b = b[2:]              // family
   120  			b = b[1:]              // source Netmask
   121  			b = b[1:]              // scope Netmask
   122  			b = b[optionLength-4:] // Subnet IP
   123  		default:
   124  			b = b[optionLength:] // opt data
   125  		}
   126  	}
   127  }
   128  
   129  // protocol change https://tools.ietf.org/html/rfc3225
   130  // https://tools.ietf.org/html/rfc4034
   131  // https://tools.ietf.org/html/rfc4035
   132  // Algorithm https://tools.ietf.org/html/rfc4034#appendix-A.1
   133  func createDNSSEC(domain string, reqType2 reqType) (header eDNSHeader, b []byte) {
   134  	//eDNSHeader := createEDNSReq(domain,reqType2,[]byte{})
   135  	header = eDNSHeader{}
   136  	header.DnsHeader = creatRequest(domain, reqType2, true)
   137  	header.Name[0] = 0b0
   138  	header.Type = [2]byte{0b00000000, 0b00101001}
   139  	header.PayloadSize = [2]byte{0b00010000, 0b00000000} //4096
   140  	header.ExtendRCode = [1]byte{0b00000000}
   141  	header.EDNSVersion = [1]byte{0b00000000}
   142  	header.Z = [2]byte{0b10000000, 0b00000000} // Do bit = 1
   143  	return header, createEDNSRequ(header)
   144  }