Skip to content

Commit

Permalink
✔ Fixed Proxy Server Error Handling.
Browse files Browse the repository at this point in the history
✔ Handled More Malformed Packet Cases.
  • Loading branch information
Texnomic committed May 30, 2020
1 parent 1659a0b commit d9a7c00
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 67 deletions.
75 changes: 21 additions & 54 deletions Texnomic.DNS.Servers/ProxyServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,19 +197,11 @@ private async Task ReceiveAsync()
throw new ArgumentOutOfRangeException();
}
}
catch (Exception Error) when (Handler(Error))
{
Logger?.Error(Error, "{@Error} Occurred While Receiving Message.", Error);

Errored?.Invoke(this, new ErroredEventArgs(Error));
}
catch (Exception Error)
{
Logger?.Fatal(Error, "Fatal {@Error} Occurred While Receiving Message.", Error);
Logger?.Error(Error, "{@Error} Occurred While Receiving Message.", Error);

Errored?.Invoke(this, new ErroredEventArgs(Error));

await StopAsync(CancellationToken);
}
}
}
Expand All @@ -229,38 +221,26 @@ private async Task ResolveAsync()
try
{
(Query, RemoteEndPoint) = await IncomingQueue.ReceiveAsync(CancellationToken)
.WithCancellation(CancellationToken);
.WithCancellation(CancellationToken);

var Answer = await ResponsibilityChain.Execute(Query);

await OutgoingQueue.SendAsync((Answer, RemoteEndPoint), CancellationToken);

Logger?.Information("Resolved {@Answer} For {@Domain} with {@ResponseCode} To {@RemoteEndPoint}.", Answer, Answer.Questions.First().Domain.Name, Answer.ResponseCode, RemoteEndPoint.ToString());
Logger?.Information("Resolved {@Answer} For {@Domain} with {@ResponseCode} To {@RemoteEndPoint}.",
Answer, Answer.Questions.First().Domain.Name, Answer.ResponseCode, RemoteEndPoint.ToString());

Resolved?.Invoke(this, new ResolvedEventArgs(Query, Answer, RemoteEndPoint));
}
catch (Exception Error) when (Handler(Error))
catch (ObjectDisposedException Error)
{
Logger?.Error(Error, "{@Error} Occurred While Resolving Message.", Error);
ResponsibilityChain = new ProxyResponsibilityChain(ProxyResponsibilityChainOptions, MiddlewareResolver);

Errored?.Invoke(this, new ErroredEventArgs(Error));

var ErrorMessage = new Message()
{
ID = Query.ID,
MessageType = MessageType.Response,
ResponseCode = ResponseCode.ServerFailure,
};

await OutgoingQueue.SendAsync((ErrorMessage, RemoteEndPoint), CancellationToken);
await Handle(Error, Query, RemoteEndPoint);
}
catch (Exception Error)
{
Logger?.Fatal(Error, "Fatal {@Error} Occurred While Resolving Message.", Error);

Errored?.Invoke(this, new ErroredEventArgs(Error));

await StopAsync(CancellationToken);
await Handle(Error, Query, RemoteEndPoint);
}
}
}
Expand All @@ -285,42 +265,29 @@ private async Task SendAsync()
Answered?.Invoke(this, new AnsweredEventArgs(Answer, RemoteEndPoint));

}
catch (Exception Error) when (Handler(Error))
{
Logger?.Error(Error, "{@Error} Occurred While Sending Message.", Error);

Errored?.Invoke(this, new ErroredEventArgs(Error));
}
catch (Exception Error)
{
Logger?.Fatal(Error, "Fatal {@Error} Occurred While Sending Message.", Error);
Logger?.Error(Error, "{@Error} Occurred While Sending Message.", Error);

Errored?.Invoke(this, new ErroredEventArgs(Error));

await StopAsync(CancellationToken);
}
}
}


private static bool Handler(Exception Error)
private async Task Handle(Exception Error, IMessage Query, IPEndPoint RemoteEndPoint)
{
switch (Error)
Logger?.Error(Error, "{@Error} Occurred While Resolving Message.", Error);

Errored?.Invoke(this, new ErroredEventArgs(Error));

var ErrorMessage = new Message()
{
case TimeoutException Timeout:
case OperationCanceledException OperationCanceled:
case ArgumentNullException ArgumentNull:
case ArgumentOutOfRangeException ArgumentOutOfRange:
case InvalidOperationException InvalidOperation:
case CryptographicUnexpectedOperationException CryptographicUnexpectedOperation:
case SocketException SocketException when (SocketException.ErrorCode == 10060):
case FormatException FormatException:
{
return true;
}
default:
return false;
}
ID = Query.ID,
MessageType = MessageType.Response,
ResponseCode = ResponseCode.ServerFailure,
};

await OutgoingQueue.SendAsync((ErrorMessage, RemoteEndPoint), CancellationToken);
}

private bool IsDisposed;
Expand Down
37 changes: 27 additions & 10 deletions Texnomic.SecureDNS.Serialization/DNSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private static IMessage GetMessage(in DnStream Stream)
AdditionalCount = Stream.ReadUShort()
};

