+ dns: respond to PTR requests for internal IP addresses from DHCP

Close #1682

Squashed commit of the following:

commit 2fad3544bf8853b1f8f19ad8b7bc8a490c96e533
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Mon Jun 22 17:32:45 2020 +0300

    minor

commit 7c17992424702d95e6de91f30e8ae2dfcd8de257
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Mon Jun 22 16:09:34 2020 +0300

    build

commit 16a52e11a015a97d3cbf30362482a4abd052192b
Merge: 7b6a73c8 2c47053c
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Mon Jun 22 16:08:32 2020 +0300

    Merge remote-tracking branch 'origin/master' into 1682-dhcp-resolve

commit 7b6a73c84b5cb9a073a9dfb7d7bdecd22e1e1318
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Mon Jun 22 16:01:34 2020 +0300

    tests

commit c2654abb2e5e7b7e3a04e4ddb8e1064b37613929
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Mon Jun 1 15:15:13 2020 +0300

    + dnsforward: respond to PTR requests for internal IP addresses

    {[IP] => "host"} <- DNSforward <-(leases)-- DHCP
This commit is contained in:
Simon Zolin
2020-06-23 12:13:13 +03:00
parent 2c47053cfe
commit 49a92605b8
9 changed files with 236 additions and 89 deletions

View File

@@ -296,70 +296,6 @@ func (a *AutoHosts) Process(host string, qtype uint16) []net.IP {
return ipsCopy
}
// convert character to hex number
func charToHex(n byte) int8 {
if n >= '0' && n <= '9' {
return int8(n) - '0'
} else if (n|0x20) >= 'a' && (n|0x20) <= 'f' {
return (int8(n) | 0x20) - 'a' + 10
}
return -1
}
// parse IPv6 reverse address
func ipParseArpa6(s string) net.IP {
if len(s) != 63 {
return nil
}
ip6 := make(net.IP, 16)
for i := 0; i != 64; i += 4 {
// parse "0.1."
n := charToHex(s[i])
n2 := charToHex(s[i+2])
if s[i+1] != '.' || (i != 60 && s[i+3] != '.') ||
n < 0 || n2 < 0 {
return nil
}
ip6[16-i/4-1] = byte(n2<<4) | byte(n&0x0f)
}
return ip6
}
// ipReverse - reverse IP address: 1.0.0.127 -> 127.0.0.1
func ipReverse(ip net.IP) net.IP {
n := len(ip)
r := make(net.IP, n)
for i := 0; i != n; i++ {
r[i] = ip[n-i-1]
}
return r
}
// Convert reversed ARPA address to a normal IP address
func dnsUnreverseAddr(s string) net.IP {
const arpaV4 = ".in-addr.arpa"
const arpaV6 = ".ip6.arpa"
if strings.HasSuffix(s, arpaV4) {
ip := strings.TrimSuffix(s, arpaV4)
ip4 := net.ParseIP(ip).To4()
if ip4 == nil {
return nil
}
return ipReverse(ip4)
} else if strings.HasSuffix(s, arpaV6) {
ip := strings.TrimSuffix(s, arpaV6)
return ipParseArpa6(ip)
}
return nil // unknown suffix
}
// ProcessReverse - process PTR request
// Return "" if not found or an error occurred
func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) string {
@@ -367,7 +303,7 @@ func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) string {
return ""
}
ipReal := dnsUnreverseAddr(addr)
ipReal := DNSUnreverseAddr(addr)
if ipReal == nil {
return "" // invalid IP in question
}

View File

@@ -104,11 +104,13 @@ func TestAutoHostsFSNotify(t *testing.T) {
}
func TestIP(t *testing.T) {
assert.True(t, dnsUnreverseAddr("1.0.0.127.in-addr.arpa").Equal(net.ParseIP("127.0.0.1").To4()))
assert.True(t, dnsUnreverseAddr("4.3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa").Equal(net.ParseIP("::abcd:1234")))
assert.Equal(t, "127.0.0.1", DNSUnreverseAddr("1.0.0.127.in-addr.arpa").String())
assert.Equal(t, "::abcd:1234", DNSUnreverseAddr("4.3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa").String())
assert.Equal(t, "::abcd:1234", DNSUnreverseAddr("4.3.2.1.d.c.B.A.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa").String())
assert.True(t, dnsUnreverseAddr("1.0.0.127.in-addr.arpa.") == nil)
assert.True(t, dnsUnreverseAddr(".0.0.127.in-addr.arpa") == nil)
assert.True(t, dnsUnreverseAddr(".3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") == nil)
assert.True(t, dnsUnreverseAddr("4.3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0..ip6.arpa") == nil)
assert.Nil(t, DNSUnreverseAddr("1.0.0.127.in-addr.arpa."))
assert.Nil(t, DNSUnreverseAddr(".0.0.127.in-addr.arpa"))
assert.Nil(t, DNSUnreverseAddr(".3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa"))
assert.Nil(t, DNSUnreverseAddr("4.3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0..ip6.arpa"))
assert.Nil(t, DNSUnreverseAddr("4.3.2.1.d.c.b. .0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa"))
}

70
util/dns.go Normal file
View File

@@ -0,0 +1,70 @@
package util
import (
"net"
"strings"
)
// convert character to hex number
func charToHex(n byte) int8 {
if n >= '0' && n <= '9' {
return int8(n) - '0'
} else if (n|0x20) >= 'a' && (n|0x20) <= 'f' {
return (int8(n) | 0x20) - 'a' + 10
}
return -1
}
// parse IPv6 reverse address
func ipParseArpa6(s string) net.IP {
if len(s) != 63 {
return nil
}
ip6 := make(net.IP, 16)
for i := 0; i != 64; i += 4 {
// parse "0.1."
n := charToHex(s[i])
n2 := charToHex(s[i+2])
if s[i+1] != '.' || (i != 60 && s[i+3] != '.') ||
n < 0 || n2 < 0 {
return nil
}
ip6[16-i/4-1] = byte(n2<<4) | byte(n&0x0f)
}
return ip6
}
// ipReverse - reverse IP address: 1.0.0.127 -> 127.0.0.1
func ipReverse(ip net.IP) net.IP {
n := len(ip)
r := make(net.IP, n)
for i := 0; i != n; i++ {
r[i] = ip[n-i-1]
}
return r
}
// DNSUnreverseAddr - convert reversed ARPA address to a normal IP address
func DNSUnreverseAddr(s string) net.IP {
const arpaV4 = ".in-addr.arpa"
const arpaV6 = ".ip6.arpa"
if strings.HasSuffix(s, arpaV4) {
ip := strings.TrimSuffix(s, arpaV4)
ip4 := net.ParseIP(ip).To4()
if ip4 == nil {
return nil
}
return ipReverse(ip4)
} else if strings.HasSuffix(s, arpaV6) {
ip := strings.TrimSuffix(s, arpaV6)
return ipParseArpa6(ip)
}
return nil // unknown suffix
}