Support workarounds for ancient/broken implementations

Fixes #984
This commit is contained in:
Frank Denis 2019-11-16 18:51:16 +01:00
parent f76e0fd8cf
commit 15b405b552
5 changed files with 90 additions and 47 deletions

View File

@ -46,47 +46,48 @@ type Config struct {
LBEstimator bool `toml:"lb_estimator"` LBEstimator bool `toml:"lb_estimator"`
BlockIPv6 bool `toml:"block_ipv6"` BlockIPv6 bool `toml:"block_ipv6"`
Cache bool Cache bool
CacheSize int `toml:"cache_size"` CacheSize int `toml:"cache_size"`
CacheNegTTL uint32 `toml:"cache_neg_ttl"` CacheNegTTL uint32 `toml:"cache_neg_ttl"`
CacheNegMinTTL uint32 `toml:"cache_neg_min_ttl"` CacheNegMinTTL uint32 `toml:"cache_neg_min_ttl"`
CacheNegMaxTTL uint32 `toml:"cache_neg_max_ttl"` CacheNegMaxTTL uint32 `toml:"cache_neg_max_ttl"`
CacheMinTTL uint32 `toml:"cache_min_ttl"` CacheMinTTL uint32 `toml:"cache_min_ttl"`
CacheMaxTTL uint32 `toml:"cache_max_ttl"` CacheMaxTTL uint32 `toml:"cache_max_ttl"`
RejectTTL uint32 `toml:"reject_ttl"` RejectTTL uint32 `toml:"reject_ttl"`
CloakTTL uint32 `toml:"cloak_ttl"` CloakTTL uint32 `toml:"cloak_ttl"`
QueryLog QueryLogConfig `toml:"query_log"` QueryLog QueryLogConfig `toml:"query_log"`
NxLog NxLogConfig `toml:"nx_log"` NxLog NxLogConfig `toml:"nx_log"`
BlockName BlockNameConfig `toml:"blacklist"` BlockName BlockNameConfig `toml:"blacklist"`
WhitelistName WhitelistNameConfig `toml:"whitelist"` WhitelistName WhitelistNameConfig `toml:"whitelist"`
BlockIP BlockIPConfig `toml:"ip_blacklist"` BlockIP BlockIPConfig `toml:"ip_blacklist"`
ForwardFile string `toml:"forwarding_rules"` ForwardFile string `toml:"forwarding_rules"`
CloakFile string `toml:"cloaking_rules"` CloakFile string `toml:"cloaking_rules"`
StaticsConfig map[string]StaticConfig `toml:"static"` StaticsConfig map[string]StaticConfig `toml:"static"`
SourcesConfig map[string]SourceConfig `toml:"sources"` SourcesConfig map[string]SourceConfig `toml:"sources"`
SourceRequireDNSSEC bool `toml:"require_dnssec"` BrokenImplementations BrokenImplementationsConfig `toml:"broken_implementations"`
SourceRequireNoLog bool `toml:"require_nolog"` SourceRequireDNSSEC bool `toml:"require_dnssec"`
SourceRequireNoFilter bool `toml:"require_nofilter"` SourceRequireNoLog bool `toml:"require_nolog"`
SourceDNSCrypt bool `toml:"dnscrypt_servers"` SourceRequireNoFilter bool `toml:"require_nofilter"`
SourceDoH bool `toml:"doh_servers"` SourceDNSCrypt bool `toml:"dnscrypt_servers"`
SourceIPv4 bool `toml:"ipv4_servers"` SourceDoH bool `toml:"doh_servers"`
SourceIPv6 bool `toml:"ipv6_servers"` SourceIPv4 bool `toml:"ipv4_servers"`
MaxClients uint32 `toml:"max_clients"` SourceIPv6 bool `toml:"ipv6_servers"`
FallbackResolver string `toml:"fallback_resolver"` MaxClients uint32 `toml:"max_clients"`
IgnoreSystemDNS bool `toml:"ignore_system_dns"` FallbackResolver string `toml:"fallback_resolver"`
AllWeeklyRanges map[string]WeeklyRangesStr `toml:"schedules"` IgnoreSystemDNS bool `toml:"ignore_system_dns"`
LogMaxSize int `toml:"log_files_max_size"` AllWeeklyRanges map[string]WeeklyRangesStr `toml:"schedules"`
LogMaxAge int `toml:"log_files_max_age"` LogMaxSize int `toml:"log_files_max_size"`
LogMaxBackups int `toml:"log_files_max_backups"` LogMaxAge int `toml:"log_files_max_age"`
TLSDisableSessionTickets bool `toml:"tls_disable_session_tickets"` LogMaxBackups int `toml:"log_files_max_backups"`
TLSCipherSuite []uint16 `toml:"tls_cipher_suite"` TLSDisableSessionTickets bool `toml:"tls_disable_session_tickets"`
NetprobeAddress string `toml:"netprobe_address"` TLSCipherSuite []uint16 `toml:"tls_cipher_suite"`
NetprobeTimeout int `toml:"netprobe_timeout"` NetprobeAddress string `toml:"netprobe_address"`
OfflineMode bool `toml:"offline_mode"` NetprobeTimeout int `toml:"netprobe_timeout"`
HTTPProxyURL string `toml:"http_proxy"` OfflineMode bool `toml:"offline_mode"`
RefusedCodeInResponses bool `toml:"refused_code_in_responses"` HTTPProxyURL string `toml:"http_proxy"`
BlockedQueryResponse string `toml:"blocked_query_response"` RefusedCodeInResponses bool `toml:"refused_code_in_responses"`
QueryMeta []string `toml:"query_meta"` BlockedQueryResponse string `toml:"blocked_query_response"`
AnonymizedDNS AnonymizedDNSConfig `toml:"anonymized_dns"` QueryMeta []string `toml:"query_meta"`
AnonymizedDNS AnonymizedDNSConfig `toml:"anonymized_dns"`
} }
func newConfig() Config { func newConfig() Config {
@ -181,6 +182,10 @@ type AnonymizedDNSConfig struct {
Routes []AnonymizedDNSRouteConfig `toml:"routes"` Routes []AnonymizedDNSRouteConfig `toml:"routes"`
} }
type BrokenImplementationsConfig struct {
IncorrectPadding []string `toml:"incorrect_padding"`
}
type ServerSummary struct { type ServerSummary struct {
Name string `json:"name"` Name string `json:"name"`
Proto string `json:"proto"` Proto string `json:"proto"`
@ -436,6 +441,7 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
} }
proxy.routes = &routes proxy.routes = &routes
} }
proxy.serversWithIncorrectPadding = config.BrokenImplementations.IncorrectPadding
if *flags.ListAll { if *flags.ListAll {
config.ServerNames = nil config.ServerNames = nil

View File

@ -79,12 +79,14 @@ func (proxy *Proxy) Encrypt(serverInfo *ServerInfo, packet []byte, proto string)
publicKey = &proxy.proxyPublicKey publicKey = &proxy.proxyPublicKey
} }
minQuestionSize := QueryOverhead + len(packet) minQuestionSize := QueryOverhead + len(packet)
if proto == "udp" { if !serverInfo.knownBugs.incorrectPadding {
minQuestionSize = Max(proxy.questionSizeEstimator.MinQuestionSize(), minQuestionSize) if proto == "udp" {
} else { minQuestionSize = Max(proxy.questionSizeEstimator.MinQuestionSize(), minQuestionSize)
var xpad [1]byte } else {
rand.Read(xpad[:]) var xpad [1]byte
minQuestionSize += int(xpad[0]) rand.Read(xpad[:])
minQuestionSize += int(xpad[0])
}
} }
paddedLength := Min(MaxDNSUDPPacketSize, (Max(minQuestionSize, QueryOverhead)+63) & ^63) paddedLength := Min(MaxDNSUDPPacketSize, (Max(minQuestionSize, QueryOverhead)+63) & ^63)
if serverInfo.RelayUDPAddr != nil && proto == "tcp" { if serverInfo.RelayUDPAddr != nil && proto == "tcp" {

View File

@ -567,6 +567,22 @@ cache_neg_max_ttl = 600
# minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3' # minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
#########################################
# Servers with known bugs #
#########################################
[broken_implementations]
# Cisco servers currently cannot handle queries larger than 1472 bytes.
# This prevents large DNSCrypt responses from being received, and breaks relaying.
incorrect_padding = ['cisco', 'cisco-ipv6', 'cisco-familyshield']
################################ ################################
# Anonymized DNS # # Anonymized DNS #
################################ ################################

View File

@ -71,6 +71,7 @@ type Proxy struct {
blockedQueryResponse string blockedQueryResponse string
queryMeta []string queryMeta []string
routes *map[string][]string routes *map[string][]string
serversWithIncorrectPadding []string
showCerts bool showCerts bool
} }

View File

@ -31,6 +31,10 @@ type RegisteredServer struct {
description string description string
} }
type ServerBugs struct {
incorrectPadding bool
}
type ServerInfo struct { type ServerInfo struct {
Proto stamps.StampProtoType Proto stamps.StampProtoType
MagicQuery [8]byte MagicQuery [8]byte
@ -45,6 +49,7 @@ type ServerInfo struct {
TCPAddr *net.TCPAddr TCPAddr *net.TCPAddr
RelayUDPAddr *net.UDPAddr RelayUDPAddr *net.UDPAddr
RelayTCPAddr *net.TCPAddr RelayTCPAddr *net.TCPAddr
knownBugs ServerBugs
lastActionTS time.Time lastActionTS time.Time
rtt ewma.MovingAverage rtt ewma.MovingAverage
initialRtt int initialRtt int
@ -293,7 +298,19 @@ func fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp
dlog.Warnf("Public key [%s] shouldn't be hex-encoded any more", string(stamp.ServerPk)) dlog.Warnf("Public key [%s] shouldn't be hex-encoded any more", string(stamp.ServerPk))
stamp.ServerPk = serverPk stamp.ServerPk = serverPk
} }
knownBugs := ServerBugs{}
for _, buggyServerName := range proxy.serversWithIncorrectPadding {
if buggyServerName == name {
knownBugs.incorrectPadding = true
dlog.Infof("Known bug in [%v]: padding is not correctly implemented", name)
break
}
}
relayUDPAddr, relayTCPAddr, err := route(proxy, name) relayUDPAddr, relayTCPAddr, err := route(proxy, name)
if knownBugs.incorrectPadding && (relayUDPAddr != nil || relayTCPAddr != nil) {
relayTCPAddr, relayUDPAddr = nil, nil
dlog.Warnf("[%v] is incompatible with anonymization", name)
}
if err != nil { if err != nil {
return ServerInfo{}, err return ServerInfo{}, err
} }
@ -322,6 +339,7 @@ func fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp
RelayUDPAddr: relayUDPAddr, RelayUDPAddr: relayUDPAddr,
RelayTCPAddr: relayTCPAddr, RelayTCPAddr: relayTCPAddr,
initialRtt: rtt, initialRtt: rtt,
knownBugs: knownBugs,
}, nil }, nil
} }