Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS Cipher Suite setting ignored with TLS 1.3 #2359

Closed
Javinator9889 opened this issue Mar 29, 2023 · 11 comments
Closed

TLS Cipher Suite setting ignored with TLS 1.3 #2359

Javinator9889 opened this issue Mar 29, 2023 · 11 comments
Labels
wontfix This will not be worked on

Comments

@Javinator9889
Copy link

Output of the following commands:

./dnscrypt-proxy -version
2.0.45
./dnscrypt-proxy -check
<no output>
./dnscrypt-proxy -resolve example.com
Resolving [example.com] using [10::dead:cafe] port 5354

Resolver      : 172.253.5.129

Canonical name: example.com.

IPv4 addresses: 93.184.216.34
IPv6 addresses: -

Name servers  : a.iana-servers.net., b.iana-servers.net.
DNSSEC signed : yes
Mail servers  : 1 mail servers found

HTTPS alias   : -
HTTPS info    : -

Host info     : -
TXT records   : v=spf1 -all, wgyf8z8cgvm2qmxpnbnldrcltvk4xqfn

What is affected by this bug?

The tls_cipher_suite seems to be doing nothing: I have configured the TLS_RSA_WITH_RC4_128_SHA algorithm (0x0005 in hex), which should not be compatible neither with cloudflare or google but the connection still works. Moreover, the used suite does not even match the one I requested.

When does this occur?

When configuring the DNSCrypt service, having a look at the journal logs, everything seems to be working fine whereas it should not.

How do we replicate the issue?

Place the following configuration:

server_names = ['cloudflare', 'google']
listen_addresses = ['[10::dead:cafe]:5354','192.168.122.2:5353']
max_clients = 250
user_name = '_dnscrypt-proxy'
ipv4_servers = true
ipv6_servers = false
dnscrypt_servers = false
doh_servers = true
require_dnssec = false
require_nolog = false
require_nofilter = false
force_tcp = false
timeout = 5000
keepalive = 30
lb_strategy = 'p2'
log_level = 0
use_syslog = true
cert_refresh_delay = 240
tls_cipher_suite = [5]
fallback_resolvers = ['192.168.122.1:53']
ignore_system_dns = true
netprobe_timeout = 60
netprobe_address = '9.9.9.9:53'
block_ipv6 = true
cache = false
[local_doh]
listen_addresses = ['[::]:3000']
path = '/dns-query'
cert_file = '/var/dnscrypt-proxy/server.crt'
cert_key_file = '/var/dnscrypt-proxy/private.key'
[query_log]
format = 'tsv'
[nx_log]
format = 'tsv'
[sources]
  [sources.public-resolvers]
    urls = ['https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md', 'https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md']
    cache_file = '/var/cache/dnscrypt-proxy/public-resolvers.md'
    minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
    refresh_delay = 72
    prefix = ''
[broken_implementations]
fragments_blocked = ['cisco', 'cisco-ipv6', 'cisco-familyshield', 'cisco-familyshield-ipv6', 'cleanbrowsing-adult', 'cleanbrowsing-adult-ipv6', 'cleanbrowsing-family', 'cleanbrowsing-family-ipv6', 'cleanbrowsing-security', 'cleanbrowsing-security-ipv6']
[doh_client_x509_auth]

Very probably it is needed to tweak the configuration to adjust IP addresses. I am running dnscrypt-proxy inside a VM running Debian. The version is the one available on bullseye. There is a DoH server configured for the instance too. However, I suppose it should not affect.

The logs I get are:

Mar 29 11:24:11.192725 osdx dnscrypt-proxy[28598]: dnscrypt-proxy 2.0.45
Mar 29 11:24:11.192974 osdx dnscrypt-proxy[28598]: Network connectivity detected
Mar 29 11:24:11.230876 osdx dnscrypt-proxy[28598]: Now listening to [10::dead:cafe]:5354 [UDP]
Mar 29 11:24:11.231802 osdx dnscrypt-proxy[28598]: Now listening to [10::dead:cafe]:5354 [TCP]
Mar 29 11:24:11.231831 osdx dnscrypt-proxy[28598]: Now listening to 192.168.122.2:5353 [UDP]
Mar 29 11:24:11.231846 osdx dnscrypt-proxy[28598]: Now listening to 192.168.122.2:5353 [TCP]
Mar 29 11:24:11.232822 osdx dnscrypt-proxy[28598]: Now listening to https://[::]:3000/dns-query [DoH]
Mar 29 11:24:11.233895 osdx dnscrypt-proxy[28598]: Source [public-resolvers] loaded
Mar 29 11:24:11.235040 osdx dnscrypt-proxy[28598]: Firefox workaround initialized
Mar 29 11:24:11.350670 osdx dnscrypt-proxy[28598]: [cloudflare] TLS version: 304 - Protocol: h2 - Cipher suite: 4865
Mar 29 11:24:11.350853 osdx dnscrypt-proxy[28598]: [cloudflare] OK (DoH) - rtt: 7ms
Mar 29 11:24:11.429428 osdx dnscrypt-proxy[28598]: [google] TLS version: 304 - Protocol: h2 - Cipher suite: 4865
Mar 29 11:24:11.429473 osdx dnscrypt-proxy[28598]: [google] OK (DoH) - rtt: 15ms
Mar 29 11:24:11.429480 osdx dnscrypt-proxy[28598]: Sorted latencies:
Mar 29 11:24:11.429498 osdx dnscrypt-proxy[28598]: -     7ms cloudflare
Mar 29 11:24:11.429500 osdx dnscrypt-proxy[28598]: -    15ms google
Mar 29 11:24:11.429503 osdx dnscrypt-proxy[28598]: Server with the lowest initial latency: cloudflare (rtt: 7ms)
Mar 29 11:24:11.429507 osdx dnscrypt-proxy[28598]: dnscrypt-proxy is ready - live servers: 2

Expected behavior (i.e. solution)

The service gets a TLS error and refuses to connect to the upstream servers. Therefore, the service fails.

Other Comments

I have tweaked the Debian service to not use the SystemD socket and therefore, behave exactly the same as a manually launched application. The service unit is:

# /etc/systemd/system/dnscrypt-proxy.service
[Unit]
Description=DNSCrypt client proxy
Documentation=https://github.com/jedisct1/dnscrypt-proxy/wiki
After=network.target
Before=nss-lookup.target
Wants=nss-lookup.target

[Install]
WantedBy=multi-user.target

[Service]
NonBlocking=true
ExecStart=/usr/sbin/dnscrypt-proxy -config /etc/dnscrypt-proxy/dnscrypt-proxy.toml
ProtectHome=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
MemoryDenyWriteExecute=true

CacheDirectory=dnscrypt-proxy
LogsDirectory=dnscrypt-proxy
RuntimeDirectory=dnscrypt-proxy
@jedisct1
Copy link
Member

jedisct1 commented Mar 29, 2023

This is only for TLS 1.0-1.2.

TLS 1.3 ciphers are not configurable:

It's an intentional limitation of the language itself (or, rather, its standard library), motivated by the fact that since Go 1.17, proper cipher suite ordering is done automatically.

As the vast majority of servers are now using TLS 1.3, we should probably remove this option from the documentation and example files.

@jedisct1 jedisct1 changed the title TLS Cipher Suite setting is not working TLS Cipher Suite setting ignored with TLS 1.3 Mar 29, 2023
@jedisct1 jedisct1 added the wontfix This will not be worked on label Mar 29, 2023
@Javinator9889
Copy link
Author

Thanks for the fast response @jedisct1!

Before closing this issue, let me check that the behavior is the expected one when working with TLS v1.2: I expect dnscrypt-proxy to fail if there is no configured tls_cipher_suite suitable for the server configuration.

@Javinator9889
Copy link
Author

On the other hand, I think removing the option would be a "bad" idea: it is true that most of the servers are using TLS v1.3 at the moment, but there are a number of others that are using TLS <= 1.2 (maybe because of maintaining backward compatibility, etc.). Depending on the device that is going to use those servers (in our case, there are some embedded ones), being able to choose a set of optimal cipher suites is mandatory.

I would suggest, if possible, that the available ciphers can be configurable when instructing dnscrypt-proxy to work as a server.

@Javinator9889
Copy link
Author

Ok @jedisct1

I have just tested using a TLS v1.2 server on a scenario we have deployed for testing the DoH. This is the configuration being used by the test:

server_names = ['RD']
max_clients = 250
user_name = '_dnscrypt-proxy'
ipv4_servers = true
ipv6_servers = true
dnscrypt_servers = true
doh_servers = true
require_dnssec = false
require_nolog = false
require_nofilter = false
force_tcp = false
timeout = 5000
keepalive = 30
lb_strategy = 'p2'
log_level = 0
use_syslog = true
cert_refresh_delay = 240
tls_cipher_suite = [5]
ignore_system_dns = true
netprobe_timeout = 60
netprobe_address = '1.1.1.1:53'
block_ipv6 = false
cloaking_rules = '/tmp/tmpNNgmiI'
cloak_ttl = 600
cache = false
[query_log]
format = 'tsv'
[nx_log]
format = 'tsv'
[sources]
[broken_implementations]
fragments_blocked = ['cisco', 'cisco-ipv6', 'cisco-familyshield', 'cisco-familyshield-ipv6', 'cleanbrowsing-adult', 'cleanbrowsing-adult-ipv6', 'cleanbrowsing-family', 'cleanbrowsing-family-ipv6', 'cleanbrowsing-security', 'cleanbrowsing-security-ipv6']
[doh_client_x509_auth]
[static]
  [static.'RD']
    stamp = 'sdns://AgAAAAAAAAAADDEwLjIxNS4xNjguMSBVNoNeRJCJdZ6qi7mgZRKWmBGMR5p5C-Bk7u9Ii_Ht0ApyZW1vdGUuZG5zCi9kbnMtcXVlcnk'

