diff --git a/ChangeLog b/ChangeLog index 7e940caf..1d820792 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,8 @@ hashes. - DoH servers on a non-standard port, with stamps that don't include IP addresses, and without working system resolvers can now be properly bootstrapped. + - A new option, `query_meta`, is now available to add optional records +to client queries. * Version 2.0.25 - The example IP address for network probes didn't work on Windows. diff --git a/dnscrypt-proxy/config.go b/dnscrypt-proxy/config.go index 7f65fda7..0dadc621 100644 --- a/dnscrypt-proxy/config.go +++ b/dnscrypt-proxy/config.go @@ -82,6 +82,7 @@ type Config struct { HTTPProxyURL string `toml:"http_proxy"` RefusedCodeInResponses bool `toml:"refused_code_in_responses"` BlockedQueryResponse string `toml:"blocked_query_response"` + QueryMeta []string `toml:"query_meta"` } func newConfig() Config { @@ -351,6 +352,8 @@ func ConfigLoad(proxy *Proxy, svcFlag *string) error { proxy.cacheMinTTL = config.CacheMinTTL proxy.cacheMaxTTL = config.CacheMaxTTL + proxy.queryMeta = config.QueryMeta + if len(config.QueryLog.Format) == 0 { config.QueryLog.Format = "tsv" } else { diff --git a/dnscrypt-proxy/example-dnscrypt-proxy.toml b/dnscrypt-proxy/example-dnscrypt-proxy.toml index f54875a7..8455f8dd 100644 --- a/dnscrypt-proxy/example-dnscrypt-proxy.toml +++ b/dnscrypt-proxy/example-dnscrypt-proxy.toml @@ -230,6 +230,14 @@ netprobe_address = '9.9.9.9:53' # offline_mode = false +## Additional data to attach to outgoing queries. +## These strings will be added as TXT records to queries. +## Do not use, except on servers explicitly asking for extra data +## to be present. + +# query_meta = ["key1:value1", "key2:value2", "key3:value3"] + + ## Automatic log files rotation # Maximum log files size in MB diff --git a/dnscrypt-proxy/plugin_querymeta.go b/dnscrypt-proxy/plugin_querymeta.go new file mode 100644 index 00000000..68398f31 --- /dev/null +++ b/dnscrypt-proxy/plugin_querymeta.go @@ -0,0 +1,43 @@ +package main + +import ( + "github.com/miekg/dns" +) + +type PluginQueryMeta struct { + queryMetaRR *dns.TXT +} + +func (plugin *PluginQueryMeta) Name() string { + return "query_log" +} + +func (plugin *PluginQueryMeta) Description() string { + return "Log DNS queries." +} + +func (plugin *PluginQueryMeta) Init(proxy *Proxy) error { + queryMetaRR := new(dns.TXT) + queryMetaRR.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeTXT, + Class: dns.ClassINET, Ttl: 86400} + queryMetaRR.Txt = proxy.queryMeta + plugin.queryMetaRR = queryMetaRR + return nil +} + +func (plugin *PluginQueryMeta) Drop() error { + return nil +} + +func (plugin *PluginQueryMeta) Reload() error { + return nil +} + +func (plugin *PluginQueryMeta) Eval(pluginsState *PluginsState, msg *dns.Msg) error { + questions := msg.Question + if len(questions) == 0 { + return nil + } + msg.Extra = []dns.RR{plugin.queryMetaRR} + return nil +} diff --git a/dnscrypt-proxy/plugins.go b/dnscrypt-proxy/plugins.go index b678e577..4cb78683 100644 --- a/dnscrypt-proxy/plugins.go +++ b/dnscrypt-proxy/plugins.go @@ -83,6 +83,10 @@ type PluginsState struct { func InitPluginsGlobals(pluginsGlobals *PluginsGlobals, proxy *Proxy) error { queryPlugins := &[]Plugin{} + + if len(proxy.queryMeta) != 0 { + *queryPlugins = append(*queryPlugins, Plugin(new(PluginQueryMeta))) + } if len(proxy.whitelistNameFile) != 0 { *queryPlugins = append(*queryPlugins, Plugin(new(PluginWhitelistName))) } diff --git a/dnscrypt-proxy/proxy.go b/dnscrypt-proxy/proxy.go index d639acea..ad3d1d7d 100644 --- a/dnscrypt-proxy/proxy.go +++ b/dnscrypt-proxy/proxy.go @@ -64,6 +64,7 @@ type Proxy struct { logMaxAge int logMaxBackups int blockedQueryResponse string + queryMeta []string showCerts bool }