MichaCo / DnsClient.NET

DnsClient.NET is a simple yet very powerful and high performant open source library for the .NET Framework to do DNS lookups
https://dnsclient.michaco.net
Apache License 2.0
781 stars 137 forks source link

Audit Log Exception - Error querying domain check in Swedish locale - Exception Parsing Question for Audit Log. #227

Closed IainS1986 closed 3 months ago

IainS1986 commented 4 months ago

We've noticed an issue when doing a domain check on a device (were using it in a .net8 application running .net-ios on an iphone or .net-android on Android devices) when the phones locale is set to Swedish.

We do a query as the following...

await _dnsLookupClient.QueryAsync(domain, QueryType.MX, cancellationToken: cancellationToken);

With just as an example, the domain as hotmail.com (obviously a fine domain)

This throws the following exception...

Query 28105 => hotmail.com IN MX on 8.8.8.8:53 failed with an error.
   at DnsClient.LookupClient.ResolveQueryAsync(IReadOnlyList`1 servers, DnsQuerySettings settings, DnsMessageHandler handler, DnsRequestMessage request, LookupClientAudit audit, CancellationToken cancellationToken)
   at DnsClient.LookupClient.QueryInternalAsync(DnsQuestion question, DnsQuerySettings queryOptions, IReadOnlyCollection`1 servers, CancellationToken cancellationToken)

With inner stack trace

Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
   at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.Format(String format, Object[] args)
   at DnsClient.DnsQuestion.ToString(Int32 offset)
   at DnsClient.LookupClientAudit.AuditEnd(IDnsQueryResponse queryResponse, NameServer nameServer)
   at DnsClient.LookupClient.ResolveQueryAsync(IReadOnlyList`1 servers, DnsQuerySettings settings, DnsMessageHandler handler, DnsRequestMessage request, LookupClientAudit audit, CancellationToken cancellationToken)

Any ideas on whats going on or if theres something were missing? Seems quite odd being Swedish locale specific and the domain is a plain english string of 'hotmail.com' (no non ascii chars)

This is our setup

_dnsLookupOptions = new LookupClientOptions(_dnsServers)
{
    AutoResolveNameServers = false, //Android (Update - and now iOS) does not have support for AutoResolve, will throw can't find 'etc/resolve.conf' file
    EnableAuditTrail = true,
    ThrowDnsErrors = false,
    Retries = 0,
    Timeout = TimeSpan.FromSeconds(7.5),
    ContinueOnDnsError = true,
   ContinueOnEmptyResponse = true,
    UseCache = true
};
_dnsLookupClient = new LookupClient(_dnsLookupOptions);

And these are the DNS servers we currently use

// List of internationally available public DNS servers:
var listDnsServers = new List<IPAddress>()
{
    new IPAddress(new byte[] { 8, 8, 8, 8 }),               // Google DNS
    new IPAddress(new byte[] { 8, 8, 4, 4 }),               // Google DNS
    new IPAddress(new byte[] { 9, 9, 9, 9 }),               // Quad-9 DNS
    new IPAddress(new byte[] { 149, 112, 112, 112 }),       // Quad-9 DNS
    new IPAddress(new byte[] { 208, 67, 222, 123 }),        // OpenDNS
};
IainS1986 commented 4 months ago

Heres the AuditTrail too

; (5 server found)
;; Got answer:
;; ->>HEADER<<- opcode: Query, status: No Error, id: 8029
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; UDP: 1232; code: NoError
;; QUESTION SECTION:
;; Error: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
System.FormatException: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
   at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.Format(String format, Object[] args)
   at DnsClient.DnsQuestion.ToString(Int32 offset)
   at DnsClient.LookupClientAudit.AuditEnd(IDnsQueryResponse queryResponse, NameServer nameServer)
   at DnsClient.LookupClient.ResolveQueryAsync(IReadOnlyList`1 servers, DnsQuerySettings settings, DnsMessageHandler handler, DnsRequestMessage request, LookupClientAudit audit, CancellationToken cancellationToken)

; Trying next server.
; (5 server found)
;; Got answer:
;; ->>HEADER<<- opcode: Query, status: No Error, id: 38221
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; UDP: 512; code: NoError
;; QUESTION SECTION:
;; Error: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
System.FormatException: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
   at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.Format(String format, Object[] args)
   at DnsClient.DnsQuestion.ToString(Int32 offset)
   at DnsClient.LookupClientAudit.AuditEnd(IDnsQueryResponse queryResponse, NameServer nameServer)
   at DnsClient.LookupClient.ResolveQueryAsync(IReadOnlyList`1 servers, DnsQuerySettings settings, DnsMessageHandler handler, DnsRequestMessage request, LookupClientAudit audit, CancellationToken cancellationToken)

; Trying next server.
; (5 server found)
;; Got answer:
;; ->>HEADER<<- opcode: Query, status: No Error, id: 45503
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; UDP: 1232; code: NoError
;; QUESTION SECTION:
;; Error: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
System.FormatException: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
   at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.Format(String format, Object[] args)
   at DnsClient.DnsQuestion.ToString(Int32 offset)
   at DnsClient.LookupClientAudit.AuditEnd(IDnsQueryResponse queryResponse, NameServer nameServer)
   at DnsClient.LookupClient.ResolveQueryAsync(IReadOnlyList`1 servers, DnsQuerySettings settings, DnsMessageHandler handler, DnsRequestMessage request, LookupClientAudit audit, CancellationToken cancellationToken)

; Trying next server.
; (5 server found)
;; Got answer:
;; ->>HEADER<<- opcode: Query, status: No Error, id: 10800
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; UDP: 1410; code: NoError
;; QUESTION SECTION:
;; Error: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
System.FormatException: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
   at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.Format(String format, Object[] args)
   at DnsClient.DnsQuestion.ToString(Int32 offset)
   at DnsClient.LookupClientAudit.AuditEnd(IDnsQueryResponse queryResponse, NameServer nameServer)
   at DnsClient.LookupClient.ResolveQueryAsync(IReadOnlyList`1 servers, DnsQuerySettings settings, DnsMessageHandler handler, DnsRequestMessage request, LookupClientAudit audit, CancellationToken cancellationToken)
; (5 server found)
;; Got answer:
;; ->>HEADER<<- opcode: Query, status: No Error, id: 35033
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; UDP: 512; code: NoError
;; QUESTION SECTION:
;; Error: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
System.FormatException: Input string was not in a correct format. Failure to parse near offset 3. Expected an ASCII digit.
   at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.Format(String format, Object[] args)
   at DnsClient.DnsQuestion.ToString(Int32 offset)
   at DnsClient.LookupClientAudit.AuditEnd(IDnsQueryResponse queryResponse, NameServer nameServer)
   at DnsClient.LookupClient.ResolveQueryAsync(IReadOnlyList`1 servers, DnsQuerySettings settings, DnsMessageHandler handler, DnsRequestMessage request, LookupClientAudit audit, CancellationToken cancellationToken)
IainS1986 commented 4 months ago

Not sure if this is a crazy work around for now, but wondering if I scan the AuditTrail for...

;; Got answer:
;; ->>HEADER<<- opcode: Query, status: No Error, id: XXXX

And if I see that assume it actually worked fine?

IainS1986 commented 4 months ago

Also just a note - this might (likely) not be Swedish only issue, we have seen other locales with similar issues and we just thought it was a DNS server issue and added some locale specific DNS servers to see if it helps.

Tried the same with Sweden initially, but then dug deeper and found the above exceptions being thrown - and its locale on device specific but I'm testing in the UK so its not specific to being located in Sweden.

IainS1986 commented 4 months ago

When I try with a completely made up domain (like sdikghukoshdf.com) I get the same error around non-ASCII character near offset 3 - but - the audit has

;; Got answer:
;; ->>HEADER<<- opcode: Query, status: Non-Existent Domain, id: 58166

From all DNS domains.

So I'm thinking for now I can scan the audit manually as a work around because it does appear to work

IainS1986 commented 4 months ago

Ok.

Sorry for the spam.

Its the Audit generaiton that throwing the exception!

So for now I'm just turning Audit off when not debugging!

MichaCo commented 4 months ago

Hi @IainS1986 , thanks for the bug report. I can actually reproduce the issue locally when setting the thread's current locale to Swedish via

CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("sv-SE");
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("sv-SE");

The problem here is that I concatenate a format string with a negative offset. With the locale, it formats the minus sign using (unicode minussign U+2212) instead of -.

There was actually a bug repoted that the behavior in Net6 changed in regards to that, which is kinda insane to me they kept that in... see https://github.com/dotnet/runtime/issues/44678

Anyways, I will fix some places where this might be a problem. You basically have to format any integer to string using Invariant prior using it in a concatenation. Or specify InvariantCulture when using interpolated string, which is a pain in the a..., too.

(a bit less spam would be great btw :wink: )