implement DNS frontend
This commit is contained in:
parent
e3e05bebcd
commit
2411a58a09
2 changed files with 142 additions and 7 deletions
145
node/lux_dns.go
145
node/lux_dns.go
|
|
@ -3,9 +3,14 @@ package node
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"lux/host"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const LUX_DNS_TTL uint32 = 60 * 5 // 5 minutes
|
||||||
|
|
||||||
type LuxDnsServer struct {
|
type LuxDnsServer struct {
|
||||||
node *LuxNode
|
node *LuxNode
|
||||||
stopChan chan bool
|
stopChan chan bool
|
||||||
|
|
@ -30,6 +35,46 @@ type dnsEntry struct {
|
||||||
dnsClass uint16
|
dnsClass uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// host
|
||||||
|
// host.lux
|
||||||
|
// host.wan.lux
|
||||||
|
// host.re0.lux
|
||||||
|
// service1.host.re0.lux
|
||||||
|
type luxDomainInfo struct {
|
||||||
|
hostname string
|
||||||
|
netif string
|
||||||
|
tld string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *dnsEntry) ParseDomainInfo() luxDomainInfo {
|
||||||
|
switch len(entry.labels) {
|
||||||
|
case 1:
|
||||||
|
return luxDomainInfo{
|
||||||
|
hostname: entry.labels[0],
|
||||||
|
netif: "wan",
|
||||||
|
tld: "lux",
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
return luxDomainInfo{
|
||||||
|
hostname: entry.labels[0],
|
||||||
|
netif: "wan",
|
||||||
|
tld: entry.labels[1],
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
return luxDomainInfo{
|
||||||
|
hostname: entry.labels[0],
|
||||||
|
netif: entry.labels[1],
|
||||||
|
tld: entry.labels[2],
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return luxDomainInfo{
|
||||||
|
hostname: entry.labels[len(entry.labels)-3],
|
||||||
|
netif: entry.labels[len(entry.labels)-2],
|
||||||
|
tld: entry.labels[len(entry.labels)-1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (sv *LuxDnsServer) HandleRequest(req []byte) []byte {
|
func (sv *LuxDnsServer) HandleRequest(req []byte) []byte {
|
||||||
id := NO.Uint16(req[0:2])
|
id := NO.Uint16(req[0:2])
|
||||||
flags := NO.Uint16(req[2:4])
|
flags := NO.Uint16(req[2:4])
|
||||||
|
|
@ -48,9 +93,7 @@ func (sv *LuxDnsServer) HandleRequest(req []byte) []byte {
|
||||||
|
|
||||||
if qr != 0 || opcode != 0 {
|
if qr != 0 || opcode != 0 {
|
||||||
// throw not supported
|
// throw not supported
|
||||||
qr = 1
|
goto not_imp
|
||||||
rcode = 4
|
|
||||||
goto reply
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode questions
|
// decode questions
|
||||||
|
|
@ -97,21 +140,113 @@ func (sv *LuxDnsServer) HandleRequest(req []byte) []byte {
|
||||||
offset += 2
|
offset += 2
|
||||||
|
|
||||||
entries[i] = dnsEntry{
|
entries[i] = dnsEntry{
|
||||||
|
fullName: strings.Join(labels, "."),
|
||||||
labels: labels,
|
labels: labels,
|
||||||
offset: thisOff,
|
offset: thisOff,
|
||||||
dnsType: dnsType,
|
dnsType: dnsType,
|
||||||
dnsClass: dnsClass,
|
dnsClass: dnsClass,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println(entries)
|
|
||||||
goto not_imp
|
// start forming response. first, we just gonna put questions
|
||||||
|
// from request into response
|
||||||
|
fmt.Println(offset)
|
||||||
|
data = req[12:offset]
|
||||||
|
|
||||||
|
// answer questions
|
||||||
|
for _, entry := range entries {
|
||||||
|
info := entry.ParseDomainInfo()
|
||||||
|
if info.tld != "lux" {
|
||||||
|
goto refused
|
||||||
|
}
|
||||||
|
|
||||||
|
// find luxHost
|
||||||
|
luxHost, ok := sv.node.GetHostByName(info.hostname)
|
||||||
|
if !ok {
|
||||||
|
goto not_found
|
||||||
|
}
|
||||||
|
|
||||||
|
// get IP by netif
|
||||||
|
state := &luxHost.State
|
||||||
|
|
||||||
|
var addr netip.Addr
|
||||||
|
switch info.netif {
|
||||||
|
case "wan":
|
||||||
|
wan, ok := state.Options[host.LuxOptionTypeWAN]
|
||||||
|
if !ok {
|
||||||
|
// no WAN info
|
||||||
|
goto not_found
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = wan.(*host.LuxOptionWAN).Addr4
|
||||||
|
default:
|
||||||
|
// look for netif
|
||||||
|
opt, ok := state.Options[host.LuxOptionTypeNetIf]
|
||||||
|
if !ok {
|
||||||
|
goto not_found
|
||||||
|
}
|
||||||
|
|
||||||
|
netif, ok := opt.(*host.LuxOptionNetIf).Interfaces[info.netif]
|
||||||
|
if !ok {
|
||||||
|
goto not_found
|
||||||
|
}
|
||||||
|
|
||||||
|
ipFound := false
|
||||||
|
for _, netAddr := range netif.Addrs {
|
||||||
|
if netAddr.Type == host.LuxNetAddrType4 {
|
||||||
|
addr = netAddr.Addr
|
||||||
|
ipFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ipFound {
|
||||||
|
goto not_found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write IP to response
|
||||||
|
answer := make([]byte, 12)
|
||||||
|
NO.PutUint16(answer[0:2], uint16(entry.offset)|0xC000) // name
|
||||||
|
NO.PutUint16(answer[2:4], entry.dnsType) // type
|
||||||
|
NO.PutUint16(answer[4:6], entry.dnsClass) // class
|
||||||
|
NO.PutUint32(answer[6:10], LUX_DNS_TTL) // DNS TTL
|
||||||
|
|
||||||
|
if addr.Is6() {
|
||||||
|
NO.PutUint16(answer[10:12], 16) // Data Length - IPv6
|
||||||
|
|
||||||
|
octets := addr.As16()
|
||||||
|
answer = append(answer, octets[:]...)
|
||||||
|
} else {
|
||||||
|
NO.PutUint16(answer[10:12], 4) // Data Length - IPv4
|
||||||
|
|
||||||
|
octets := addr.As4()
|
||||||
|
answer = append(answer, octets[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
data = append(data, answer...)
|
||||||
|
ancount++
|
||||||
|
}
|
||||||
|
|
||||||
|
rcode = 0
|
||||||
|
nscount = 0
|
||||||
|
arcount = 0
|
||||||
|
|
||||||
|
flags |= (1 << 10) // Authoritative Answer
|
||||||
|
goto reply
|
||||||
|
|
||||||
decode_error:
|
decode_error:
|
||||||
rcode = 2
|
rcode = 2
|
||||||
goto reply
|
goto reply
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
rcode = 3
|
||||||
|
goto reply
|
||||||
|
|
||||||
not_imp:
|
not_imp:
|
||||||
rcode = 4
|
rcode = 4
|
||||||
|
goto reply
|
||||||
|
|
||||||
|
refused:
|
||||||
|
rcode = 5
|
||||||
|
|
||||||
reply:
|
reply:
|
||||||
qr = 1
|
qr = 1
|
||||||
|
|
|
||||||
|
|
@ -101,8 +101,8 @@ func (node *LuxNode) GetStateLock() *sync.RWMutex {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *LuxNode) GetHostByName(name string) (LuxHostState, bool) {
|
func (node *LuxNode) GetHostByName(name string) (LuxHostState, bool) {
|
||||||
node.stateLock.RLock()
|
// node.stateLock.RLock()
|
||||||
defer node.stateLock.RUnlock()
|
// defer node.stateLock.RUnlock()
|
||||||
|
|
||||||
for _, host := range node.state.hosts {
|
for _, host := range node.state.hosts {
|
||||||
if host.State.Hostname == name {
|
if host.State.Hostname == name {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue