|
|
|
@ -7,6 +7,8 @@ package dns
|
|
|
|
|
import ( |
|
|
|
|
"context" |
|
|
|
|
"log" |
|
|
|
|
"net/url" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
|
"sync" |
|
|
|
|
"time" |
|
|
|
@ -85,22 +87,49 @@ func New(ctx context.Context, config *Config) (*Server, error) {
|
|
|
|
|
} |
|
|
|
|
server.hosts = hosts |
|
|
|
|
|
|
|
|
|
parseDOHURI := func(d string, endpoint *net.Endpoint) (host string, port uint32, err error) { |
|
|
|
|
u, err := url.Parse(d) |
|
|
|
|
if err != nil { |
|
|
|
|
return "", 0, err |
|
|
|
|
} |
|
|
|
|
host = u.Hostname() |
|
|
|
|
port = 443 |
|
|
|
|
if u.Port() != "" { |
|
|
|
|
p, err := strconv.ParseUint(u.Port(), 10, 16) |
|
|
|
|
if err != nil { |
|
|
|
|
return "", 0, err |
|
|
|
|
} |
|
|
|
|
port = uint32(p) |
|
|
|
|
} |
|
|
|
|
if endpoint.Port != 0 { |
|
|
|
|
port = endpoint.Port |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
addNameServer := func(endpoint *net.Endpoint) int { |
|
|
|
|
address := endpoint.Address.AsAddress() |
|
|
|
|
if address.Family().IsDomain() && address.Domain() == "localhost" { |
|
|
|
|
server.clients = append(server.clients, NewLocalNameServer()) |
|
|
|
|
} else if address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "DOHL_") { |
|
|
|
|
dohHost := address.Domain()[5:] |
|
|
|
|
server.clients = append(server.clients, NewDoHLocalNameServer(dohHost, endpoint.Port, server.clientIP)) |
|
|
|
|
} else if address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "DOH_") { |
|
|
|
|
// DOH_ prefix makes net.Address think it's a domain
|
|
|
|
|
dohHost := address.Domain()[4:] |
|
|
|
|
} else if address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https+local://") { |
|
|
|
|
// URI schemed string treated as domain
|
|
|
|
|
dohlHost, dohlPort, err := parseDOHURI(address.Domain(), endpoint) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Fatalln(newError("DNS config error").Base(err)) |
|
|
|
|
} |
|
|
|
|
server.clients = append(server.clients, NewDoHLocalNameServer(dohlHost, dohlPort, server.clientIP)) |
|
|
|
|
} else if address.Family().IsDomain() && |
|
|
|
|
strings.HasPrefix(address.Domain(), "https://") { |
|
|
|
|
dohHost, dohPort, err := parseDOHURI(address.Domain(), endpoint) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Fatalln(newError("DNS config error").Base(err)) |
|
|
|
|
} |
|
|
|
|
idx := len(server.clients) |
|
|
|
|
server.clients = append(server.clients, nil) |
|
|
|
|
|
|
|
|
|
// need the core dispatcher, register DOHClient at callback
|
|
|
|
|
common.Must(core.RequireFeatures(ctx, func(d routing.Dispatcher) { |
|
|
|
|
c, err := NewDoHNameServer(dohHost, endpoint.Port, d, server.clientIP) |
|
|
|
|
c, err := NewDoHNameServer(dohHost, dohPort, d, server.clientIP) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Fatalln(newError("DNS config error").Base(err)) |
|
|
|
|
} |
|
|
|
|