Keep lines short
$ golines -w -m 120 --shorten-comments .
This commit is contained in:
parent
c0435772d4
commit
df3fb0c9f8
|
@ -116,7 +116,12 @@ func handleColdStartClient(clientPc *net.UDPConn, cancelChannel chan struct{}, i
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func addColdStartListener(proxy *Proxy, ipsMap *CaptivePortalMap, listenAddrStr string, cancelChannel chan struct{}) error {
|
func addColdStartListener(
|
||||||
|
proxy *Proxy,
|
||||||
|
ipsMap *CaptivePortalMap,
|
||||||
|
listenAddrStr string,
|
||||||
|
cancelChannel chan struct{},
|
||||||
|
) error {
|
||||||
listenUDPAddr, err := net.ResolveUDPAddr("udp", listenAddrStr)
|
listenUDPAddr, err := net.ResolveUDPAddr("udp", listenAddrStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -314,7 +314,10 @@ func findConfigFile(configFile *string) (string, error) {
|
||||||
func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
||||||
foundConfigFile, err := findConfigFile(flags.ConfigFile)
|
foundConfigFile, err := findConfigFile(flags.ConfigFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to load the configuration file [%s] -- Maybe use the -config command-line switch?", *flags.ConfigFile)
|
return fmt.Errorf(
|
||||||
|
"Unable to load the configuration file [%s] -- Maybe use the -config command-line switch?",
|
||||||
|
*flags.ConfigFile,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
config := newConfig()
|
config := newConfig()
|
||||||
md, err := toml.DecodeFile(foundConfigFile, &config)
|
md, err := toml.DecodeFile(foundConfigFile, &config)
|
||||||
|
@ -638,7 +641,9 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backwards compatibility
|
// Backwards compatibility
|
||||||
config.BrokenImplementations.FragmentsBlocked = append(config.BrokenImplementations.FragmentsBlocked, config.BrokenImplementations.BrokenQueryPadding...)
|
config.BrokenImplementations.FragmentsBlocked = append(
|
||||||
|
config.BrokenImplementations.FragmentsBlocked,
|
||||||
|
config.BrokenImplementations.BrokenQueryPadding...)
|
||||||
|
|
||||||
proxy.serversBlockingFragments = config.BrokenImplementations.FragmentsBlocked
|
proxy.serversBlockingFragments = config.BrokenImplementations.FragmentsBlocked
|
||||||
|
|
||||||
|
@ -707,7 +712,9 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
||||||
// if 'userName' is set and we are the parent process drop privilege and exit
|
// if 'userName' is set and we are the parent process drop privilege and exit
|
||||||
if len(proxy.userName) > 0 && !proxy.child {
|
if len(proxy.userName) > 0 && !proxy.child {
|
||||||
proxy.dropPrivilege(proxy.userName, FileDescriptors)
|
proxy.dropPrivilege(proxy.userName, FileDescriptors)
|
||||||
return errors.New("Dropping privileges is not supporting on this operating system. Unset `user_name` in the configuration file")
|
return errors.New(
|
||||||
|
"Dropping privileges is not supporting on this operating system. Unset `user_name` in the configuration file",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if !config.OfflineMode {
|
if !config.OfflineMode {
|
||||||
if err := config.loadSources(proxy); err != nil {
|
if err := config.loadSources(proxy); err != nil {
|
||||||
|
@ -727,8 +734,12 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
||||||
hasSpecificRoutes := false
|
hasSpecificRoutes := false
|
||||||
for _, server := range proxy.registeredServers {
|
for _, server := range proxy.registeredServers {
|
||||||
if via, ok := (*proxy.routes)[server.name]; ok {
|
if via, ok := (*proxy.routes)[server.name]; ok {
|
||||||
if server.stamp.Proto != stamps.StampProtoTypeDNSCrypt && server.stamp.Proto != stamps.StampProtoTypeODoHTarget {
|
if server.stamp.Proto != stamps.StampProtoTypeDNSCrypt &&
|
||||||
dlog.Errorf("DNS anonymization is only supported with the DNSCrypt and ODoH protocols - Connections to [%v] cannot be anonymized", server.name)
|
server.stamp.Proto != stamps.StampProtoTypeODoHTarget {
|
||||||
|
dlog.Errorf(
|
||||||
|
"DNS anonymization is only supported with the DNSCrypt and ODoH protocols - Connections to [%v] cannot be anonymized",
|
||||||
|
server.name,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
dlog.Noticef("Anonymized DNS: routing [%v] via %v", server.name, via)
|
dlog.Noticef("Anonymized DNS: routing [%v] via %v", server.name, via)
|
||||||
}
|
}
|
||||||
|
@ -757,7 +768,8 @@ func (config *Config) printRegisteredServers(proxy *Proxy, jsonOutput bool) erro
|
||||||
var hostAddr string
|
var hostAddr string
|
||||||
hostAddr, port = ExtractHostAndPort(addrStr, port)
|
hostAddr, port = ExtractHostAndPort(addrStr, port)
|
||||||
addrs := make([]string, 0)
|
addrs := make([]string, 0)
|
||||||
if (registeredServer.stamp.Proto == stamps.StampProtoTypeDoH || registeredServer.stamp.Proto == stamps.StampProtoTypeODoHTarget) && len(registeredServer.stamp.ProviderName) > 0 {
|
if (registeredServer.stamp.Proto == stamps.StampProtoTypeDoH || registeredServer.stamp.Proto == stamps.StampProtoTypeODoHTarget) &&
|
||||||
|
len(registeredServer.stamp.ProviderName) > 0 {
|
||||||
providerName := registeredServer.stamp.ProviderName
|
providerName := registeredServer.stamp.ProviderName
|
||||||
var host string
|
var host string
|
||||||
host, port = ExtractHostAndPort(providerName, port)
|
host, port = ExtractHostAndPort(providerName, port)
|
||||||
|
@ -866,7 +878,16 @@ func (config *Config) loadSource(proxy *Proxy, cfgSourceName string, cfgSource *
|
||||||
} else if cfgSource.RefreshDelay > 168 {
|
} else if cfgSource.RefreshDelay > 168 {
|
||||||
cfgSource.RefreshDelay = 168
|
cfgSource.RefreshDelay = 168
|
||||||
}
|
}
|
||||||
source, err := NewSource(cfgSourceName, proxy.xTransport, cfgSource.URLs, cfgSource.MinisignKeyStr, cfgSource.CacheFile, cfgSource.FormatStr, time.Duration(cfgSource.RefreshDelay)*time.Hour, cfgSource.Prefix)
|
source, err := NewSource(
|
||||||
|
cfgSourceName,
|
||||||
|
proxy.xTransport,
|
||||||
|
cfgSource.URLs,
|
||||||
|
cfgSource.MinisignKeyStr,
|
||||||
|
cfgSource.CacheFile,
|
||||||
|
cfgSource.FormatStr,
|
||||||
|
time.Duration(cfgSource.RefreshDelay)*time.Hour,
|
||||||
|
cfgSource.Prefix,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if len(source.in) <= 0 {
|
if len(source.in) <= 0 {
|
||||||
dlog.Criticalf("Unable to retrieve source [%s]: [%s]", cfgSourceName, err)
|
dlog.Criticalf("Unable to retrieve source [%s]: [%s]", cfgSourceName, err)
|
||||||
|
@ -894,7 +915,10 @@ func cdFileDir(fileName string) error {
|
||||||
func cdLocal() {
|
func cdLocal() {
|
||||||
exeFileName, err := os.Executable()
|
exeFileName, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dlog.Warnf("Unable to determine the executable directory: [%s] -- You will need to specify absolute paths in the configuration file", err)
|
dlog.Warnf(
|
||||||
|
"Unable to determine the executable directory: [%s] -- You will need to specify absolute paths in the configuration file",
|
||||||
|
err,
|
||||||
|
)
|
||||||
} else if err := os.Chdir(filepath.Dir(exeFileName)); err != nil {
|
} else if err := os.Chdir(filepath.Dir(exeFileName)); err != nil {
|
||||||
dlog.Warnf("Unable to change working directory to [%s]: %s", exeFileName, err)
|
dlog.Warnf("Unable to change working directory to [%s]: %s", exeFileName, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,12 @@ func unpad(packet []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ComputeSharedKey(cryptoConstruction CryptoConstruction, secretKey *[32]byte, serverPk *[32]byte, providerName *string) (sharedKey [32]byte) {
|
func ComputeSharedKey(
|
||||||
|
cryptoConstruction CryptoConstruction,
|
||||||
|
secretKey *[32]byte,
|
||||||
|
serverPk *[32]byte,
|
||||||
|
providerName *string,
|
||||||
|
) (sharedKey [32]byte) {
|
||||||
if cryptoConstruction == XChacha20Poly1305 {
|
if cryptoConstruction == XChacha20Poly1305 {
|
||||||
var err error
|
var err error
|
||||||
sharedKey, err = xsecretbox.SharedKey(*secretKey, *serverPk)
|
sharedKey, err = xsecretbox.SharedKey(*secretKey, *serverPk)
|
||||||
|
@ -68,7 +73,11 @@ func ComputeSharedKey(cryptoConstruction CryptoConstruction, secretKey *[32]byte
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) Encrypt(serverInfo *ServerInfo, packet []byte, proto string) (sharedKey *[32]byte, encrypted []byte, clientNonce []byte, err error) {
|
func (proxy *Proxy) Encrypt(
|
||||||
|
serverInfo *ServerInfo,
|
||||||
|
packet []byte,
|
||||||
|
proto string,
|
||||||
|
) (sharedKey *[32]byte, encrypted []byte, clientNonce []byte, err error) {
|
||||||
nonce, clientNonce := make([]byte, NonceSize), make([]byte, HalfNonceSize)
|
nonce, clientNonce := make([]byte, NonceSize), make([]byte, HalfNonceSize)
|
||||||
crypto_rand.Read(clientNonce)
|
crypto_rand.Read(clientNonce)
|
||||||
copy(nonce, clientNonce)
|
copy(nonce, clientNonce)
|
||||||
|
@ -120,7 +129,12 @@ func (proxy *Proxy) Encrypt(serverInfo *ServerInfo, packet []byte, proto string)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) Decrypt(serverInfo *ServerInfo, sharedKey *[32]byte, encrypted []byte, nonce []byte) ([]byte, error) {
|
func (proxy *Proxy) Decrypt(
|
||||||
|
serverInfo *ServerInfo,
|
||||||
|
sharedKey *[32]byte,
|
||||||
|
encrypted []byte,
|
||||||
|
nonce []byte,
|
||||||
|
) ([]byte, error) {
|
||||||
serverMagicLen := len(ServerMagic)
|
serverMagicLen := len(ServerMagic)
|
||||||
responseHeaderLen := serverMagicLen + NonceSize
|
responseHeaderLen := serverMagicLen + NonceSize
|
||||||
if len(encrypted) < responseHeaderLen+TagSize+int(MinDNSPacketSize) ||
|
if len(encrypted) < responseHeaderLen+TagSize+int(MinDNSPacketSize) ||
|
||||||
|
|
|
@ -20,7 +20,17 @@ type CertInfo struct {
|
||||||
ForwardSecurity bool
|
ForwardSecurity bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func FetchCurrentDNSCryptCert(proxy *Proxy, serverName *string, proto string, pk ed25519.PublicKey, serverAddress string, providerName string, isNew bool, relay *DNSCryptRelay, knownBugs ServerBugs) (CertInfo, int, bool, error) {
|
func FetchCurrentDNSCryptCert(
|
||||||
|
proxy *Proxy,
|
||||||
|
serverName *string,
|
||||||
|
proto string,
|
||||||
|
pk ed25519.PublicKey,
|
||||||
|
serverAddress string,
|
||||||
|
providerName string,
|
||||||
|
isNew bool,
|
||||||
|
relay *DNSCryptRelay,
|
||||||
|
knownBugs ServerBugs,
|
||||||
|
) (CertInfo, int, bool, error) {
|
||||||
if len(pk) != ed25519.PublicKeySize {
|
if len(pk) != ed25519.PublicKeySize {
|
||||||
return CertInfo{}, 0, false, errors.New("Invalid public key length")
|
return CertInfo{}, 0, false, errors.New("Invalid public key length")
|
||||||
}
|
}
|
||||||
|
@ -34,7 +44,11 @@ func FetchCurrentDNSCryptCert(proxy *Proxy, serverName *string, proto string, pk
|
||||||
query.SetQuestion(providerName, dns.TypeTXT)
|
query.SetQuestion(providerName, dns.TypeTXT)
|
||||||
if !strings.HasPrefix(providerName, "2.dnscrypt-cert.") {
|
if !strings.HasPrefix(providerName, "2.dnscrypt-cert.") {
|
||||||
if relay != nil && !proxy.anonDirectCertFallback {
|
if relay != nil && !proxy.anonDirectCertFallback {
|
||||||
dlog.Warnf("[%v] uses a non-standard provider name, enable direct cert fallback to use with a relay ('%v' doesn't start with '2.dnscrypt-cert.')", *serverName, providerName)
|
dlog.Warnf(
|
||||||
|
"[%v] uses a non-standard provider name, enable direct cert fallback to use with a relay ('%v' doesn't start with '2.dnscrypt-cert.')",
|
||||||
|
*serverName,
|
||||||
|
providerName,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
dlog.Warnf("[%v] uses a non-standard provider name ('%v' doesn't start with '2.dnscrypt-cert.')", *serverName, providerName)
|
dlog.Warnf("[%v] uses a non-standard provider name ('%v' doesn't start with '2.dnscrypt-cert.')", *serverName, providerName)
|
||||||
relay = nil
|
relay = nil
|
||||||
|
@ -44,7 +58,15 @@ func FetchCurrentDNSCryptCert(proxy *Proxy, serverName *string, proto string, pk
|
||||||
if knownBugs.fragmentsBlocked {
|
if knownBugs.fragmentsBlocked {
|
||||||
tryFragmentsSupport = false
|
tryFragmentsSupport = false
|
||||||
}
|
}
|
||||||
in, rtt, fragmentsBlocked, err := DNSExchange(proxy, proto, &query, serverAddress, relay, serverName, tryFragmentsSupport)
|
in, rtt, fragmentsBlocked, err := DNSExchange(
|
||||||
|
proxy,
|
||||||
|
proto,
|
||||||
|
&query,
|
||||||
|
serverAddress,
|
||||||
|
relay,
|
||||||
|
serverName,
|
||||||
|
tryFragmentsSupport,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dlog.Noticef("[%s] TIMEOUT", *serverName)
|
dlog.Noticef("[%s] TIMEOUT", *serverName)
|
||||||
return CertInfo{}, 0, fragmentsBlocked, err
|
return CertInfo{}, 0, fragmentsBlocked, err
|
||||||
|
@ -95,10 +117,17 @@ func FetchCurrentDNSCryptCert(proxy *Proxy, serverName *string, proto string, pk
|
||||||
}
|
}
|
||||||
ttl := tsEnd - tsBegin
|
ttl := tsEnd - tsBegin
|
||||||
if ttl > 86400*7 {
|
if ttl > 86400*7 {
|
||||||
dlog.Infof("[%v] the key validity period for this server is excessively long (%d days), significantly reducing reliability and forward security.", *serverName, ttl/86400)
|
dlog.Infof(
|
||||||
|
"[%v] the key validity period for this server is excessively long (%d days), significantly reducing reliability and forward security.",
|
||||||
|
*serverName,
|
||||||
|
ttl/86400,
|
||||||
|
)
|
||||||
daysLeft := (tsEnd - now) / 86400
|
daysLeft := (tsEnd - now) / 86400
|
||||||
if daysLeft < 1 {
|
if daysLeft < 1 {
|
||||||
dlog.Criticalf("[%v] certificate will expire today -- Switch to a different resolver as soon as possible", *serverName)
|
dlog.Criticalf(
|
||||||
|
"[%v] certificate will expire today -- Switch to a different resolver as soon as possible",
|
||||||
|
*serverName,
|
||||||
|
)
|
||||||
} else if daysLeft <= 7 {
|
} else if daysLeft <= 7 {
|
||||||
dlog.Warnf("[%v] certificate is about to expire -- if you don't manage this server, tell the server operator about it", *serverName)
|
dlog.Warnf("[%v] certificate is about to expire -- if you don't manage this server, tell the server operator about it", *serverName)
|
||||||
} else if daysLeft <= 30 {
|
} else if daysLeft <= 30 {
|
||||||
|
@ -112,7 +141,13 @@ func FetchCurrentDNSCryptCert(proxy *Proxy, serverName *string, proto string, pk
|
||||||
}
|
}
|
||||||
if !proxy.certIgnoreTimestamp {
|
if !proxy.certIgnoreTimestamp {
|
||||||
if now > tsEnd || now < tsBegin {
|
if now > tsEnd || now < tsBegin {
|
||||||
dlog.Debugf("[%v] Certificate not valid at the current date (now: %v is not in [%v..%v])", *serverName, now, tsBegin, tsEnd)
|
dlog.Debugf(
|
||||||
|
"[%v] Certificate not valid at the current date (now: %v is not in [%v..%v])",
|
||||||
|
*serverName,
|
||||||
|
now,
|
||||||
|
tsBegin,
|
||||||
|
tsEnd,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,8 @@ func NormalizeQName(str string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMinTTL(msg *dns.Msg, minTTL uint32, maxTTL uint32, cacheNegMinTTL uint32, cacheNegMaxTTL uint32) time.Duration {
|
func getMinTTL(msg *dns.Msg, minTTL uint32, maxTTL uint32, cacheNegMinTTL uint32, cacheNegMaxTTL uint32) time.Duration {
|
||||||
if (msg.Rcode != dns.RcodeSuccess && msg.Rcode != dns.RcodeNameError) || (len(msg.Answer) <= 0 && len(msg.Ns) <= 0) {
|
if (msg.Rcode != dns.RcodeSuccess && msg.Rcode != dns.RcodeNameError) ||
|
||||||
|
(len(msg.Answer) <= 0 && len(msg.Ns) <= 0) {
|
||||||
return time.Duration(cacheNegMinTTL) * time.Second
|
return time.Duration(cacheNegMinTTL) * time.Second
|
||||||
}
|
}
|
||||||
var ttl uint32
|
var ttl uint32
|
||||||
|
@ -304,7 +305,15 @@ type DNSExchangeResponse struct {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func DNSExchange(proxy *Proxy, proto string, query *dns.Msg, serverAddress string, relay *DNSCryptRelay, serverName *string, tryFragmentsSupport bool) (*dns.Msg, time.Duration, bool, error) {
|
func DNSExchange(
|
||||||
|
proxy *Proxy,
|
||||||
|
proto string,
|
||||||
|
query *dns.Msg,
|
||||||
|
serverAddress string,
|
||||||
|
relay *DNSCryptRelay,
|
||||||
|
serverName *string,
|
||||||
|
tryFragmentsSupport bool,
|
||||||
|
) (*dns.Msg, time.Duration, bool, error) {
|
||||||
for {
|
for {
|
||||||
cancelChannel := make(chan struct{})
|
cancelChannel := make(chan struct{})
|
||||||
channel := make(chan DNSExchangeResponse)
|
channel := make(chan DNSExchangeResponse)
|
||||||
|
@ -375,12 +384,23 @@ func DNSExchange(proxy *Proxy, proto string, query *dns.Msg, serverAddress strin
|
||||||
}
|
}
|
||||||
return nil, 0, false, err
|
return nil, 0, false, err
|
||||||
}
|
}
|
||||||
dlog.Infof("Unable to get the public key for [%v] via relay [%v], retrying over a direct connection", *serverName, relay.RelayUDPAddr.IP)
|
dlog.Infof(
|
||||||
|
"Unable to get the public key for [%v] via relay [%v], retrying over a direct connection",
|
||||||
|
*serverName,
|
||||||
|
relay.RelayUDPAddr.IP,
|
||||||
|
)
|
||||||
relay = nil
|
relay = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _dnsExchange(proxy *Proxy, proto string, query *dns.Msg, serverAddress string, relay *DNSCryptRelay, paddedLen int) DNSExchangeResponse {
|
func _dnsExchange(
|
||||||
|
proxy *Proxy,
|
||||||
|
proto string,
|
||||||
|
query *dns.Msg,
|
||||||
|
serverAddress string,
|
||||||
|
relay *DNSCryptRelay,
|
||||||
|
paddedLen int,
|
||||||
|
) DNSExchangeResponse {
|
||||||
var packet []byte
|
var packet []byte
|
||||||
var rtt time.Duration
|
var rtt time.Duration
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,10 @@ type QuestionSizeEstimator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewQuestionSizeEstimator() QuestionSizeEstimator {
|
func NewQuestionSizeEstimator() QuestionSizeEstimator {
|
||||||
return QuestionSizeEstimator{minQuestionSize: InitialMinQuestionSize, ewma: ewma.NewMovingAverage(SizeEstimatorEwmaDecay)}
|
return QuestionSizeEstimator{
|
||||||
|
minQuestionSize: InitialMinQuestionSize,
|
||||||
|
ewma: ewma.NewMovingAverage(SizeEstimatorEwmaDecay),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (questionSizeEstimator *QuestionSizeEstimator) MinQuestionSize() int {
|
func (questionSizeEstimator *QuestionSizeEstimator) MinQuestionSize() int {
|
||||||
|
|
|
@ -23,8 +23,12 @@ func FuzzParseODoHTargetConfigs(f *testing.F) {
|
||||||
func FuzzParseStampParser(f *testing.F) {
|
func FuzzParseStampParser(f *testing.F) {
|
||||||
f.Add("sdns://AgcAAAAAAAAACzEwNC4yMS42Ljc4AA1kb2guY3J5cHRvLnN4Ci9kbnMtcXVlcnk")
|
f.Add("sdns://AgcAAAAAAAAACzEwNC4yMS42Ljc4AA1kb2guY3J5cHRvLnN4Ci9kbnMtcXVlcnk")
|
||||||
f.Add("sdns://AgcAAAAAAAAAGlsyNjA2OjQ3MDA6MzAzNzo6NjgxNTo2NGVdABJkb2gtaXB2Ni5jcnlwdG8uc3gKL2Rucy1xdWVyeQ")
|
f.Add("sdns://AgcAAAAAAAAAGlsyNjA2OjQ3MDA6MzAzNzo6NjgxNTo2NGVdABJkb2gtaXB2Ni5jcnlwdG8uc3gKL2Rucy1xdWVyeQ")
|
||||||
f.Add("sdns://AQcAAAAAAAAADTUxLjE1LjEyMi4yNTAg6Q3ZfapcbHgiHKLF7QFoli0Ty1Vsz3RXs1RUbxUrwZAcMi5kbnNjcnlwdC1jZXJ0LnNjYWxld2F5LWFtcw")
|
f.Add(
|
||||||
f.Add("sdns://AQcAAAAAAAAAFlsyMDAxOmJjODoxODIwOjUwZDo6MV0g6Q3ZfapcbHgiHKLF7QFoli0Ty1Vsz3RXs1RUbxUrwZAcMi5kbnNjcnlwdC1jZXJ0LnNjYWxld2F5LWFtcw")
|
"sdns://AQcAAAAAAAAADTUxLjE1LjEyMi4yNTAg6Q3ZfapcbHgiHKLF7QFoli0Ty1Vsz3RXs1RUbxUrwZAcMi5kbnNjcnlwdC1jZXJ0LnNjYWxld2F5LWFtcw",
|
||||||
|
)
|
||||||
|
f.Add(
|
||||||
|
"sdns://AQcAAAAAAAAAFlsyMDAxOmJjODoxODIwOjUwZDo6MV0g6Q3ZfapcbHgiHKLF7QFoli0Ty1Vsz3RXs1RUbxUrwZAcMi5kbnNjcnlwdC1jZXJ0LnNjYWxld2F5LWFtcw",
|
||||||
|
)
|
||||||
f.Add("sdns://gQ8xNjMuMTcyLjE4MC4xMjU")
|
f.Add("sdns://gQ8xNjMuMTcyLjE4MC4xMjU")
|
||||||
f.Add("sdns://BQcAAAAAAAAADm9kb2guY3J5cHRvLnN4Ci9kbnMtcXVlcnk")
|
f.Add("sdns://BQcAAAAAAAAADm9kb2guY3J5cHRvLnN4Ci9kbnMtcXVlcnk")
|
||||||
f.Add("sdns://hQcAAAAAAAAAACCi3jNJDEdtNW4tvHN8J3lpIklSa2Wrj7qaNCgEgci9_BpvZG9oLXJlbGF5LmVkZ2Vjb21wdXRlLmFwcAEv")
|
f.Add("sdns://hQcAAAAAAAAAACCi3jNJDEdtNW4tvHN8J3lpIklSa2Wrj7qaNCgEgci9_BpvZG9oLXJlbGF5LmVkZ2Vjb21wdXRlLmFwcAEv")
|
||||||
|
|
|
@ -114,7 +114,25 @@ func (proxy *Proxy) localDoHListener(acceptPc *net.TCPListener) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func dohPaddedLen(unpaddedLen int) int {
|
func dohPaddedLen(unpaddedLen int) int {
|
||||||
boundaries := [...]int{64, 128, 192, 256, 320, 384, 512, 704, 768, 896, 960, 1024, 1088, 1152, 2688, 4080, MaxDNSPacketSize}
|
boundaries := [...]int{
|
||||||
|
64,
|
||||||
|
128,
|
||||||
|
192,
|
||||||
|
256,
|
||||||
|
320,
|
||||||
|
384,
|
||||||
|
512,
|
||||||
|
704,
|
||||||
|
768,
|
||||||
|
896,
|
||||||
|
960,
|
||||||
|
1024,
|
||||||
|
1088,
|
||||||
|
1152,
|
||||||
|
2688,
|
||||||
|
4080,
|
||||||
|
MaxDNSPacketSize,
|
||||||
|
}
|
||||||
for _, boundary := range boundaries {
|
for _, boundary := range boundaries {
|
||||||
if boundary >= unpaddedLen {
|
if boundary >= unpaddedLen {
|
||||||
return boundary
|
return boundary
|
||||||
|
|
|
@ -22,7 +22,14 @@ func Logger(logMaxSize int, logMaxAge int, logMaxBackups int, fileName string) i
|
||||||
}
|
}
|
||||||
return fp
|
return fp
|
||||||
}
|
}
|
||||||
logger := &lumberjack.Logger{LocalTime: true, MaxSize: logMaxSize, MaxAge: logMaxAge, MaxBackups: logMaxBackups, Filename: fileName, Compress: true}
|
logger := &lumberjack.Logger{
|
||||||
|
LocalTime: true,
|
||||||
|
MaxSize: logMaxSize,
|
||||||
|
MaxAge: logMaxAge,
|
||||||
|
MaxBackups: logMaxBackups,
|
||||||
|
Filename: fileName,
|
||||||
|
Compress: true,
|
||||||
|
}
|
||||||
|
|
||||||
return logger
|
return logger
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,9 @@ func NetProbe(proxy *Proxy, address string, timeout int) error {
|
||||||
pc, err := net.DialUDP("udp", nil, remoteUDPAddr)
|
pc, err := net.DialUDP("udp", nil, remoteUDPAddr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Write at least 1 byte. This ensures that sockets are ready to use for writing.
|
// Write at least 1 byte. This ensures that sockets are ready to use for writing.
|
||||||
// Windows specific: during the system startup, sockets can be created but the underlying buffers may not be setup yet. If this is the case
|
// Windows specific: during the system startup, sockets can be created but the underlying buffers may not be
|
||||||
// Write fails with WSAENOBUFS: "An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full"
|
// setup yet. If this is the case Write fails with WSAENOBUFS: "An operation on a socket could not be
|
||||||
|
// performed because the system lacked sufficient buffer space or because a queue was full"
|
||||||
_, err = pc.Write([]byte{0})
|
_, err = pc.Write([]byte{0})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -130,7 +130,14 @@ func (plugin *PluginAllowedIP) Eval(pluginsState *PluginsState, msg *dns.Msg) er
|
||||||
year, month, day := now.Date()
|
year, month, day := now.Date()
|
||||||
hour, minute, second := now.Clock()
|
hour, minute, second := now.Clock()
|
||||||
tsStr := fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d]", year, int(month), day, hour, minute, second)
|
tsStr := fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d]", year, int(month), day, hour, minute, second)
|
||||||
line = fmt.Sprintf("%s\t%s\t%s\t%s\t%s\n", tsStr, clientIPStr, StringQuote(qName), StringQuote(ipStr), StringQuote(reason))
|
line = fmt.Sprintf(
|
||||||
|
"%s\t%s\t%s\t%s\t%s\n",
|
||||||
|
tsStr,
|
||||||
|
clientIPStr,
|
||||||
|
StringQuote(qName),
|
||||||
|
StringQuote(ipStr),
|
||||||
|
StringQuote(reason),
|
||||||
|
)
|
||||||
} else if plugin.format == "ltsv" {
|
} else if plugin.format == "ltsv" {
|
||||||
line = fmt.Sprintf("time:%d\thost:%s\tqname:%s\tip:%s\tmessage:%s\n", time.Now().Unix(), clientIPStr, StringQuote(qName), StringQuote(ipStr), StringQuote(reason))
|
line = fmt.Sprintf("time:%d\thost:%s\tqname:%s\tip:%s\tmessage:%s\n", time.Now().Unix(), clientIPStr, StringQuote(qName), StringQuote(ipStr), StringQuote(reason))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -134,7 +134,14 @@ func (plugin *PluginBlockIP) Eval(pluginsState *PluginsState, msg *dns.Msg) erro
|
||||||
year, month, day := now.Date()
|
year, month, day := now.Date()
|
||||||
hour, minute, second := now.Clock()
|
hour, minute, second := now.Clock()
|
||||||
tsStr := fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d]", year, int(month), day, hour, minute, second)
|
tsStr := fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d]", year, int(month), day, hour, minute, second)
|
||||||
line = fmt.Sprintf("%s\t%s\t%s\t%s\t%s\n", tsStr, clientIPStr, StringQuote(qName), StringQuote(ipStr), StringQuote(reason))
|
line = fmt.Sprintf(
|
||||||
|
"%s\t%s\t%s\t%s\t%s\n",
|
||||||
|
tsStr,
|
||||||
|
clientIPStr,
|
||||||
|
StringQuote(qName),
|
||||||
|
StringQuote(ipStr),
|
||||||
|
StringQuote(reason),
|
||||||
|
)
|
||||||
} else if plugin.format == "ltsv" {
|
} else if plugin.format == "ltsv" {
|
||||||
line = fmt.Sprintf("time:%d\thost:%s\tqname:%s\tip:%s\tmessage:%s\n", time.Now().Unix(), clientIPStr, StringQuote(qName), StringQuote(ipStr), StringQuote(reason))
|
line = fmt.Sprintf("time:%d\thost:%s\tqname:%s\tip:%s\tmessage:%s\n", time.Now().Unix(), clientIPStr, StringQuote(qName), StringQuote(ipStr), StringQuote(reason))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -139,7 +139,13 @@ func (plugin *PluginCacheResponse) Eval(pluginsState *PluginsState, msg *dns.Msg
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cacheKey := computeCacheKey(pluginsState, msg)
|
cacheKey := computeCacheKey(pluginsState, msg)
|
||||||
ttl := getMinTTL(msg, pluginsState.cacheMinTTL, pluginsState.cacheMaxTTL, pluginsState.cacheNegMinTTL, pluginsState.cacheNegMaxTTL)
|
ttl := getMinTTL(
|
||||||
|
msg,
|
||||||
|
pluginsState.cacheMinTTL,
|
||||||
|
pluginsState.cacheMaxTTL,
|
||||||
|
pluginsState.cacheNegMinTTL,
|
||||||
|
pluginsState.cacheNegMaxTTL,
|
||||||
|
)
|
||||||
cachedResponse := CachedResponse{
|
cachedResponse := CachedResponse{
|
||||||
expiration: time.Now().Add(ttl),
|
expiration: time.Now().Add(ttl),
|
||||||
msg: *msg,
|
msg: *msg,
|
||||||
|
|
|
@ -136,7 +136,8 @@ func (plugin *PluginCloak) Reload() error {
|
||||||
|
|
||||||
func (plugin *PluginCloak) Eval(pluginsState *PluginsState, msg *dns.Msg) error {
|
func (plugin *PluginCloak) Eval(pluginsState *PluginsState, msg *dns.Msg) error {
|
||||||
question := msg.Question[0]
|
question := msg.Question[0]
|
||||||
if question.Qclass != dns.ClassINET || (question.Qtype != dns.TypeA && question.Qtype != dns.TypeAAAA && question.Qtype != dns.TypePTR) {
|
if question.Qclass != dns.ClassINET ||
|
||||||
|
(question.Qtype != dns.TypeA && question.Qtype != dns.TypeAAAA && question.Qtype != dns.TypePTR) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
@ -207,7 +208,10 @@ func (plugin *PluginCloak) Eval(pluginsState *PluginsState, msg *dns.Msg) error
|
||||||
synth.Answer = append(synth.Answer, rr)
|
synth.Answer = append(synth.Answer, rr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rand.Shuffle(len(synth.Answer), func(i, j int) { synth.Answer[i], synth.Answer[j] = synth.Answer[j], synth.Answer[i] })
|
rand.Shuffle(
|
||||||
|
len(synth.Answer),
|
||||||
|
func(i, j int) { synth.Answer[i], synth.Answer[j] = synth.Answer[j], synth.Answer[i] },
|
||||||
|
)
|
||||||
pluginsState.synthResponse = synth
|
pluginsState.synthResponse = synth
|
||||||
pluginsState.action = PluginsActionSynth
|
pluginsState.action = PluginsActionSynth
|
||||||
pluginsState.returnCode = PluginsReturnCodeCloak
|
pluginsState.returnCode = PluginsReturnCodeCloak
|
||||||
|
|
|
@ -87,7 +87,15 @@ func (plugin *PluginDNS64) Eval(pluginsState *PluginsState, msg *dns.Msg) error
|
||||||
if !plugin.proxy.clientsCountInc() {
|
if !plugin.proxy.clientsCountInc() {
|
||||||
return errors.New("Too many concurrent connections to handle DNS64 subqueries")
|
return errors.New("Too many concurrent connections to handle DNS64 subqueries")
|
||||||
}
|
}
|
||||||
respPacket := plugin.proxy.processIncomingQuery("trampoline", plugin.proxy.mainProto, msgAPacket, nil, nil, time.Now(), false)
|
respPacket := plugin.proxy.processIncomingQuery(
|
||||||
|
"trampoline",
|
||||||
|
plugin.proxy.mainProto,
|
||||||
|
msgAPacket,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
time.Now(),
|
||||||
|
false,
|
||||||
|
)
|
||||||
plugin.proxy.clientsCountDec()
|
plugin.proxy.clientsCountDec()
|
||||||
resp := dns.Msg{}
|
resp := dns.Msg{}
|
||||||
if err := resp.Unpack(respPacket); err != nil {
|
if err := resp.Unpack(respPacket); err != nil {
|
||||||
|
@ -125,7 +133,12 @@ func (plugin *PluginDNS64) Eval(pluginsState *PluginsState, msg *dns.Msg) error
|
||||||
for _, prefix := range plugin.pref64 {
|
for _, prefix := range plugin.pref64 {
|
||||||
ipv6 := translateToIPv6(ipv4, prefix)
|
ipv6 := translateToIPv6(ipv4, prefix)
|
||||||
synthAAAA := new(dns.AAAA)
|
synthAAAA := new(dns.AAAA)
|
||||||
synthAAAA.Hdr = dns.RR_Header{Name: header.Name, Rrtype: dns.TypeAAAA, Class: header.Class, Ttl: ttl}
|
synthAAAA.Hdr = dns.RR_Header{
|
||||||
|
Name: header.Name,
|
||||||
|
Rrtype: dns.TypeAAAA,
|
||||||
|
Class: header.Class,
|
||||||
|
Ttl: ttl,
|
||||||
|
}
|
||||||
synthAAAA.AAAA = ipv6
|
synthAAAA.AAAA = ipv6
|
||||||
synthAAAAs = append(synthAAAAs, synthAAAA)
|
synthAAAAs = append(synthAAAAs, synthAAAA)
|
||||||
}
|
}
|
||||||
|
@ -190,7 +203,8 @@ func (plugin *PluginDNS64) fetchPref64(resolver string) error {
|
||||||
if ipv6 != nil && len(ipv6) == net.IPv6len {
|
if ipv6 != nil && len(ipv6) == net.IPv6len {
|
||||||
prefEnd := 0
|
prefEnd := 0
|
||||||
|
|
||||||
if wka := net.IPv4(ipv6[12], ipv6[13], ipv6[14], ipv6[15]); wka.Equal(rfc7050WKA1) || wka.Equal(rfc7050WKA2) { //96
|
if wka := net.IPv4(ipv6[12], ipv6[13], ipv6[14], ipv6[15]); wka.Equal(rfc7050WKA1) ||
|
||||||
|
wka.Equal(rfc7050WKA2) { //96
|
||||||
prefEnd = 12
|
prefEnd = 12
|
||||||
} else if wka := net.IPv4(ipv6[9], ipv6[10], ipv6[11], ipv6[12]); wka.Equal(rfc7050WKA1) || wka.Equal(rfc7050WKA2) { //64
|
} else if wka := net.IPv4(ipv6[9], ipv6[10], ipv6[11], ipv6[12]); wka.Equal(rfc7050WKA1) || wka.Equal(rfc7050WKA2) { //64
|
||||||
prefEnd = 8
|
prefEnd = 8
|
||||||
|
|
|
@ -82,7 +82,8 @@ func (plugin *PluginForward) Eval(pluginsState *PluginsState, msg *dns.Msg) erro
|
||||||
if candidateLen > qNameLen {
|
if candidateLen > qNameLen {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if qName[qNameLen-candidateLen:] == candidate.domain && (candidateLen == qNameLen || (qName[qNameLen-candidateLen-1] == '.')) {
|
if qName[qNameLen-candidateLen:] == candidate.domain &&
|
||||||
|
(candidateLen == qNameLen || (qName[qNameLen-candidateLen-1] == '.')) {
|
||||||
servers = candidate.servers
|
servers = candidate.servers
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,18 @@ func (plugin *PluginGetSetPayloadSize) Eval(pluginsState *PluginsState, msg *dns
|
||||||
dnssec := false
|
dnssec := false
|
||||||
if edns0 != nil {
|
if edns0 != nil {
|
||||||
pluginsState.maxUnencryptedUDPSafePayloadSize = int(edns0.UDPSize())
|
pluginsState.maxUnencryptedUDPSafePayloadSize = int(edns0.UDPSize())
|
||||||
pluginsState.originalMaxPayloadSize = Max(pluginsState.maxUnencryptedUDPSafePayloadSize-ResponseOverhead, pluginsState.originalMaxPayloadSize)
|
pluginsState.originalMaxPayloadSize = Max(
|
||||||
|
pluginsState.maxUnencryptedUDPSafePayloadSize-ResponseOverhead,
|
||||||
|
pluginsState.originalMaxPayloadSize,
|
||||||
|
)
|
||||||
dnssec = edns0.Do()
|
dnssec = edns0.Do()
|
||||||
}
|
}
|
||||||
var options *[]dns.EDNS0
|
var options *[]dns.EDNS0
|
||||||
pluginsState.dnssec = dnssec
|
pluginsState.dnssec = dnssec
|
||||||
pluginsState.maxPayloadSize = Min(MaxDNSUDPPacketSize-ResponseOverhead, Max(pluginsState.originalMaxPayloadSize, pluginsState.maxPayloadSize))
|
pluginsState.maxPayloadSize = Min(
|
||||||
|
MaxDNSUDPPacketSize-ResponseOverhead,
|
||||||
|
Max(pluginsState.originalMaxPayloadSize, pluginsState.maxPayloadSize),
|
||||||
|
)
|
||||||
if pluginsState.maxPayloadSize > 512 {
|
if pluginsState.maxPayloadSize > 512 {
|
||||||
extra2 := []dns.RR{}
|
extra2 := []dns.RR{}
|
||||||
for _, extra := range msg.Extra {
|
for _, extra := range msg.Extra {
|
||||||
|
|
|
@ -86,8 +86,16 @@ func (plugin *PluginQueryLog) Eval(pluginsState *PluginsState, msg *dns.Msg) err
|
||||||
year, month, day := now.Date()
|
year, month, day := now.Date()
|
||||||
hour, minute, second := now.Clock()
|
hour, minute, second := now.Clock()
|
||||||
tsStr := fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d]", year, int(month), day, hour, minute, second)
|
tsStr := fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d]", year, int(month), day, hour, minute, second)
|
||||||
line = fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%dms\t%s\n", tsStr, clientIPStr, StringQuote(qName), qType, returnCode, requestDuration/time.Millisecond,
|
line = fmt.Sprintf(
|
||||||
StringQuote(pluginsState.serverName))
|
"%s\t%s\t%s\t%s\t%s\t%dms\t%s\n",
|
||||||
|
tsStr,
|
||||||
|
clientIPStr,
|
||||||
|
StringQuote(qName),
|
||||||
|
qType,
|
||||||
|
returnCode,
|
||||||
|
requestDuration/time.Millisecond,
|
||||||
|
StringQuote(pluginsState.serverName),
|
||||||
|
)
|
||||||
} else if plugin.format == "ltsv" {
|
} else if plugin.format == "ltsv" {
|
||||||
cached := 0
|
cached := 0
|
||||||
if pluginsState.cacheHit {
|
if pluginsState.cacheHit {
|
||||||
|
|
|
@ -206,7 +206,9 @@ func parseBlockedQueryResponse(blockedResponse string, pluginsGlobals *PluginsGl
|
||||||
(*pluginsGlobals).respondWithIPv6 = net.ParseIP(ipv6Response)
|
(*pluginsGlobals).respondWithIPv6 = net.ParseIP(ipv6Response)
|
||||||
|
|
||||||
if (*pluginsGlobals).respondWithIPv6 == nil {
|
if (*pluginsGlobals).respondWithIPv6 == nil {
|
||||||
dlog.Notice("Error parsing IPv6 response given in blocked_query_response option, defaulting to IPv4")
|
dlog.Notice(
|
||||||
|
"Error parsing IPv6 response given in blocked_query_response option, defaulting to IPv4",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dlog.Noticef("Invalid IPv6 response given in blocked_query_response option [%s], the option should take the form 'a:<IPv4>,aaaa:<IPv6>'", blockedIPStrings[1])
|
dlog.Noticef("Invalid IPv6 response given in blocked_query_response option [%s], the option should take the form 'a:<IPv4>,aaaa:<IPv6>'", blockedIPStrings[1])
|
||||||
|
@ -238,7 +240,13 @@ type Plugin interface {
|
||||||
Eval(pluginsState *PluginsState, msg *dns.Msg) error
|
Eval(pluginsState *PluginsState, msg *dns.Msg) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPluginsState(proxy *Proxy, clientProto string, clientAddr *net.Addr, serverProto string, start time.Time) PluginsState {
|
func NewPluginsState(
|
||||||
|
proxy *Proxy,
|
||||||
|
clientProto string,
|
||||||
|
clientAddr *net.Addr,
|
||||||
|
serverProto string,
|
||||||
|
start time.Time,
|
||||||
|
) PluginsState {
|
||||||
return PluginsState{
|
return PluginsState{
|
||||||
action: PluginsActionContinue,
|
action: PluginsActionContinue,
|
||||||
returnCode: PluginsReturnCodePass,
|
returnCode: PluginsReturnCodePass,
|
||||||
|
@ -262,7 +270,11 @@ func NewPluginsState(proxy *Proxy, clientProto string, clientAddr *net.Addr, ser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pluginsState *PluginsState) ApplyQueryPlugins(pluginsGlobals *PluginsGlobals, packet []byte, needsEDNS0Padding bool) ([]byte, error) {
|
func (pluginsState *PluginsState) ApplyQueryPlugins(
|
||||||
|
pluginsGlobals *PluginsGlobals,
|
||||||
|
packet []byte,
|
||||||
|
needsEDNS0Padding bool,
|
||||||
|
) ([]byte, error) {
|
||||||
msg := dns.Msg{}
|
msg := dns.Msg{}
|
||||||
if err := msg.Unpack(packet); err != nil {
|
if err := msg.Unpack(packet); err != nil {
|
||||||
return packet, err
|
return packet, err
|
||||||
|
@ -288,7 +300,13 @@ func (pluginsState *PluginsState) ApplyQueryPlugins(pluginsGlobals *PluginsGloba
|
||||||
return packet, err
|
return packet, err
|
||||||
}
|
}
|
||||||
if pluginsState.action == PluginsActionReject {
|
if pluginsState.action == PluginsActionReject {
|
||||||
synth := RefusedResponseFromMessage(&msg, pluginsGlobals.refusedCodeInResponses, pluginsGlobals.respondWithIPv4, pluginsGlobals.respondWithIPv6, pluginsState.rejectTTL)
|
synth := RefusedResponseFromMessage(
|
||||||
|
&msg,
|
||||||
|
pluginsGlobals.refusedCodeInResponses,
|
||||||
|
pluginsGlobals.respondWithIPv4,
|
||||||
|
pluginsGlobals.respondWithIPv6,
|
||||||
|
pluginsState.rejectTTL,
|
||||||
|
)
|
||||||
pluginsState.synthResponse = synth
|
pluginsState.synthResponse = synth
|
||||||
}
|
}
|
||||||
if pluginsState.action != PluginsActionContinue {
|
if pluginsState.action != PluginsActionContinue {
|
||||||
|
@ -309,7 +327,11 @@ func (pluginsState *PluginsState) ApplyQueryPlugins(pluginsGlobals *PluginsGloba
|
||||||
return packet2, nil
|
return packet2, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pluginsState *PluginsState) ApplyResponsePlugins(pluginsGlobals *PluginsGlobals, packet []byte, ttl *uint32) ([]byte, error) {
|
func (pluginsState *PluginsState) ApplyResponsePlugins(
|
||||||
|
pluginsGlobals *PluginsGlobals,
|
||||||
|
packet []byte,
|
||||||
|
ttl *uint32,
|
||||||
|
) ([]byte, error) {
|
||||||
msg := dns.Msg{Compress: true}
|
msg := dns.Msg{Compress: true}
|
||||||
if err := msg.Unpack(packet); err != nil {
|
if err := msg.Unpack(packet); err != nil {
|
||||||
if len(packet) >= MinDNSPacketSize && HasTCFlag(packet) {
|
if len(packet) >= MinDNSPacketSize && HasTCFlag(packet) {
|
||||||
|
@ -336,7 +358,13 @@ func (pluginsState *PluginsState) ApplyResponsePlugins(pluginsGlobals *PluginsGl
|
||||||
return packet, err
|
return packet, err
|
||||||
}
|
}
|
||||||
if pluginsState.action == PluginsActionReject {
|
if pluginsState.action == PluginsActionReject {
|
||||||
synth := RefusedResponseFromMessage(&msg, pluginsGlobals.refusedCodeInResponses, pluginsGlobals.respondWithIPv4, pluginsGlobals.respondWithIPv6, pluginsState.rejectTTL)
|
synth := RefusedResponseFromMessage(
|
||||||
|
&msg,
|
||||||
|
pluginsGlobals.refusedCodeInResponses,
|
||||||
|
pluginsGlobals.respondWithIPv4,
|
||||||
|
pluginsGlobals.respondWithIPv6,
|
||||||
|
pluginsState.rejectTTL,
|
||||||
|
)
|
||||||
pluginsState.synthResponse = synth
|
pluginsState.synthResponse = synth
|
||||||
}
|
}
|
||||||
if pluginsState.action != PluginsActionContinue {
|
if pluginsState.action != PluginsActionContinue {
|
||||||
|
|
|
@ -25,9 +25,19 @@ func (proxy *Proxy) dropPrivilege(userStr string, fds []*os.File) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
uid, err2 := strconv.Atoi(userStr)
|
uid, err2 := strconv.Atoi(userStr)
|
||||||
if err2 != nil || uid <= 0 {
|
if err2 != nil || uid <= 0 {
|
||||||
dlog.Fatalf("Unable to retrieve any information about user [%s]: [%s] - Remove the user_name directive from the configuration file in order to avoid identity switch", userStr, err)
|
dlog.Fatalf(
|
||||||
|
"Unable to retrieve any information about user [%s]: [%s] - Remove the user_name directive from the configuration file in order to avoid identity switch",
|
||||||
|
userStr,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
dlog.Warnf("Unable to retrieve any information about user [%s]: [%s] - Switching to user id [%v] with the same group id, as [%v] looks like a user id. But you should remove or fix the user_name directive in the configuration file if possible", userStr, err, uid, uid)
|
dlog.Warnf(
|
||||||
|
"Unable to retrieve any information about user [%s]: [%s] - Switching to user id [%v] with the same group id, as [%v] looks like a user id. But you should remove or fix the user_name directive in the configuration file if possible",
|
||||||
|
userStr,
|
||||||
|
err,
|
||||||
|
uid,
|
||||||
|
uid,
|
||||||
|
)
|
||||||
userInfo = &user.User{Uid: userStr, Gid: userStr}
|
userInfo = &user.User{Uid: userStr, Gid: userStr}
|
||||||
}
|
}
|
||||||
uid, err := strconv.Atoi(userInfo.Uid)
|
uid, err := strconv.Atoi(userInfo.Uid)
|
||||||
|
|
|
@ -27,9 +27,19 @@ func (proxy *Proxy) dropPrivilege(userStr string, fds []*os.File) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
uid, err2 := strconv.Atoi(userStr)
|
uid, err2 := strconv.Atoi(userStr)
|
||||||
if err2 != nil || uid <= 0 {
|
if err2 != nil || uid <= 0 {
|
||||||
dlog.Fatalf("Unable to retrieve any information about user [%s]: [%s] - Remove the user_name directive from the configuration file in order to avoid identity switch", userStr, err)
|
dlog.Fatalf(
|
||||||
|
"Unable to retrieve any information about user [%s]: [%s] - Remove the user_name directive from the configuration file in order to avoid identity switch",
|
||||||
|
userStr,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
dlog.Warnf("Unable to retrieve any information about user [%s]: [%s] - Switching to user id [%v] with the same group id, as [%v] looks like a user id. But you should remove or fix the user_name directive in the configuration file if possible", userStr, err, uid, uid)
|
dlog.Warnf(
|
||||||
|
"Unable to retrieve any information about user [%s]: [%s] - Switching to user id [%v] with the same group id, as [%v] looks like a user id. But you should remove or fix the user_name directive in the configuration file if possible",
|
||||||
|
userStr,
|
||||||
|
err,
|
||||||
|
uid,
|
||||||
|
uid,
|
||||||
|
)
|
||||||
userInfo = &user.User{Uid: userStr, Gid: userStr}
|
userInfo = &user.User{Uid: userStr, Gid: userStr}
|
||||||
}
|
}
|
||||||
uid, err := strconv.Atoi(userInfo.Uid)
|
uid, err := strconv.Atoi(userInfo.Uid)
|
||||||
|
|
|
@ -284,10 +284,16 @@ func (proxy *Proxy) updateRegisteredServers() error {
|
||||||
dlog.Criticalf("Unable to use source [%s]: [%s]", source.name, err)
|
dlog.Criticalf("Unable to use source [%s]: [%s]", source.name, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dlog.Warnf("Error in source [%s]: [%s] -- Continuing with reduced server count [%d]", source.name, err, len(registeredServers))
|
dlog.Warnf(
|
||||||
|
"Error in source [%s]: [%s] -- Continuing with reduced server count [%d]",
|
||||||
|
source.name,
|
||||||
|
err,
|
||||||
|
len(registeredServers),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
for _, registeredServer := range registeredServers {
|
for _, registeredServer := range registeredServers {
|
||||||
if registeredServer.stamp.Proto != stamps.StampProtoTypeDNSCryptRelay && registeredServer.stamp.Proto != stamps.StampProtoTypeODoHRelay {
|
if registeredServer.stamp.Proto != stamps.StampProtoTypeDNSCryptRelay &&
|
||||||
|
registeredServer.stamp.Proto != stamps.StampProtoTypeODoHRelay {
|
||||||
if len(proxy.ServerNames) > 0 {
|
if len(proxy.ServerNames) > 0 {
|
||||||
if !includesName(proxy.ServerNames, registeredServer.name) {
|
if !includesName(proxy.ServerNames, registeredServer.name) {
|
||||||
continue
|
continue
|
||||||
|
@ -311,13 +317,19 @@ func (proxy *Proxy) updateRegisteredServers() error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if registeredServer.stamp.Proto == stamps.StampProtoTypeDNSCryptRelay || registeredServer.stamp.Proto == stamps.StampProtoTypeODoHRelay {
|
if registeredServer.stamp.Proto == stamps.StampProtoTypeDNSCryptRelay ||
|
||||||
|
registeredServer.stamp.Proto == stamps.StampProtoTypeODoHRelay {
|
||||||
var found bool
|
var found bool
|
||||||
for i, currentRegisteredRelay := range proxy.registeredRelays {
|
for i, currentRegisteredRelay := range proxy.registeredRelays {
|
||||||
if currentRegisteredRelay.name == registeredServer.name {
|
if currentRegisteredRelay.name == registeredServer.name {
|
||||||
found = true
|
found = true
|
||||||
if currentRegisteredRelay.stamp.String() != registeredServer.stamp.String() {
|
if currentRegisteredRelay.stamp.String() != registeredServer.stamp.String() {
|
||||||
dlog.Infof("Updating stamp for [%s] was: %s now: %s", registeredServer.name, currentRegisteredRelay.stamp.String(), registeredServer.stamp.String())
|
dlog.Infof(
|
||||||
|
"Updating stamp for [%s] was: %s now: %s",
|
||||||
|
registeredServer.name,
|
||||||
|
currentRegisteredRelay.stamp.String(),
|
||||||
|
registeredServer.stamp.String(),
|
||||||
|
)
|
||||||
proxy.registeredRelays[i].stamp = registeredServer.stamp
|
proxy.registeredRelays[i].stamp = registeredServer.stamp
|
||||||
dlog.Debugf("Total count of registered relays %v", len(proxy.registeredRelays))
|
dlog.Debugf("Total count of registered relays %v", len(proxy.registeredRelays))
|
||||||
}
|
}
|
||||||
|
@ -371,7 +383,15 @@ func (proxy *Proxy) udpListener(clientPc *net.UDPConn) {
|
||||||
packet := buffer[:length]
|
packet := buffer[:length]
|
||||||
if !proxy.clientsCountInc() {
|
if !proxy.clientsCountInc() {
|
||||||
dlog.Warnf("Too many incoming connections (max=%d)", proxy.maxClients)
|
dlog.Warnf("Too many incoming connections (max=%d)", proxy.maxClients)
|
||||||
proxy.processIncomingQuery("udp", proxy.mainProto, packet, &clientAddr, clientPc, time.Now(), true) // respond synchronously, but only to cached/synthesized queries
|
proxy.processIncomingQuery(
|
||||||
|
"udp",
|
||||||
|
proxy.mainProto,
|
||||||
|
packet,
|
||||||
|
&clientAddr,
|
||||||
|
clientPc,
|
||||||
|
time.Now(),
|
||||||
|
true,
|
||||||
|
) // respond synchronously, but only to cached/synthesized queries
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -477,7 +497,12 @@ func (proxy *Proxy) prepareForRelay(ip net.IP, port int, encryptedQuery *[]byte)
|
||||||
*encryptedQuery = relayedQuery
|
*encryptedQuery = relayedQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) exchangeWithUDPServer(serverInfo *ServerInfo, sharedKey *[32]byte, encryptedQuery []byte, clientNonce []byte) ([]byte, error) {
|
func (proxy *Proxy) exchangeWithUDPServer(
|
||||||
|
serverInfo *ServerInfo,
|
||||||
|
sharedKey *[32]byte,
|
||||||
|
encryptedQuery []byte,
|
||||||
|
clientNonce []byte,
|
||||||
|
) ([]byte, error) {
|
||||||
upstreamAddr := serverInfo.UDPAddr
|
upstreamAddr := serverInfo.UDPAddr
|
||||||
if serverInfo.Relay != nil && serverInfo.Relay.Dnscrypt != nil {
|
if serverInfo.Relay != nil && serverInfo.Relay.Dnscrypt != nil {
|
||||||
upstreamAddr = serverInfo.Relay.Dnscrypt.RelayUDPAddr
|
upstreamAddr = serverInfo.Relay.Dnscrypt.RelayUDPAddr
|
||||||
|
@ -515,7 +540,12 @@ func (proxy *Proxy) exchangeWithUDPServer(serverInfo *ServerInfo, sharedKey *[32
|
||||||
return proxy.Decrypt(serverInfo, sharedKey, encryptedResponse, clientNonce)
|
return proxy.Decrypt(serverInfo, sharedKey, encryptedResponse, clientNonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) exchangeWithTCPServer(serverInfo *ServerInfo, sharedKey *[32]byte, encryptedQuery []byte, clientNonce []byte) ([]byte, error) {
|
func (proxy *Proxy) exchangeWithTCPServer(
|
||||||
|
serverInfo *ServerInfo,
|
||||||
|
sharedKey *[32]byte,
|
||||||
|
encryptedQuery []byte,
|
||||||
|
clientNonce []byte,
|
||||||
|
) ([]byte, error) {
|
||||||
upstreamAddr := serverInfo.TCPAddr
|
upstreamAddr := serverInfo.TCPAddr
|
||||||
if serverInfo.Relay != nil && serverInfo.Relay.Dnscrypt != nil {
|
if serverInfo.Relay != nil && serverInfo.Relay.Dnscrypt != nil {
|
||||||
upstreamAddr = serverInfo.Relay.Dnscrypt.RelayTCPAddr
|
upstreamAddr = serverInfo.Relay.Dnscrypt.RelayTCPAddr
|
||||||
|
@ -567,13 +597,22 @@ func (proxy *Proxy) clientsCountInc() bool {
|
||||||
|
|
||||||
func (proxy *Proxy) clientsCountDec() {
|
func (proxy *Proxy) clientsCountDec() {
|
||||||
for {
|
for {
|
||||||
if count := atomic.LoadUint32(&proxy.clientsCount); count == 0 || atomic.CompareAndSwapUint32(&proxy.clientsCount, count, count-1) {
|
if count := atomic.LoadUint32(&proxy.clientsCount); count == 0 ||
|
||||||
|
atomic.CompareAndSwapUint32(&proxy.clientsCount, count, count-1) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) processIncomingQuery(clientProto string, serverProto string, query []byte, clientAddr *net.Addr, clientPc net.Conn, start time.Time, onlyCached bool) []byte {
|
func (proxy *Proxy) processIncomingQuery(
|
||||||
|
clientProto string,
|
||||||
|
serverProto string,
|
||||||
|
query []byte,
|
||||||
|
clientAddr *net.Addr,
|
||||||
|
clientPc net.Conn,
|
||||||
|
start time.Time,
|
||||||
|
onlyCached bool,
|
||||||
|
) []byte {
|
||||||
var response []byte = nil
|
var response []byte = nil
|
||||||
if len(query) < MinDNSPacketSize {
|
if len(query) < MinDNSPacketSize {
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -147,7 +147,12 @@ type ServersInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServersInfo() ServersInfo {
|
func NewServersInfo() ServersInfo {
|
||||||
return ServersInfo{lbStrategy: DefaultLBStrategy, lbEstimator: true, registeredServers: make([]RegisteredServer, 0), registeredRelays: make([]RegisteredServer, 0)}
|
return ServersInfo{
|
||||||
|
lbStrategy: DefaultLBStrategy,
|
||||||
|
lbEstimator: true,
|
||||||
|
registeredServers: make([]RegisteredServer, 0),
|
||||||
|
registeredRelays: make([]RegisteredServer, 0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (serversInfo *ServersInfo) registerServer(name string, stamp stamps.ServerStamp) {
|
func (serversInfo *ServersInfo) registerServer(name string, stamp stamps.ServerStamp) {
|
||||||
|
@ -262,7 +267,12 @@ func (serversInfo *ServersInfo) estimatorUpdate() {
|
||||||
partialSort := false
|
partialSort := false
|
||||||
if candidateRtt < currentActiveRtt {
|
if candidateRtt < currentActiveRtt {
|
||||||
serversInfo.inner[candidate], serversInfo.inner[currentActive] = serversInfo.inner[currentActive], serversInfo.inner[candidate]
|
serversInfo.inner[candidate], serversInfo.inner[currentActive] = serversInfo.inner[currentActive], serversInfo.inner[candidate]
|
||||||
dlog.Debugf("New preferred candidate: %s (RTT: %d vs previous: %d)", serversInfo.inner[currentActive].Name, int(candidateRtt), int(currentActiveRtt))
|
dlog.Debugf(
|
||||||
|
"New preferred candidate: %s (RTT: %d vs previous: %d)",
|
||||||
|
serversInfo.inner[currentActive].Name,
|
||||||
|
int(candidateRtt),
|
||||||
|
int(currentActiveRtt),
|
||||||
|
)
|
||||||
partialSort = true
|
partialSort = true
|
||||||
} else if candidateRtt > 0 && candidateRtt >= (serversInfo.inner[0].rtt.Value()+serversInfo.inner[activeCount-1].rtt.Value())/2.0*4.0 {
|
} else if candidateRtt > 0 && candidateRtt >= (serversInfo.inner[0].rtt.Value()+serversInfo.inner[activeCount-1].rtt.Value())/2.0*4.0 {
|
||||||
if time.Since(serversInfo.inner[candidate].lastActionTS) > time.Duration(1*time.Minute) {
|
if time.Since(serversInfo.inner[candidate].lastActionTS) > time.Duration(1*time.Minute) {
|
||||||
|
@ -462,7 +472,8 @@ func route(proxy *Proxy, name string, serverProto stamps.StampProtoType) (*Relay
|
||||||
relayName := relayCandidateStamp.ServerAddrStr
|
relayName := relayCandidateStamp.ServerAddrStr
|
||||||
proxy.serversInfo.RLock()
|
proxy.serversInfo.RLock()
|
||||||
for _, registeredServer := range proxy.serversInfo.registeredRelays {
|
for _, registeredServer := range proxy.serversInfo.registeredRelays {
|
||||||
if registeredServer.stamp.Proto == relayProto && registeredServer.stamp.ServerAddrStr == relayCandidateStamp.ServerAddrStr {
|
if registeredServer.stamp.Proto == relayProto &&
|
||||||
|
registeredServer.stamp.ServerAddrStr == relayCandidateStamp.ServerAddrStr {
|
||||||
relayName = registeredServer.name
|
relayName = registeredServer.name
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -479,9 +490,14 @@ func route(proxy *Proxy, name string, serverProto stamps.StampProtoType) (*Relay
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dlog.Noticef("Anonymizing queries for [%v] via [%v]", name, relayName)
|
dlog.Noticef("Anonymizing queries for [%v] via [%v]", name, relayName)
|
||||||
return &Relay{Proto: stamps.StampProtoTypeDNSCryptRelay, Dnscrypt: &DNSCryptRelay{RelayUDPAddr: relayUDPAddr, RelayTCPAddr: relayTCPAddr}}, nil
|
return &Relay{
|
||||||
|
Proto: stamps.StampProtoTypeDNSCryptRelay,
|
||||||
|
Dnscrypt: &DNSCryptRelay{RelayUDPAddr: relayUDPAddr, RelayTCPAddr: relayTCPAddr},
|
||||||
|
}, nil
|
||||||
case stamps.StampProtoTypeODoHRelay:
|
case stamps.StampProtoTypeODoHRelay:
|
||||||
relayBaseURL, err := url.Parse("https://" + url.PathEscape(relayCandidateStamp.ProviderName) + relayCandidateStamp.Path)
|
relayBaseURL, err := url.Parse(
|
||||||
|
"https://" + url.PathEscape(relayCandidateStamp.ProviderName) + relayCandidateStamp.Path,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -541,7 +557,17 @@ func fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp
|
||||||
if relay != nil {
|
if relay != nil {
|
||||||
dnscryptRelay = relay.Dnscrypt
|
dnscryptRelay = relay.Dnscrypt
|
||||||
}
|
}
|
||||||
certInfo, rtt, fragmentsBlocked, err := FetchCurrentDNSCryptCert(proxy, &name, proxy.mainProto, stamp.ServerPk, stamp.ServerAddrStr, stamp.ProviderName, isNew, dnscryptRelay, knownBugs)
|
certInfo, rtt, fragmentsBlocked, err := FetchCurrentDNSCryptCert(
|
||||||
|
proxy,
|
||||||
|
&name,
|
||||||
|
proxy.mainProto,
|
||||||
|
stamp.ServerPk,
|
||||||
|
stamp.ServerAddrStr,
|
||||||
|
stamp.ProviderName,
|
||||||
|
isNew,
|
||||||
|
dnscryptRelay,
|
||||||
|
knownBugs,
|
||||||
|
)
|
||||||
if !knownBugs.fragmentsBlocked && fragmentsBlocked {
|
if !knownBugs.fragmentsBlocked && fragmentsBlocked {
|
||||||
dlog.Debugf("[%v] drops fragmented queries", name)
|
dlog.Debugf("[%v] drops fragmented queries", name)
|
||||||
knownBugs.fragmentsBlocked = true
|
knownBugs.fragmentsBlocked = true
|
||||||
|
@ -750,7 +776,10 @@ func _fetchODoHTargetInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, i
|
||||||
}
|
}
|
||||||
|
|
||||||
if relay == nil {
|
if relay == nil {
|
||||||
dlog.Criticalf("No relay defined for [%v] - Configuring a relay is required for ODoH servers (see the `[anonymized_dns]` section)", name)
|
dlog.Criticalf(
|
||||||
|
"No relay defined for [%v] - Configuring a relay is required for ODoH servers (see the `[anonymized_dns]` section)",
|
||||||
|
name,
|
||||||
|
)
|
||||||
return ServerInfo{}, errors.New("No ODoH relay")
|
return ServerInfo{}, errors.New("No ODoH relay")
|
||||||
} else {
|
} else {
|
||||||
if relay.ODoH == nil {
|
if relay.ODoH == nil {
|
||||||
|
@ -798,7 +827,12 @@ func _fetchODoHTargetInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, i
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
responseBody, responseCode, tls, rtt, err := proxy.xTransport.ObliviousDoHQuery(useGet, url, odohQuery.odohMessage, proxy.timeout)
|
responseBody, responseCode, tls, rtt, err := proxy.xTransport.ObliviousDoHQuery(
|
||||||
|
useGet,
|
||||||
|
url,
|
||||||
|
odohQuery.odohMessage,
|
||||||
|
proxy.timeout,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -828,7 +862,13 @@ func _fetchODoHTargetInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, i
|
||||||
if strings.HasPrefix(protocol, "http/1.") {
|
if strings.HasPrefix(protocol, "http/1.") {
|
||||||
dlog.Warnf("[%s] does not support HTTP/2", name)
|
dlog.Warnf("[%s] does not support HTTP/2", name)
|
||||||
}
|
}
|
||||||
dlog.Infof("[%s] TLS version: %x - Protocol: %v - Cipher suite: %v", name, tls.Version, protocol, tls.CipherSuite)
|
dlog.Infof(
|
||||||
|
"[%s] TLS version: %x - Protocol: %v - Cipher suite: %v",
|
||||||
|
name,
|
||||||
|
tls.Version,
|
||||||
|
protocol,
|
||||||
|
tls.CipherSuite,
|
||||||
|
)
|
||||||
showCerts := proxy.showCerts
|
showCerts := proxy.showCerts
|
||||||
found := false
|
found := false
|
||||||
var wantedHash [32]byte
|
var wantedHash [32]byte
|
||||||
|
|
|
@ -12,7 +12,12 @@ func (proxy *Proxy) udpListenerConfig() (*net.ListenConfig, error) {
|
||||||
_ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_FREEBIND, 1)
|
_ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_FREEBIND, 1)
|
||||||
_ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_DF, 0)
|
_ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_DF, 0)
|
||||||
_ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TOS, 0x70)
|
_ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TOS, 0x70)
|
||||||
_ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_MTU_DISCOVER, syscall.IP_PMTUDISC_DONT)
|
_ = syscall.SetsockoptInt(
|
||||||
|
int(fd),
|
||||||
|
syscall.IPPROTO_IP,
|
||||||
|
syscall.IP_MTU_DISCOVER,
|
||||||
|
syscall.IP_PMTUDISC_DONT,
|
||||||
|
)
|
||||||
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUFFORCE, 4096)
|
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUFFORCE, 4096)
|
||||||
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUFFORCE, 4096)
|
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUFFORCE, 4096)
|
||||||
})
|
})
|
||||||
|
|
|
@ -180,11 +180,27 @@ func (source *Source) fetchWithCache(xTransport *XTransport, now time.Time) (del
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSource loads a new source using the given cacheFile and urls, ensuring it has a valid signature
|
// NewSource loads a new source using the given cacheFile and urls, ensuring it has a valid signature
|
||||||
func NewSource(name string, xTransport *XTransport, urls []string, minisignKeyStr string, cacheFile string, formatStr string, refreshDelay time.Duration, prefix string) (source *Source, err error) {
|
func NewSource(
|
||||||
|
name string,
|
||||||
|
xTransport *XTransport,
|
||||||
|
urls []string,
|
||||||
|
minisignKeyStr string,
|
||||||
|
cacheFile string,
|
||||||
|
formatStr string,
|
||||||
|
refreshDelay time.Duration,
|
||||||
|
prefix string,
|
||||||
|
) (source *Source, err error) {
|
||||||
if refreshDelay < DefaultPrefetchDelay {
|
if refreshDelay < DefaultPrefetchDelay {
|
||||||
refreshDelay = DefaultPrefetchDelay
|
refreshDelay = DefaultPrefetchDelay
|
||||||
}
|
}
|
||||||
source = &Source{name: name, urls: []*url.URL{}, cacheFile: cacheFile, cacheTTL: refreshDelay, prefetchDelay: DefaultPrefetchDelay, prefix: prefix}
|
source = &Source{
|
||||||
|
name: name,
|
||||||
|
urls: []*url.URL{},
|
||||||
|
cacheFile: cacheFile,
|
||||||
|
cacheTTL: refreshDelay,
|
||||||
|
prefetchDelay: DefaultPrefetchDelay,
|
||||||
|
prefix: prefix,
|
||||||
|
}
|
||||||
if formatStr == "v2" {
|
if formatStr == "v2" {
|
||||||
source.format = SourceFormatV2
|
source.format = SourceFormatV2
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -296,7 +296,13 @@ func prepSourceTestCache(t *testing.T, d *SourceTestData, e *SourceTestExpect, s
|
||||||
writeSourceCache(t, e)
|
writeSourceCache(t, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepSourceTestDownload(t *testing.T, d *SourceTestData, e *SourceTestExpect, source string, downloadTest []SourceTestState) {
|
func prepSourceTestDownload(
|
||||||
|
t *testing.T,
|
||||||
|
d *SourceTestData,
|
||||||
|
e *SourceTestExpect,
|
||||||
|
source string,
|
||||||
|
downloadTest []SourceTestState,
|
||||||
|
) {
|
||||||
if len(downloadTest) == 0 {
|
if len(downloadTest) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -313,7 +319,11 @@ func prepSourceTestDownload(t *testing.T, d *SourceTestData, e *SourceTestExpect
|
||||||
case TestStateOpenErr, TestStateOpenSigErr:
|
case TestStateOpenErr, TestStateOpenSigErr:
|
||||||
if u, err := url.Parse(serverURL + path); err == nil {
|
if u, err := url.Parse(serverURL + path); err == nil {
|
||||||
host, port := ExtractHostAndPort(u.Host, -1)
|
host, port := ExtractHostAndPort(u.Host, -1)
|
||||||
u.Host = fmt.Sprintf("%s:%d", host, port|0x10000) // high numeric port is parsed but then fails to connect
|
u.Host = fmt.Sprintf(
|
||||||
|
"%s:%d",
|
||||||
|
host,
|
||||||
|
port|0x10000,
|
||||||
|
) // high numeric port is parsed but then fails to connect
|
||||||
serverURL = u.String()
|
serverURL = u.String()
|
||||||
}
|
}
|
||||||
e.err = "invalid port"
|
e.err = "invalid port"
|
||||||
|
@ -394,7 +404,16 @@ func TestNewSource(t *testing.T) {
|
||||||
{"v2", "", DefaultPrefetchDelay * 3, &SourceTestExpect{err: "Invalid encoded public key", Source: &Source{name: "invalid public key", urls: []*url.URL{}, cacheTTL: DefaultPrefetchDelay * 3, prefetchDelay: DefaultPrefetchDelay}}},
|
{"v2", "", DefaultPrefetchDelay * 3, &SourceTestExpect{err: "Invalid encoded public key", Source: &Source{name: "invalid public key", urls: []*url.URL{}, cacheTTL: DefaultPrefetchDelay * 3, prefetchDelay: DefaultPrefetchDelay}}},
|
||||||
} {
|
} {
|
||||||
t.Run(tt.e.Source.name, func(t *testing.T) {
|
t.Run(tt.e.Source.name, func(t *testing.T) {
|
||||||
got, err := NewSource(tt.e.Source.name, d.xTransport, tt.e.urls, tt.key, tt.e.cachePath, tt.v, tt.refreshDelay, tt.e.prefix)
|
got, err := NewSource(
|
||||||
|
tt.e.Source.name,
|
||||||
|
d.xTransport,
|
||||||
|
tt.e.urls,
|
||||||
|
tt.key,
|
||||||
|
tt.e.cachePath,
|
||||||
|
tt.v,
|
||||||
|
tt.refreshDelay,
|
||||||
|
tt.e.prefix,
|
||||||
|
)
|
||||||
checkResult(t, tt.e, got, err)
|
checkResult(t, tt.e, got, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -404,7 +423,16 @@ func TestNewSource(t *testing.T) {
|
||||||
for i := range d.sources {
|
for i := range d.sources {
|
||||||
id, e := setupSourceTestCase(t, d, i, &cacheTest, downloadTest)
|
id, e := setupSourceTestCase(t, d, i, &cacheTest, downloadTest)
|
||||||
t.Run("cache "+cacheTestName+", download "+downloadTestName+"/"+id, func(t *testing.T) {
|
t.Run("cache "+cacheTestName+", download "+downloadTestName+"/"+id, func(t *testing.T) {
|
||||||
got, err := NewSource(id, d.xTransport, e.urls, d.keyStr, e.cachePath, "v2", DefaultPrefetchDelay*3, "")
|
got, err := NewSource(
|
||||||
|
id,
|
||||||
|
d.xTransport,
|
||||||
|
e.urls,
|
||||||
|
d.keyStr,
|
||||||
|
e.cachePath,
|
||||||
|
"v2",
|
||||||
|
DefaultPrefetchDelay*3,
|
||||||
|
"",
|
||||||
|
)
|
||||||
checkResult(t, e, got, err)
|
checkResult(t, e, got, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,9 @@ func (proxy *Proxy) addSystemDListeners() error {
|
||||||
|
|
||||||
if len(files) > 0 {
|
if len(files) > 0 {
|
||||||
if len(proxy.userName) > 0 || proxy.child {
|
if len(proxy.userName) > 0 || proxy.child {
|
||||||
dlog.Fatal("Systemd activated sockets are incompatible with privilege dropping. Remove activated sockets and fill `listen_addresses` in the dnscrypt-proxy configuration file instead.")
|
dlog.Fatal(
|
||||||
|
"Systemd activated sockets are incompatible with privilege dropping. Remove activated sockets and fill `listen_addresses` in the dnscrypt-proxy configuration file instead.",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
dlog.Warn("Systemd sockets are untested and unsupported - use at your own risk")
|
dlog.Warn("Systemd sockets are untested and unsupported - use at your own risk")
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,15 @@ func parseTimeRanges(timeRangesStr []TimeRangeStr) ([]TimeRange, error) {
|
||||||
|
|
||||||
func parseWeeklyRanges(weeklyRangesStr WeeklyRangesStr) (WeeklyRanges, error) {
|
func parseWeeklyRanges(weeklyRangesStr WeeklyRangesStr) (WeeklyRanges, error) {
|
||||||
weeklyRanges := WeeklyRanges{}
|
weeklyRanges := WeeklyRanges{}
|
||||||
weeklyRangesStrX := [7][]TimeRangeStr{weeklyRangesStr.Sun, weeklyRangesStr.Mon, weeklyRangesStr.Tue, weeklyRangesStr.Wed, weeklyRangesStr.Thu, weeklyRangesStr.Fri, weeklyRangesStr.Sat}
|
weeklyRangesStrX := [7][]TimeRangeStr{
|
||||||
|
weeklyRangesStr.Sun,
|
||||||
|
weeklyRangesStr.Mon,
|
||||||
|
weeklyRangesStr.Tue,
|
||||||
|
weeklyRangesStr.Wed,
|
||||||
|
weeklyRangesStr.Thu,
|
||||||
|
weeklyRangesStr.Fri,
|
||||||
|
weeklyRangesStr.Sat,
|
||||||
|
}
|
||||||
for day, weeklyRangeStrX := range weeklyRangesStrX {
|
for day, weeklyRangeStrX := range weeklyRangesStrX {
|
||||||
timeRanges, err := parseTimeRanges(weeklyRangeStrX)
|
timeRanges, err := parseTimeRanges(weeklyRangeStrX)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -187,7 +187,12 @@ func (xTransport *XTransport) rebuildTransport() {
|
||||||
if clientCreds.clientCert != "" {
|
if clientCreds.clientCert != "" {
|
||||||
cert, err := tls.LoadX509KeyPair(clientCreds.clientCert, clientCreds.clientKey)
|
cert, err := tls.LoadX509KeyPair(clientCreds.clientCert, clientCreds.clientKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dlog.Fatalf("Unable to use certificate [%v] (key: [%v]): %v", clientCreds.clientCert, clientCreds.clientKey, err)
|
dlog.Fatalf(
|
||||||
|
"Unable to use certificate [%v] (key: [%v]): %v",
|
||||||
|
clientCreds.clientCert,
|
||||||
|
clientCreds.clientKey,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
tlsClientConfig.Certificates = []tls.Certificate{cert}
|
tlsClientConfig.Certificates = []tls.Certificate{cert}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +243,10 @@ func (xTransport *XTransport) resolveUsingSystem(host string) (ip net.IP, ttl ti
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (xTransport *XTransport) resolveUsingResolver(proto, host string, resolver string) (ip net.IP, ttl time.Duration, err error) {
|
func (xTransport *XTransport) resolveUsingResolver(
|
||||||
|
proto, host string,
|
||||||
|
resolver string,
|
||||||
|
) (ip net.IP, ttl time.Duration, err error) {
|
||||||
dnsClient := dns.Client{Net: proto}
|
dnsClient := dns.Client{Net: proto}
|
||||||
if xTransport.useIPv4 {
|
if xTransport.useIPv4 {
|
||||||
msg := dns.Msg{}
|
msg := dns.Msg{}
|
||||||
|
@ -283,7 +291,10 @@ func (xTransport *XTransport) resolveUsingResolver(proto, host string, resolver
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (xTransport *XTransport) resolveUsingResolvers(proto, host string, resolvers []string) (ip net.IP, ttl time.Duration, err error) {
|
func (xTransport *XTransport) resolveUsingResolvers(
|
||||||
|
proto, host string,
|
||||||
|
resolvers []string,
|
||||||
|
) (ip net.IP, ttl time.Duration, err error) {
|
||||||
for i, resolver := range resolvers {
|
for i, resolver := range resolvers {
|
||||||
ip, ttl, err = xTransport.resolveUsingResolver(proto, host, resolver)
|
ip, ttl, err = xTransport.resolveUsingResolver(proto, host, resolver)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -323,7 +334,11 @@ func (xTransport *XTransport) resolveAndUpdateCache(host string) error {
|
||||||
}
|
}
|
||||||
for _, proto := range protos {
|
for _, proto := range protos {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dlog.Noticef("System DNS configuration not usable yet, exceptionally resolving [%s] using bootstrap resolvers over %s", host, proto)
|
dlog.Noticef(
|
||||||
|
"System DNS configuration not usable yet, exceptionally resolving [%s] using bootstrap resolvers over %s",
|
||||||
|
host,
|
||||||
|
proto,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
dlog.Debugf("Resolving [%s] using bootstrap resolvers over %s", host, proto)
|
dlog.Debugf("Resolving [%s] using bootstrap resolvers over %s", host, proto)
|
||||||
}
|
}
|
||||||
|
@ -354,7 +369,14 @@ func (xTransport *XTransport) resolveAndUpdateCache(host string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string, contentType string, body *[]byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
func (xTransport *XTransport) Fetch(
|
||||||
|
method string,
|
||||||
|
url *url.URL,
|
||||||
|
accept string,
|
||||||
|
contentType string,
|
||||||
|
body *[]byte,
|
||||||
|
timeout time.Duration,
|
||||||
|
) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||||
if timeout <= 0 {
|
if timeout <= 0 {
|
||||||
timeout = xTransport.timeout
|
timeout = xTransport.timeout
|
||||||
}
|
}
|
||||||
|
@ -380,7 +402,10 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
|
||||||
return nil, 0, nil, 0, errors.New("Onion service is not reachable without Tor")
|
return nil, 0, nil, 0, errors.New("Onion service is not reachable without Tor")
|
||||||
}
|
}
|
||||||
if err := xTransport.resolveAndUpdateCache(host); err != nil {
|
if err := xTransport.resolveAndUpdateCache(host); err != nil {
|
||||||
dlog.Errorf("Unable to resolve [%v] - Make sure that the system resolver works, or that `bootstrap_resolvers` has been set to resolvers that can be reached", host)
|
dlog.Errorf(
|
||||||
|
"Unable to resolve [%v] - Make sure that the system resolver works, or that `bootstrap_resolvers` has been set to resolvers that can be reached",
|
||||||
|
host,
|
||||||
|
)
|
||||||
return nil, 0, nil, 0, err
|
return nil, 0, nil, 0, err
|
||||||
}
|
}
|
||||||
req := &http.Request{
|
req := &http.Request{
|
||||||
|
@ -412,7 +437,9 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dlog.Debugf("[%s]: [%s]", req.URL, err)
|
dlog.Debugf("[%s]: [%s]", req.URL, err)
|
||||||
if xTransport.tlsCipherSuite != nil && strings.Contains(err.Error(), "handshake failure") {
|
if xTransport.tlsCipherSuite != nil && strings.Contains(err.Error(), "handshake failure") {
|
||||||
dlog.Warnf("TLS handshake failure - Try changing or deleting the tls_cipher_suite value in the configuration file")
|
dlog.Warnf(
|
||||||
|
"TLS handshake failure - Try changing or deleting the tls_cipher_suite value in the configuration file",
|
||||||
|
)
|
||||||
xTransport.tlsCipherSuite = nil
|
xTransport.tlsCipherSuite = nil
|
||||||
xTransport.rebuildTransport()
|
xTransport.rebuildTransport()
|
||||||
}
|
}
|
||||||
|
@ -427,15 +454,31 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
|
||||||
return bin, statusCode, tls, rtt, err
|
return bin, statusCode, tls, rtt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (xTransport *XTransport) Get(url *url.URL, accept string, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
func (xTransport *XTransport) Get(
|
||||||
|
url *url.URL,
|
||||||
|
accept string,
|
||||||
|
timeout time.Duration,
|
||||||
|
) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||||
return xTransport.Fetch("GET", url, accept, "", nil, timeout)
|
return xTransport.Fetch("GET", url, accept, "", nil, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (xTransport *XTransport) Post(url *url.URL, accept string, contentType string, body *[]byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
func (xTransport *XTransport) Post(
|
||||||
|
url *url.URL,
|
||||||
|
accept string,
|
||||||
|
contentType string,
|
||||||
|
body *[]byte,
|
||||||
|
timeout time.Duration,
|
||||||
|
) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||||
return xTransport.Fetch("POST", url, accept, contentType, body, timeout)
|
return xTransport.Fetch("POST", url, accept, contentType, body, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (xTransport *XTransport) dohLikeQuery(dataType string, useGet bool, url *url.URL, body []byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
func (xTransport *XTransport) dohLikeQuery(
|
||||||
|
dataType string,
|
||||||
|
useGet bool,
|
||||||
|
url *url.URL,
|
||||||
|
body []byte,
|
||||||
|
timeout time.Duration,
|
||||||
|
) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||||
if useGet {
|
if useGet {
|
||||||
qs := url.Query()
|
qs := url.Query()
|
||||||
encBody := base64.RawURLEncoding.EncodeToString(body)
|
encBody := base64.RawURLEncoding.EncodeToString(body)
|
||||||
|
@ -447,10 +490,20 @@ func (xTransport *XTransport) dohLikeQuery(dataType string, useGet bool, url *ur
|
||||||
return xTransport.Post(url, dataType, dataType, &body, timeout)
|
return xTransport.Post(url, dataType, dataType, &body, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (xTransport *XTransport) DoHQuery(useGet bool, url *url.URL, body []byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
func (xTransport *XTransport) DoHQuery(
|
||||||
|
useGet bool,
|
||||||
|
url *url.URL,
|
||||||
|
body []byte,
|
||||||
|
timeout time.Duration,
|
||||||
|
) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||||
return xTransport.dohLikeQuery("application/dns-message", useGet, url, body, timeout)
|
return xTransport.dohLikeQuery("application/dns-message", useGet, url, body, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (xTransport *XTransport) ObliviousDoHQuery(useGet bool, url *url.URL, body []byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
func (xTransport *XTransport) ObliviousDoHQuery(
|
||||||
|
useGet bool,
|
||||||
|
url *url.URL,
|
||||||
|
body []byte,
|
||||||
|
timeout time.Duration,
|
||||||
|
) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||||
return xTransport.dohLikeQuery("application/oblivious-dns-message", useGet, url, body, timeout)
|
return xTransport.dohLikeQuery("application/oblivious-dns-message", useGet, url, body, timeout)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue