protected override byte[] QueryByTcp(IPAddress nameServer, int port, byte[] messageData, int messageLength, ref TcpClient tcpClient, ref System.IO.Stream tlsStream, out IPAddress responderAddress, out int responderPort) { responderAddress = nameServer; responderPort = port == 0 ? _port : port; if (!IsTcpEnabled) { return(null); } IPEndPoint endPoint = new IPEndPoint(nameServer, port == 0 ? _port : port); IPAddress unferResponderAddress = responderAddress; int unferResponderPort = responderPort; TlsUpstreamServer tlsServer = _tlsservers.Where(t => t.IPAddress == unferResponderAddress && t.Port == unferResponderPort).FirstOrDefault(); if (tlsServer == null) { Trace.TraceError("Error on dns query: invalid TLS upstream server"); return(null); } try { if (tcpClient == null || (this.IsReuseTcpEnabled && !tcpClient.IsConnected())) { tcpClient = new TcpClient(nameServer.AddressFamily) { ReceiveTimeout = QueryTimeout, SendTimeout = QueryTimeout }; if (!tcpClient.TryConnect(endPoint, QueryTimeout)) { return(null); } SslStream sslStream = new SslStream(tcpClient.GetStream(), true, new RemoteCertificateValidationCallback(tlsServer.ValidateRemoteCertificate)); tlsStream = sslStream; try { sslStream.AuthenticateAsClient(tlsServer.AuthName ?? string.Empty, new X509CertificateCollection(), tlsServer.SslProtocols, false); } catch (Exception) { } if (!sslStream.IsAuthenticated) { Trace.TraceError("Error on dns query: invalid TLS upstream server certificate"); if (this.IsReuseTcpEnabled) { try { tlsStream.Dispose(); tcpClient.Close(); } catch (Exception) { } } return(null); } } int tmp = 0; byte[] lengthBuffer = new byte[2]; if (messageLength > 0) { DnsMessageBase.EncodeUShort(lengthBuffer, ref tmp, (ushort)messageLength); tlsStream.Write(lengthBuffer, 0, 2); tlsStream.Write(messageData, 0, messageLength); } if (!TryRead(tcpClient, tlsStream, lengthBuffer, 2)) { return(null); } tmp = 0; int length = DnsMessageBase.ParseUShort(lengthBuffer, ref tmp); byte[] resultData = new byte[length]; return(TryRead(tcpClient, tlsStream, resultData, length) ? resultData : null); } catch (Exception e) { Trace.TraceError("Error on dns query: " + e); return(null); } }
/// <summary> /// Provides a new instance with custom dns server and query timeout /// </summary> /// <param name="dnsServer"> The IPAddress of the dns server to use </param> /// <param name="queryTimeout"> Query timeout in milliseconds </param> /// <param name="port"> Server port </param> public DnsOverTlsClient(TlsUpstreamServer dnsServer, int queryTimeout, int port = 853) : this(new List <TlsUpstreamServer> { dnsServer }, queryTimeout, port) { }
protected async override Task <QueryResponse> QueryByTcpAsync(IPAddress nameServer, int port, byte[] messageData, int messageLength, TcpClient tcpClient, System.IO.Stream tlsStream, CancellationToken token) { if (!IsTcpEnabled) { return(null); } int responderPort = port == 0 ? _port : port; TlsUpstreamServer tlsServer = _tlsservers.Where(t => t.IPAddress == nameServer && t.Port == responderPort).FirstOrDefault(); if (tlsServer == null) { Trace.TraceError("Error on dns query: invalid TLS upstream server"); return(null); } string reusableMapKey = string.Concat(nameServer, port); if (tcpClient == null && this.IsReuseTcpEnabled) { if (!this.reusableTcp.ContainsKey(reusableMapKey)) { this.reusableTcp[reusableMapKey] = new ReusableTcpConnection(); } ReusableTcpConnection reuse = this.reusableTcp[reusableMapKey]; tcpClient = reuse.Client; tlsStream = reuse.Stream; this.reusableTcp[reusableMapKey].LastUsed = DateTime.UtcNow; } try { if (tcpClient == null || (this.IsReuseTcpEnabled && !tcpClient.IsConnected())) { tcpClient = new TcpClient(nameServer.AddressFamily) { ReceiveTimeout = QueryTimeout, SendTimeout = QueryTimeout }; if (!await tcpClient.TryConnectAsync(nameServer, responderPort, QueryTimeout, token)) { return(null); } SslStream sslStream = new SslStream(tcpClient.GetStream(), true, new RemoteCertificateValidationCallback(tlsServer.ValidateRemoteCertificate)); tlsStream = sslStream; try { sslStream.AuthenticateAsClient(tlsServer.AuthName ?? string.Empty, new X509CertificateCollection(), tlsServer.SslProtocols, false); } catch (Exception) { } if (!sslStream.IsAuthenticated) { Trace.TraceError("Error on dns query: invalid TLS upstream server certificate"); if (this.IsReuseTcpEnabled) { try { tlsStream.Dispose(); tcpClient.Close(); } catch (Exception) { } } return(null); } } int tmp = 0; byte[] lengthBuffer = new byte[2]; if (messageLength > 0) { DnsMessageBase.EncodeUShort(lengthBuffer, ref tmp, (ushort)messageLength); await tlsStream.WriteAsync(lengthBuffer, 0, 2, token); await tlsStream.WriteAsync(messageData, 0, messageLength, token); } if (!await TryReadAsync(tcpClient, tlsStream, lengthBuffer, 2, token)) { return(null); } tmp = 0; int length = DnsMessageBase.ParseUShort(lengthBuffer, ref tmp); byte[] resultData = new byte[length]; return(await TryReadAsync(tcpClient, tlsStream, resultData, length, token) ? new QueryResponse(resultData, nameServer, tcpClient, tlsStream, responderPort) : null); } catch (Exception e) { Trace.TraceError("Error on dns query: " + e); return(null); } }