if(Message.QuestionsCount == 0)
if (Message.QuestionsCount == 0)
throw new FormatException("Incomplete DNS Message, Message Must Have At Least 1 Question Record.");

Message.Questions = GetQuestions(in Stream, Message.QuestionsCount);
Expand Down Expand Up @@ -415,7 +415,7 @@ private static ushort SizeOf(in DoUStamp Stamp)
private static IEnumerable<IQuestion> GetQuestions(in DnStream Stream, ushort Count)
{
if (Count < 1)
throw new FormatException($"DNS Message Must Have At Least 1 Question, Got {Count}.");
throw new FormatException($"Incomplete DNS Message, DNS Message Must Have At Least 1 Question, Got {Count}.");

var Questions = new List<IQuestion>();

Expand Down Expand Up @@ -457,11 +457,19 @@ private static IQuestion GetQuestion(in DnStream Stream)
{
var Question = new Question()
{
Domain = GetDomain(in Stream),
Type = Stream.ReadUShort().AsEnum<RecordType>(),
Class = Stream.ReadUShort().AsEnum<RecordClass>()
Domain = GetDomain(in Stream)
};

if (Stream.Length < Stream.BytePosition + 2)
throw new FormatException("Incomplete DNS Message, Missing Question Record Type.");

Question.Type = Stream.ReadUShort().AsEnum<RecordType>();

//Note: Ignores Missing Bytes Error As We Can Recover Message in Single Question Cases.
Question.Class = Stream.Length >= Stream.BytePosition + 2
? Stream.ReadUShort().AsEnum<RecordClass>()
: RecordClass.Internet;

return Question;
}

Expand Down Expand Up @@ -539,7 +547,7 @@ private static IEnumerable<string> GetLabels(in DnStream Stream)
{
var Pointer = (ushort)(Stream.ReadBits(6) + Stream.ReadByte());

if (Pointer >= Stream.BytePosition - 2)
if (Pointer >= Stream.BytePosition - 2)
throw new ArgumentOutOfRangeException(nameof(Pointer), Pointer, "Compressed Label Infinite Loop Detected.");

var Position = Stream.BytePosition;
Expand All @@ -552,6 +560,8 @@ private static IEnumerable<string> GetLabels(in DnStream Stream)

return Labels;
}
case LabelType.Extended:
case LabelType.Unallocated:
default:
throw new ArgumentOutOfRangeException(nameof(LabelType), LabelType, null);
}
Expand Down Expand Up @@ -665,12 +675,19 @@ private static IAnswer GetAnswer(in DnStream Stream)
var Answer = new Answer()
{
Domain = GetDomain(in Stream),
Type = Stream.ReadUShort().AsEnum<RecordType>(),
Class = Stream.ReadUShort().AsEnum<RecordClass>(),
TimeToLive = Stream.ReadTimeSpan(),
Length = Stream.ReadUShort(),
};

if (Stream.Length < Stream.BytePosition + 6)
throw new FormatException("Incomplete DNS Message, Missing Answer Body.");

Answer.Type = Stream.ReadUShort().AsEnum<RecordType>();

Answer.Class = Stream.ReadUShort().AsEnum<RecordClass>();

Answer.TimeToLive = Stream.ReadTimeSpan();

Answer.Length = Stream.ReadUShort();

if (Stream.Length < Answer.Length)
throw new FormatException("Incomplete DNS Message, Missing Record Section.");

Expand Down
5 changes: 3 additions & 2 deletions Texnomic.SecureDNS.Tests/Core/Serialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ public void DeserializeMalformed()
{
var ResponseBytes = new byte[]
{
0x02, 0xBD, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x74, 0x69, 0x6D, 0x65,
0x05, 0x63, 0x68, 0x74, 0x74, 0x6C, 0x03, 0x63, 0x6F, 0x6D, 0x02, 0x74, 0x77
0x02, 0x69, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x75, 0x67, 0x63, 0x06,
0x64, 0x75, 0x63, 0x61, 0x74, 0x69, 0x07, 0x6B, 0x6F, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x03, 0x63, 0x6F,
0x6D, 0x00, 0x00, 0x01, 0x00
};

var ResponseMessage = DnSerializer.Deserialize(in ResponseBytes);
Expand Down
1 change: 0 additions & 1 deletion Texnomic.SecureDNS.Tests/Texnomic.SecureDNS.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Texnomic.DNS\Texnomic.DNS.csproj" />
<ProjectReference Include="..\Texnomic.SecureDNS.Abstractions\Texnomic.SecureDNS.Abstractions.csproj" />
<ProjectReference Include="..\Texnomic.SecureDNS.Core\Texnomic.SecureDNS.Core.csproj" />
<ProjectReference Include="..\Texnomic.SecureDNS.Serialization\Texnomic.SecureDNS.Serialization.csproj" />
Expand Down

0 comments on commit d9a7c00

Please sign in to comment.