Merge: + dnsforward: add dnssec_enabled option
Close #66 * commit '79bfa6a72b6cda8c0f5211a3a6df0293c4b6c7d1': + client: handle DNSSEC setting + dnsforward: add dnssec_enabled option
This commit is contained in:
commit
72c20acb86
|
@ -888,6 +888,7 @@ Response:
|
||||||
"blocking_ipv4": "1.2.3.4",
|
"blocking_ipv4": "1.2.3.4",
|
||||||
"blocking_ipv6": "1:2:3::4",
|
"blocking_ipv6": "1:2:3::4",
|
||||||
"edns_cs_enabled": true | false,
|
"edns_cs_enabled": true | false,
|
||||||
|
"dnssec_enabled": true | false
|
||||||
"disable_ipv6": true | false,
|
"disable_ipv6": true | false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,6 +906,7 @@ Request:
|
||||||
"blocking_ipv4": "1.2.3.4",
|
"blocking_ipv4": "1.2.3.4",
|
||||||
"blocking_ipv6": "1:2:3::4",
|
"blocking_ipv6": "1:2:3::4",
|
||||||
"edns_cs_enabled": true | false,
|
"edns_cs_enabled": true | false,
|
||||||
|
"dnssec_enabled": true | false
|
||||||
"disable_ipv6": true | false,
|
"disable_ipv6": true | false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1254,6 +1256,7 @@ Response:
|
||||||
}
|
}
|
||||||
...
|
...
|
||||||
],
|
],
|
||||||
|
"answer_dnssec": true,
|
||||||
"client":"127.0.0.1",
|
"client":"127.0.0.1",
|
||||||
"elapsedMs":"0.098403",
|
"elapsedMs":"0.098403",
|
||||||
"filterId":1,
|
"filterId":1,
|
||||||
|
|
|
@ -479,5 +479,7 @@
|
||||||
"install_static_configure": "We have detected that a dynamic IP address is used — <0>{{ip}}</0>. Do you want to use it as your static address?",
|
"install_static_configure": "We have detected that a dynamic IP address is used — <0>{{ip}}</0>. Do you want to use it as your static address?",
|
||||||
"confirm_static_ip": "AdGuard Home will configure {{ip}} to be your static IP address. Do you want to proceed?",
|
"confirm_static_ip": "AdGuard Home will configure {{ip}} to be your static IP address. Do you want to proceed?",
|
||||||
"list_updated": "{{count}} list updated",
|
"list_updated": "{{count}} list updated",
|
||||||
"list_updated_plural": "{{count}} lists updated"
|
"list_updated_plural": "{{count}} lists updated",
|
||||||
|
"dnssec_enable": "Enable DNSSEC",
|
||||||
|
"dnssec_enable_desc": "Set DNSSEC flag in the outcoming DNS queries and check the result (DNSSEC-enabled resolver is required)"
|
||||||
}
|
}
|
|
@ -65,6 +65,18 @@ let Form = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form__group form__group--settings">
|
||||||
|
<Field
|
||||||
|
name="dnssec_enabled"
|
||||||
|
type="checkbox"
|
||||||
|
component={renderSelectField}
|
||||||
|
placeholder={t('dnssec_enable')}
|
||||||
|
disabled={processing}
|
||||||
|
subtitle={t('dnssec_enable_desc')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="form__group form__group--settings">
|
<div className="form__group form__group--settings">
|
||||||
<Field
|
<Field
|
||||||
|
|
|
@ -16,6 +16,7 @@ const Config = ({ t, dnsConfig, setDnsConfig }) => {
|
||||||
blocking_ipv4,
|
blocking_ipv4,
|
||||||
blocking_ipv6,
|
blocking_ipv6,
|
||||||
edns_cs_enabled,
|
edns_cs_enabled,
|
||||||
|
dnssec_enabled,
|
||||||
disable_ipv6,
|
disable_ipv6,
|
||||||
processingSetConfig,
|
processingSetConfig,
|
||||||
} = dnsConfig;
|
} = dnsConfig;
|
||||||
|
@ -35,6 +36,7 @@ const Config = ({ t, dnsConfig, setDnsConfig }) => {
|
||||||
blocking_ipv6,
|
blocking_ipv6,
|
||||||
edns_cs_enabled,
|
edns_cs_enabled,
|
||||||
disable_ipv6,
|
disable_ipv6,
|
||||||
|
dnssec_enabled,
|
||||||
}}
|
}}
|
||||||
onSubmit={handleFormSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
processing={processingSetConfig}
|
processing={processingSetConfig}
|
||||||
|
|
|
@ -45,6 +45,7 @@ const dnsConfig = handleActions(
|
||||||
blocking_ipv6: DEFAULT_BLOCKING_IPV6,
|
blocking_ipv6: DEFAULT_BLOCKING_IPV6,
|
||||||
edns_cs_enabled: false,
|
edns_cs_enabled: false,
|
||||||
disable_ipv6: false,
|
disable_ipv6: false,
|
||||||
|
dnssec_enabled: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,8 @@ type FilteringConfig struct {
|
||||||
|
|
||||||
EnableEDNSClientSubnet bool `yaml:"edns_client_subnet"` // Enable EDNS Client Subnet option
|
EnableEDNSClientSubnet bool `yaml:"edns_client_subnet"` // Enable EDNS Client Subnet option
|
||||||
|
|
||||||
|
EnableDNSSEC bool `yaml:"enable_dnssec"` // Set DNSSEC flag in outcoming DNS request
|
||||||
|
|
||||||
// Respond with an empty answer to all AAAA requests
|
// Respond with an empty answer to all AAAA requests
|
||||||
AAAADisabled bool `yaml:"aaaa_disabled"`
|
AAAADisabled bool `yaml:"aaaa_disabled"`
|
||||||
|
|
||||||
|
@ -512,6 +514,7 @@ type dnsContext struct {
|
||||||
err error // error returned from the module
|
err error // error returned from the module
|
||||||
protectionEnabled bool // filtering is enabled, dnsfilter object is ready
|
protectionEnabled bool // filtering is enabled, dnsfilter object is ready
|
||||||
responseFromUpstream bool // response is received from upstream servers
|
responseFromUpstream bool // response is received from upstream servers
|
||||||
|
origReqDNSSEC bool // DNSSEC flag in the original request from user
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -588,6 +591,18 @@ func processUpstream(ctx *dnsContext) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.conf.EnableDNSSEC {
|
||||||
|
opt := d.Req.IsEdns0()
|
||||||
|
if opt == nil {
|
||||||
|
log.Debug("DNS: Adding OPT record with DNSSEC flag")
|
||||||
|
d.Req.SetEdns0(4096, true)
|
||||||
|
} else if !opt.Do() {
|
||||||
|
opt.SetDo(true)
|
||||||
|
} else {
|
||||||
|
ctx.origReqDNSSEC = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// request was not filtered so let it be processed further
|
// request was not filtered so let it be processed further
|
||||||
err := s.dnsProxy.Resolve(d)
|
err := s.dnsProxy.Resolve(d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -599,6 +614,50 @@ func processUpstream(ctx *dnsContext) int {
|
||||||
return resultDone
|
return resultDone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process DNSSEC after response from upstream server
|
||||||
|
func processDNSSECAfterResponse(ctx *dnsContext) int {
|
||||||
|
d := ctx.proxyCtx
|
||||||
|
|
||||||
|
if !ctx.responseFromUpstream || // don't process response if it's not from upstream servers
|
||||||
|
!ctx.srv.conf.EnableDNSSEC {
|
||||||
|
return resultDone
|
||||||
|
}
|
||||||
|
|
||||||
|
optResp := d.Res.IsEdns0()
|
||||||
|
if !ctx.origReqDNSSEC && optResp != nil && optResp.Do() {
|
||||||
|
return resultDone
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove RRSIG records from response
|
||||||
|
// because there is no DO flag in the original request from client,
|
||||||
|
// but we have EnableDNSSEC set, so we have set DO flag ourselves,
|
||||||
|
// and now we have to clean up the DNS records our client didn't ask for.
|
||||||
|
|
||||||
|
answers := []dns.RR{}
|
||||||
|
for _, a := range d.Res.Answer {
|
||||||
|
switch a.(type) {
|
||||||
|
case *dns.RRSIG:
|
||||||
|
log.Debug("Removing RRSIG record from response: %v", a)
|
||||||
|
default:
|
||||||
|
answers = append(answers, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.Res.Answer = answers
|
||||||
|
|
||||||
|
answers = []dns.RR{}
|
||||||
|
for _, a := range d.Res.Ns {
|
||||||
|
switch a.(type) {
|
||||||
|
case *dns.RRSIG:
|
||||||
|
log.Debug("Removing RRSIG record from response: %v", a)
|
||||||
|
default:
|
||||||
|
answers = append(answers, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.Res.Ns = answers
|
||||||
|
|
||||||
|
return resultDone
|
||||||
|
}
|
||||||
|
|
||||||
// Apply filtering logic after we have received response from upstream servers
|
// Apply filtering logic after we have received response from upstream servers
|
||||||
func processFilteringAfterResponse(ctx *dnsContext) int {
|
func processFilteringAfterResponse(ctx *dnsContext) int {
|
||||||
s := ctx.srv
|
s := ctx.srv
|
||||||
|
@ -606,10 +665,6 @@ func processFilteringAfterResponse(ctx *dnsContext) int {
|
||||||
res := ctx.result
|
res := ctx.result
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if !ctx.responseFromUpstream {
|
|
||||||
return resultDone // don't process response if it's not from upstream servers
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Reason == dnsfilter.ReasonRewrite && len(res.CanonName) != 0 {
|
if res.Reason == dnsfilter.ReasonRewrite && len(res.CanonName) != 0 {
|
||||||
d.Req.Question[0] = ctx.origQuestion
|
d.Req.Question[0] = ctx.origQuestion
|
||||||
d.Res.Question[0] = ctx.origQuestion
|
d.Res.Question[0] = ctx.origQuestion
|
||||||
|
@ -688,14 +743,19 @@ func (s *Server) handleDNSRequest(p *proxy.Proxy, d *proxy.DNSContext) error {
|
||||||
processInitial,
|
processInitial,
|
||||||
processFilteringBeforeRequest,
|
processFilteringBeforeRequest,
|
||||||
processUpstream,
|
processUpstream,
|
||||||
|
processDNSSECAfterResponse,
|
||||||
processFilteringAfterResponse,
|
processFilteringAfterResponse,
|
||||||
processQueryLogsAndStats,
|
processQueryLogsAndStats,
|
||||||
}
|
}
|
||||||
for _, process := range mods {
|
for _, process := range mods {
|
||||||
r := process(ctx)
|
r := process(ctx)
|
||||||
switch r {
|
switch r {
|
||||||
|
case resultDone:
|
||||||
|
// continue: call the next filter
|
||||||
|
|
||||||
case resultFinish:
|
case resultFinish:
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case resultError:
|
case resultError:
|
||||||
return ctx.err
|
return ctx.err
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ type dnsConfigJSON struct {
|
||||||
BlockingIPv4 string `json:"blocking_ipv4"`
|
BlockingIPv4 string `json:"blocking_ipv4"`
|
||||||
BlockingIPv6 string `json:"blocking_ipv6"`
|
BlockingIPv6 string `json:"blocking_ipv6"`
|
||||||
EDNSCSEnabled bool `json:"edns_cs_enabled"`
|
EDNSCSEnabled bool `json:"edns_cs_enabled"`
|
||||||
|
DNSSECEnabled bool `json:"dnssec_enabled"`
|
||||||
DisableIPv6 bool `json:"disable_ipv6"`
|
DisableIPv6 bool `json:"disable_ipv6"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
resp.BlockingIPv6 = s.conf.BlockingIPv6
|
resp.BlockingIPv6 = s.conf.BlockingIPv6
|
||||||
resp.RateLimit = s.conf.Ratelimit
|
resp.RateLimit = s.conf.Ratelimit
|
||||||
resp.EDNSCSEnabled = s.conf.EnableEDNSClientSubnet
|
resp.EDNSCSEnabled = s.conf.EnableEDNSClientSubnet
|
||||||
|
resp.DNSSECEnabled = s.conf.EnableDNSSEC
|
||||||
resp.DisableIPv6 = s.conf.AAAADisabled
|
resp.DisableIPv6 = s.conf.AAAADisabled
|
||||||
s.RUnlock()
|
s.RUnlock()
|
||||||
|
|
||||||
|
@ -119,6 +121,10 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
restart = true
|
restart = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if js.Exists("dnssec_enabled") {
|
||||||
|
s.conf.EnableDNSSEC = req.DNSSECEnabled
|
||||||
|
}
|
||||||
|
|
||||||
if js.Exists("disable_ipv6") {
|
if js.Exists("disable_ipv6") {
|
||||||
s.conf.AAAADisabled = req.DisableIPv6
|
s.conf.AAAADisabled = req.DisableIPv6
|
||||||
}
|
}
|
||||||
|
|
|
@ -1110,6 +1110,8 @@ definitions:
|
||||||
type: "string"
|
type: "string"
|
||||||
edns_cs_enabled:
|
edns_cs_enabled:
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
|
dnssec_enabled:
|
||||||
|
type: "boolean"
|
||||||
|
|
||||||
UpstreamsConfig:
|
UpstreamsConfig:
|
||||||
type: "object"
|
type: "object"
|
||||||
|
@ -1517,6 +1519,8 @@ definitions:
|
||||||
description: "Answer from upstream server (optional)"
|
description: "Answer from upstream server (optional)"
|
||||||
items:
|
items:
|
||||||
$ref: "#/definitions/DnsAnswer"
|
$ref: "#/definitions/DnsAnswer"
|
||||||
|
answer_dnssec:
|
||||||
|
type: "boolean"
|
||||||
client:
|
client:
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "192.168.0.1"
|
example: "192.168.0.1"
|
||||||
|
|
|
@ -286,7 +286,15 @@ func logEntryToJSONEntry(entry *logEntry) map[string]interface{} {
|
||||||
|
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
jsonEntry["status"] = dns.RcodeToString[msg.Rcode]
|
jsonEntry["status"] = dns.RcodeToString[msg.Rcode]
|
||||||
|
|
||||||
|
opt := msg.IsEdns0()
|
||||||
|
dnssecOk := false
|
||||||
|
if opt != nil {
|
||||||
|
dnssecOk = opt.Do()
|
||||||
}
|
}
|
||||||
|
jsonEntry["answer_dnssec"] = dnssecOk
|
||||||
|
}
|
||||||
|
|
||||||
if len(entry.Result.Rule) > 0 {
|
if len(entry.Result.Rule) > 0 {
|
||||||
jsonEntry["rule"] = entry.Result.Rule
|
jsonEntry["rule"] = entry.Result.Rule
|
||||||
jsonEntry["filterId"] = entry.Result.FilterID
|
jsonEntry["filterId"] = entry.Result.FilterID
|
||||||
|
|
Loading…
Reference in New Issue