Skip to content

Commit

Permalink
add Http01ChallengeService
Browse files Browse the repository at this point in the history
  • Loading branch information
trudyhood committed Feb 16, 2024
1 parent 424a000 commit af101c5
Show file tree
Hide file tree
Showing 21 changed files with 122 additions and 117 deletions.
4 changes: 2 additions & 2 deletions Pub/PubVersion.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"Version": "3.3.464",
"BumpTime": "2024-02-14T03:23:34.9308800Z",
"Version": "3.3.465",
"BumpTime": "2024-02-14T22:25:09.8987718Z",
"Prerelease": true,
"DeprecatedVersion": "3.0.416"
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
<BaseOutputPath></BaseOutputPath>
<BaseIntermediateOutputPath />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
<BaseOutputPath></BaseOutputPath>
<BaseIntermediateOutputPath />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
<BaseOutputPath></BaseOutputPath>
<BaseIntermediateOutputPath />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion VpnHood.Client.App.Store/VpnHood.Client.App.Store.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion VpnHood.Client.App/VpnHood.Client.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion VpnHood.Client.Device/VpnHood.Client.Device.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion VpnHood.Client/VpnHood.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion VpnHood.Common/VpnHood.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion VpnHood.Server.Access/VpnHood.Server.Access.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<PackageIcon>VpnHood.png</PackageIcon>
<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
<Version>3.3.464</Version>
<Version>3.3.465</Version>
<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
</PropertyGroup>

Expand Down
85 changes: 42 additions & 43 deletions VpnHood.Server/Http01ChallengeService.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using System.Net;
using System.Net.Sockets;
using System.Text;
using Microsoft.Extensions.Logging;
using VpnHood.Common.Logging;
using VpnHood.Tunneling;
using VpnHood.Tunneling.Utils;

namespace VpnHood.Server;

public class Http01ChallengeService(IPAddress[] ipAddresses) : IDisposable
public class Http01ChallengeService(IPAddress[] ipAddresses, string token, string keyAuthorization) : IDisposable
{
private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly List<TcpListener> _tcpListeners = [];
private bool _disposed;
public bool IsStarted { get; private set; }
Expand All @@ -18,73 +19,70 @@ public Task Start()
if (IsStarted) throw new InvalidOperationException("The HTTP-01 Challenge Service has already been started.");
if (_disposed) throw new ObjectDisposedException(nameof(Http01ChallengeService));

foreach (var ipAddress in ipAddresses)
try
{
var ipEndPoint = new IPEndPoint(ipAddress, 80);
VhLogger.Instance.LogInformation("HTTP-01 Challenge Listener starting on {EndPoint}", ipEndPoint);
foreach (var ipAddress in ipAddresses)
{
var ipEndPoint = new IPEndPoint(ipAddress, 80);
VhLogger.Instance.LogInformation("HTTP-01 Challenge Listener starting on {EndPoint}", ipEndPoint);

var listener = new TcpListener(ipEndPoint);
listener.Start();
_tcpListeners.Add(listener);
}
var listener = new TcpListener(ipEndPoint);
listener.Start();
_tcpListeners.Add(listener);
}

var listenTasks = _tcpListeners.Select(AcceptTcpClient);
return Task.WhenAll(listenTasks);
var listenTasks = _tcpListeners.Select(x => AcceptTcpClient(x, _cancellationTokenSource.Token));
return Task.WhenAll(listenTasks);
}
catch
{
Stop();
throw;
}
}

private async Task AcceptTcpClient(TcpListener tcpListener)
private async Task AcceptTcpClient(TcpListener tcpListener, CancellationToken cancellationToken)
{
try
{
while (true)
{
using var client = await tcpListener.AcceptTcpClientAsync();
//HandleRequest(client, token, keyAuthorization);
await HandleRequest(client, token, keyAuthorization, cancellationToken);
}
}
catch (Exception ex)
{
VhLogger.Instance.LogError(ex, "Could not process HTTP-01 request.");
VhLogger.Instance.LogError(GeneralEventId.Acme, ex, "Could not process the ACME request.");
}
}

private static byte[] BuildHttp01Response(string challengeCode)
{
var header =
"HTTP/1.1 200\r\n" +
"Server: Kestrel\r\n" +
$"Date: {DateTime.UtcNow:r}\r\n" +
"Content-Type: text/plain\r\n" +
$"Content-Length: {challengeCode.Length}\r\n" +
"Connection: close\r\n";

var body = $"{challengeCode}\r\n";

var ret = header + "\r\n" + body;
return Encoding.UTF8.GetBytes(ret);
}

private static async Task HandleRequest(TcpClient client, string token, string keyAuthorization, CancellationToken cancellationToken)
{
await using var stream = client.GetStream();
var headers = await HttpUtil.ParseHeadersAsync(stream, cancellationToken)
?? throw new Exception("Connection has been closed before receiving any request.");

if (!headers.Any()) return;
var requestPart = headers[HttpUtil.HttpRequestKey];
var requestParts = requestPart.Split(' ');
var url = "/ok";

if (requestParts.Length > 1 && requestParts[0] == "GET" && requestParts[1] == url)
{
var response = BuildHttp01Response("sss");
await stream.WriteAsync(response, 0, response.Length, cancellationToken);
}
var request = headers[HttpUtil.HttpRequestKey];
var requestParts = request.Split(' ');
var expectedUrl = $"/.well-known/acme-challenge/{token}";
var isMatched = requestParts.Length > 1 && requestParts[0] == "GET" && requestParts[1] == expectedUrl;

VhLogger.Instance.LogInformation(GeneralEventId.Acme, "HTTP Challenge. Request: {request}, IsMatched: {isMatched}", request, isMatched);

var response = (isMatched)
? HttpResponseBuilder.Http01(keyAuthorization)
: HttpResponseBuilder.BadRequest();

await stream.WriteAsync(response, 0, response.Length, cancellationToken);
await stream.FlushAsync(cancellationToken);
}

public void Stop()
// use dispose
private void Stop()
{
if (!IsStarted || _disposed)
if (!IsStarted || _disposed)
return;

foreach (var listener in _tcpListeners)
Expand All @@ -100,15 +98,16 @@ public void Stop()
}

_tcpListeners.Clear();
_cancellationTokenSource.Cancel();
IsStarted = false;
}

public void Dispose()
{
if (_disposed)
if (_disposed)
return;

if (IsStarted)
if (IsStarted)
Stop();

_disposed = true;
Expand Down
57 changes: 57 additions & 0 deletions VpnHood.Server/HttpResponseBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Net;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Text;

namespace VpnHood.Server;

internal static class HttpResponseBuilder
{
public static byte[] Build(HttpResponseMessage httpResponse)
{
var context = httpResponse.Content.ReadAsStringAsync().Result;
httpResponse.Headers.Date = DateTimeOffset.Now;
httpResponse.Content.Headers.ContentLength = context.Length;

var response = $"HTTP/{httpResponse.Version.Major}.{httpResponse.Version.Minor} {(int)httpResponse.StatusCode} {httpResponse.ReasonPhrase}\r\n";
response = httpResponse.Headers.Aggregate(response, (current, header) => current + $"{header.Key}: {string.Join(", ", header.Value)}\r\n");
response = httpResponse.Content.Headers.Aggregate(response, (current, header) => current + $"{header.Key}: {string.Join(", ", header.Value)}\r\n");
response += "\r\n" + context;
return Encoding.UTF8.GetBytes(response);
}

public static byte[] Ok()
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
return Build(response);
}

public static byte[] Unauthorized()
{
var response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Bearer"));
return Build(response);
}

public static byte[] Http01(string keyAuthorization)
{
var response = new HttpResponseMessage(HttpStatusCode.BadRequest);
response.Headers.ConnectionClose = true;
response.Content = new StringContent(keyAuthorization, Encoding.Default, MediaTypeNames.Text.Plain);
return Build(response);
}

public static byte[] BadRequest()
{
var response = new HttpResponseMessage(HttpStatusCode.BadRequest);
response.Headers.ConnectionClose = true;
return Build(response);
}

public static byte[] NotFound()
{
var response = new HttpResponseMessage(HttpStatusCode.NotFound);
response.Headers.ConnectionClose = true;
return Build(response);
}
}
53 changes: 0 additions & 53 deletions VpnHood.Server/HttpResponses.cs

This file was deleted.

Loading

0 comments on commit af101c5

Please sign in to comment.