In this case, the DNS stamp points to a server we have on a private network whose DNS is resolved by the hosts file (we have an automated script for translating the hosts file into a cloaking one). The R&D server TLS is limited to v1.2, and the cipher the test tries is the same as the one indicated by my first message.

However, when having a look at the logs, this is the output we get:

Mar 29 13:28:18.555077 osdx dnscrypt-proxy[2746]: dnscrypt-proxy 2.0.45
Mar 29 13:28:18.555392 osdx dnscrypt-proxy[2746]: Network connectivity detected
Mar 29 13:28:18.555835 osdx dnscrypt-proxy[2746]: Dropping privileges
Mar 29 13:28:18.561617 osdx dnscrypt-proxy[2746]: Network connectivity detected
Mar 29 13:28:18.561891 osdx dnscrypt-proxy[2746]: Now listening to 127.0.0.1:53 [UDP]
Mar 29 13:28:18.561985 osdx dnscrypt-proxy[2746]: Now listening to 127.0.0.1:53 [TCP]
Mar 29 13:28:18.562076 osdx dnscrypt-proxy[2746]: Firefox workaround initialized
Mar 29 13:28:18.562148 osdx dnscrypt-proxy[2746]: Loading the set of cloaking rules from [/tmp/tmpNNgmiI]
Mar 29 13:28:18.574989 osdx dnscrypt-proxy[2746]: TLS handshake failure - Try changing or deleting the tls_cipher_suite value in the configuration file
Mar 29 13:28:18.788534 osdx dnscrypt-proxy[2746]: [RD] TLS version: 303 - Protocol: h2 - Cipher suite: 49199
Mar 29 13:28:18.788548 osdx dnscrypt-proxy[2746]: [RD] OK (DoH) - rtt: 160ms
Mar 29 13:28:18.788556 osdx dnscrypt-proxy[2746]: Server with the lowest initial latency: RD (rtt: 160ms)
Mar 29 13:28:18.788561 osdx dnscrypt-proxy[2746]: dnscrypt-proxy is ready - live servers: 1

I can confirm you the /tmp/tmpNNgmil file contents are:

remote.dns    10.215.168.1

Is there anything that I am missing? Is the problem related to having the server manually configured and not using a resolver list?

Thanks in advance

@jedisct1
Copy link
Member

jedisct1 commented Mar 29, 2023

In that case we should at least update the documentation.

In order for the cipher suite to be used with servers that also support TLS 1.3, we would need to introduce a new option to downgrade the TLS version.

That doesn't sound like a good idea.

Status quo is that with TLS 1.2, the client can choose the ciphers, and that with TLS 1.3, Go chooses the fastest cipher.

The option to change the cipher suite was introduced to force usage of RSA instead of ECC, because on some devices, RSA was faster in spite of the bigger signatures and keys.

So maybe what we need instead is a favor_rsa option, that wouldd disable TLS 1.3 and ECC?

@jedisct1
Copy link
Member

Your "RD" server is probably using a cipher suite that is not supported by Go any more even for TLS 1.2.

@jedisct1
Copy link
Member

Before closing this issue, let me check that the behavior is the expected one when working with TLS v1.2: I expect dnscrypt-proxy to fail if there is no configured tls_cipher_suite suitable for the server configuration.

Ah no, it doesn't fail, as this is usually a client configuration error. It warns you so that you can adjust the configuration, and performs the handshake with the default suites.

@Javinator9889
Copy link
Author

Oh f**k! Is there any way to fail it, if possible? We can have control over the messages that are generated, so analyze them and produce an error... But if there is any way to do it from configuration it would be better

@jedisct1
Copy link
Member

No, because some servers don't support RSA, but most people still expect things to work.

Replacing the list with a prefer_rsa toggle may make this more clear. Or maybe something like preferred_key_exchange_algs so we can include post-quantum and hybrid algorithms here.

@Javinator9889
Copy link
Author

Yeah, I think (for clarity) it would be better: The current naming seems to say "those are the algorithms you shall use", while it's more like: "ey, use these algorithms, and if not I don't really care" :)

I think we are going to introduce some warnings and information whenever a user attempts to configure the ciphers, to let them know they are not really restricting them.

Thanks for the support @jedisct1! <3
If you think so, this issue can be considered close (unless you wanna use it as a start point for changing the setting name).

@jedisct1
Copy link
Member

TLS 1.3 didn't exist yet when this option was introduced.

@DNSCrypt DNSCrypt locked and limited conversation to collaborators May 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants