obfuscate log output for user sensitive data to increase privacy (#225)

This commit is contained in:
Dimitri Herzog 2021-08-22 22:45:11 +02:00
parent 6e2dbe4681
commit 6a3baa5b95
5 changed files with 24 additions and 7 deletions

View File

@ -209,6 +209,7 @@ type Config struct {
Prometheus PrometheusConfig `yaml:"prometheus"`
LogLevel string `yaml:"logLevel"`
LogFormat string `yaml:"logFormat"`
LogPrivacy bool `yaml:"logPrivacy"`
LogTimestamp bool `yaml:"logTimestamp"`
Port string `yaml:"port"`
HTTPPort string `yaml:"httpPort"`

View File

@ -135,7 +135,7 @@ httpPort: 4000
# mandatory, if https port > 0: path to cert and key file for SSL encryption
#httpsCertFile: server.crt
#httpsKeyFile: server.key
# optional: use this DNS server to resolve blacklist urls and upstream DNS servers (DOH). Useful if no DNS resolver is configured and blocky needs to resolve a host name. Format net:IP:port, net must be udp or tcp
# optional: use this DNS server to resolve blacklist urls and upstream DNS servers. Useful if no DNS resolver is configured and blocky needs to resolve a host name. Format net:IP:port, net must be udp or tcp
bootstrapDns: tcp:1.1.1.1
# optional: Drop all AAAA query if set to true. Default: false
disableIPv6: false
@ -145,3 +145,5 @@ logLevel: info
logFormat: text
# optional: log timestamps. Default: true
logTimestamp: true
# optional: obfuscate log output (replace all alphanumeric characters with *) for user sensitive data like request domains or responses to increase privacy. Default: false
logPrivacy: false

View File

@ -12,11 +12,12 @@ configuration properties as [JSON](config.yml).
| httpsPort | no | | HTTPS listener port and optional bind ip address . If > 0, will be used for prometheus metrics, pprof, REST API, DoH... If you wish to specify a specific IP, you can do so such as 192.168.0.1:443 |
| httpsCertFile | yes, if httpsPort > 0 | | path to cert and key file for SSL encryption |
| httpsKeyFile | yes, if httpsPort > 0 | | path to cert and key file for SSL encryption |
| bootstrapDns | no | | use this DNS server to resolve blacklist urls and upstream DNS servers (DoH). Useful if no DNS resolver is configured and blocky needs to resolve a host name. Format net:IP:port, net must be udp or tcp|
| bootstrapDns | no | | use this DNS server to resolve blacklist urls and upstream DNS servers. Useful if no DNS resolver is configured and blocky needs to resolve a host name. Format net:IP:port, net must be udp or tcp|
| disableIPv6 | no | false | Drop all AAAA query if set to true
| logLevel | no | info | Log level (one from debug, info, warn, error) |
| logFormat | no | text | Log format (text or json). |
| logTimestamp | no | true | Log time stamps (true or false). |
| logPrivacy | no | false | Obfuscate log output (replace all alphanumeric characters with *) for user sensitive data like request domains or responses to increase privacy. |
!!! example

View File

@ -82,7 +82,7 @@ func (r *CachingResolver) onEvicted(cacheKey string) {
// check if domain was queried > threshold in the time window
if found && cnt.(int) > r.prefetchThreshold {
logger.Debugf("prefetching '%s' (%s)", domainName, dns.TypeToString[qType])
logger.Debugf("prefetching '%s' (%s)", util.Obfuscate(domainName), dns.TypeToString[qType])
req := newRequest(fmt.Sprintf("%s.", domainName), qType, logger)
response, err := r.next.Resolve(req)
@ -137,7 +137,7 @@ func (r *CachingResolver) Resolve(request *Request) (response *Response, err err
for _, question := range request.Req.Question {
domain := util.ExtractDomain(question)
cacheKey := util.GenerateCacheKey(question.Qtype, domain)
logger := logger.WithField("domain", domain)
logger := logger.WithField("domain", util.Obfuscate(domain))
r.trackQueryDomainNameCount(domain, cacheKey, logger)
@ -194,7 +194,7 @@ func (r *CachingResolver) trackQueryDomainNameCount(domain string, cacheKey stri
domainCount++
r.prefetchingNameCache.SetDefault(cacheKey, domainCount)
logger.Debugf("domain '%s' was requested %d times, "+
"total cache size: %d", domain, domainCount, r.prefetchingNameCache.ItemCount())
"total cache size: %d", util.Obfuscate(domain), domainCount, r.prefetchingNameCache.ItemCount())
evt.Bus().Publish(evt.CachingDomainsToPrefetchCountChanged, r.prefetchingNameCache.ItemCount())
}
}

View File

@ -1,10 +1,12 @@
package util
import (
"blocky/config"
"encoding/binary"
"fmt"
"net"
"path/filepath"
"regexp"
"sort"
"strings"
@ -14,6 +16,17 @@ import (
"github.com/sirupsen/logrus"
)
var alphanumeric = regexp.MustCompile("[a-zA-Z0-9]")
// Obfuscate replaces all alphanumeric characters with * to obfuscate user sensitive data if LogPrivacy is enabled
func Obfuscate(in string) string {
if config.GetConfig().LogPrivacy {
return alphanumeric.ReplaceAllString(in, "*")
}
return in
}
// AnswerToString creates a user-friendly representation of an answer
func AnswerToString(answer []dns.RR) string {
answers := make([]string, len(answer))
@ -33,7 +46,7 @@ func AnswerToString(answer []dns.RR) string {
}
}
return strings.Join(answers, ", ")
return Obfuscate(strings.Join(answers, ", "))
}
// QuestionToString creates a user-friendly representation of a question
@ -43,7 +56,7 @@ func QuestionToString(questions []dns.Question) string {
result[i] = fmt.Sprintf("%s (%s)", dns.TypeToString[question.Qtype], question.Name)
}
return strings.Join(result, ", ")
return Obfuscate(strings.Join(result, ", "))
}
// CreateAnswerFromQuestion creates new answer from a question