} // End Sub Test1 // https://stackoverflow.com/questions/28612289/tcpclient-connectasync-or-socket-beginconnect-with-non-blocking-timeout-setting public static void Test2() { IDnsSecResolver resolver = new DnsSecRecursiveDnsResolver(); //using (TcpClient client = new TcpClient("example.com", 443)) using (TcpClient client = new TcpClient()) { Task t = client.ConnectAsync("example.com", 443); t.Wait(); using (DaneStream stream = new DaneStream(client.GetStream(), resolver)) { stream.AuthenticateAsClient("example.com", 443); if (stream.IsAuthenticatedByDane) { Console.WriteLine("Stream is authenticated by DANE/TLSA"); } // work with the stream } // End Using stream } // End Using client } // End Sub Test2
} // End Sub Test1 // https://stackoverflow.com/questions/28612289/tcpclient-connectasync-or-socket-beginconnect-with-non-blocking-timeout-setting public static void Test2() { IDnsSecResolver resolver = new DnsSecRecursiveDnsResolver(); //using (System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("example.com", 443)) using (System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient()) { System.Threading.Tasks.Task t = client.ConnectAsync("example.com", 443); t.Wait(); using (ARSoft.Tools.Net.Net.DaneStream stream = new ARSoft.Tools.Net.Net.DaneStream(client.GetStream(), resolver)) { stream.AuthenticateAsClient("example.com", 443); if (stream.IsAuthenticatedByDane) { System.Console.WriteLine("Stream is authenticated by DANE/TLSA"); } // work with the stream } // End Using stream } // End Using client } // End Sub Test2
public async Task <List <ActionResult> > CheckDNS(ILog log, string domain, bool?useProxyAPI = null, bool includeIPCheck = true) { var results = new List <ActionResult>(); log.Information("CheckDNS: performing DNS checks. This option can be disabled in Settings if required."); if (string.IsNullOrEmpty(domain)) { results.Add(new ActionResult { IsSuccess = false, Message = "CheckDNS: Cannot check null or empty DNS name." }); log.Error(results.Last().Message); return(results); } // if validation proxy enabled, DNS for the domain being validated is checked via our // remote API rather than directly on the servers var useProxy = useProxyAPI ?? _enableValidationProxyAPI; if (useProxy) { // TODO: update proxy and implement proxy check here return (ok, message); } // check dns resolves to IP if (includeIPCheck) { try { log.Information($"Checking DNS name resolves to IP: {domain}"); var result = await Dns.GetHostEntryAsync(domain); // this throws SocketException for bad DNS results.Add(new ActionResult { IsSuccess = true, Message = $"CheckDNS: '{domain}' resolved to an IP Address {result.AddressList[0]}. " }); } catch { results.Add(new ActionResult { IsSuccess = false, Message = $"CheckDNS: '{domain}' failed to resolve to an IP Address. " }); log.Error(results.Last().Message); return(results); } } DnsMessage caa_query = null; DomainName dn = null; try { // check CAA dn = DomainName.Parse(domain); caa_query = DnsClient.Default.Resolve(dn, RecordType.CAA); } catch (Exception exp) { log.Error(exp, $"'{domain}' DNS error resolving CAA : {exp.Message}"); } if (caa_query == null || caa_query.ReturnCode != ReturnCode.NoError) { // dns lookup failed results.Add(new ActionResult { IsSuccess = false, Message = $"CheckDNS: '{domain}' failed to parse or resolve CAA. " }); log.Error(results.Last().Message); return(results); } if (caa_query.AnswerRecords.Where(r => r is CAARecord).Count() > 0) { // dns returned at least 1 CAA record, check for validity if (!caa_query.AnswerRecords.Where(r => r is CAARecord).Cast <CAARecord>() .Any(r => (r.Tag == "issue" || r.Tag == "issuewild") && r.Value == "letsencrypt.org")) { // there were no CAA records of "[flag] [tag] [value]" where [tag] = issue | // issuewild and [value] = letsencrypt.org // see: https://letsencrypt.org/docs/caa/ results.Add(new ActionResult { IsSuccess = false, Message = $"CheckDNS: '{domain}' DNS CAA verification failed - existing CAA record prevent issuance for letsencrypt.org CA." }); log.Warning(results.Last().Message); return(results); } } // now either there were no CAA records returned (i.e. CAA is not configured) or the CAA // records are correctly configured // check DNSSEC var dnssec = new DnsSecRecursiveDnsResolver(); try { log.Information("Checking DNSSEC resolution"); var res = await dnssec.ResolveSecureAsync <ARecord>(dn); var isOk = res.ValidationResult != DnsSecValidationResult.Bogus; if (isOk) { results.Add(new ActionResult { IsSuccess = true, Message = $"CheckDNS: '{domain}' DNSSEC Check OK - Validation Result: {res.ValidationResult}" }); } else { results.Add(new ActionResult { IsSuccess = isOk, Message = $"CheckDNS: '{domain}'DNSSEC Check Failed - Validation Result: {res.ValidationResult}" }); } } catch (DnsSecValidationException exp) { // invalid dnssec results.Add(new ActionResult { IsSuccess = false, Message = $"CheckDNS: '{domain}'DNSSEC Check Failed - {exp.Message}" }); log.Warning(results.Last().Message); } catch (Exception exp) { // domain failed to resolve from this machine results.Add(new ActionResult { IsSuccess = false, Message = $"CheckDNS: '{domain}' DNS error resolving DnsSecRecursiveDnsResolver - {exp.Message}" }); } return(results); }
public (bool Ok, string Message) CheckDNS(string domain, bool?useProxyAPI = null) { // helper function to log the error then return the ValueTuple Func <string, (bool, string)> errorResponse = (msg) => { msg = $"CheckDNS: {msg}\nDNS checks can be disabled in Settings if required."; Log(msg); return(false, msg); }; if (String.IsNullOrEmpty(domain)) { return(errorResponse("Cannot check null or empty DNS name.")); } // if validation proxy enabled, DNS for the domain being validated is checked via our // remote API rather than directly on the servers bool useProxy = useProxyAPI ?? CoreAppSettings.Current.EnableValidationProxyAPI; if (useProxy) { // TODO: update proxy and implement proxy check here return (ok, message); } // check dns try { Dns.GetHostEntry(domain); // this throws SocketException for bad DNS } catch { return(errorResponse($"'{domain}' failed to resolve to an IP Address.")); } DnsMessage caa_query = null; DomainName dn = null; try { // check CAA dn = DomainName.Parse(domain); caa_query = DnsClient.Default.Resolve(dn, RecordType.CAA); } catch (Exception exp) { Log($"'{domain}' DNS error resolving CAA: " + exp.ToString()); } if (caa_query == null || caa_query.ReturnCode != ReturnCode.NoError) { // dns lookup failed return(errorResponse($"'{domain}' failed to parse or resolve CAA.")); } if (caa_query.AnswerRecords.Where(r => r is CAARecord).Count() > 0) { // dns returned at least 1 CAA record, check for validity if (!caa_query.AnswerRecords.Where(r => r is CAARecord).Cast <CAARecord>() .Any(r => (r.Tag == "issue" || r.Tag == "issuewild") && r.Value == "letsencrypt.org")) { // there were no CAA records of "[flag] [tag] [value]" where [tag] = issue | // issuewild and [value] = letsencrypt.org // see: https://letsencrypt.org/docs/caa/ return(errorResponse($"'{domain}' DNS CAA verification failed.")); } } // now either there were no CAA records returned (i.e. CAA is not configured) or the CAA // records are correctly configured // note: this seems to need to run in a Task or it hangs forever when called from the WPF UI if (!Task.Run(async() => { // check DNSSEC var dnssec = new DnsSecRecursiveDnsResolver(); try { var res = await dnssec.ResolveSecureAsync <ARecord>(dn); return(res.ValidationResult != DnsSecValidationResult.Bogus); } catch (DnsSecValidationException) { // invalid dnssec return(false); } catch (Exception exp) { // domain failed to resolve from this machine Log($"'{domain}' DNS error resolving DnsSecRecursiveDnsResolver: " + exp.ToString()); return(false); } }).Result) { return(errorResponse($"'{domain}' DNSSEC verification failed.")); } return(true, ""); }
public (bool Ok, string Message) CheckDNS(string domain, bool?useProxyAPI = null) { // if validation proxy enabled, DNS for the domain being validated is checked via our // remote API rather than directly on the servers bool useProxy = useProxyAPI ?? Certify.Properties.Settings.Default.EnableValidationProxyAPI; if (useProxy) { // TODO: update proxy and implement proxy check here // return (ok, message); } var dn = DomainName.Parse(domain); var dns = DnsClient.Default.Resolve(dn, RecordType.CAA); if (dns == null || dns.ReturnCode != ReturnCode.NoError) { // dns lookup failed string message = $"DNS lookup failed for '{domain}'"; Log(message); return(false, message); } // check CAA if (dns.AnswerRecords.Where(r => r is CAARecord).Count() > 0) { // dns returned at least 1 CAA record, check for validity if (!dns.AnswerRecords.Where(r => r is CAARecord).Cast <CAARecord>() .Any(r => (r.Tag == "issue" || r.Tag == "issuewild") && r.Value == "letsencrypt.org")) { // there were no CAA records of "[flag] [tag] [value]" // where [tag] = issue | issuewild // and [value] = letsencrypt.org // see: https://letsencrypt.org/docs/caa/ string message = $"DNS CAA verification failed for '{domain}'"; Log(message); return(false, message); } } // now either there were no CAA records returned (i.e. CAA is not configured) // or the CAA records are correctly configured // note: this seems to need to run in a Task or it hangs forever // when called from the WPF UI if (!Task.Run(async() => { // check DNSSEC var dnssec = new DnsSecRecursiveDnsResolver(); try { var res = await dnssec.ResolveSecureAsync <ARecord>(dn); return(res.ValidationResult != DnsSecValidationResult.Bogus); } catch (DnsSecValidationException) { // invalid dnssec return(false); } }).Result) { string message = $"DNSSEC verification failed for '{domain}'"; Log(message); return(false, message); } return(true, ""); }