diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 61e40c54..d7366be0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -6,20 +6,36 @@ jobs: build_and_test: name: Build & Test runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + include: + - dotnet_version: "3.1.x" + flag: "" + - dotnet_version: "7.0.x" + flag: "-p:NET7=true" steps: - uses: actions/checkout@v2 with: submodules: recursive - - name: Setup .NET Core SDK 3.1.x + - name: Setup .NET SDK ${{ matrix.dotnet_version }} uses: actions/setup-dotnet@v1.7.2 with: - dotnet-version: '3.1.x' + dotnet-version: ${{ matrix.dotnet_version }} - name: Install dependencies - run: dotnet restore + run: dotnet restore ${{ matrix.flag }} - name: Build - run: dotnet build --configuration Release --no-restore + run: dotnet build --configuration Release --no-restore ${{ matrix.flag }} + # Please keep in mind that NOnion DOES NOT require tor client to function + # tor client is only installed here for testing purposes. + - name: Install Tor and wait for startup + run: | + sudo apt install tor + echo -e "SOCKSPort 127.0.0.1:9050" | sudo tee -a /etc/tor/torrc + sudo systemctl restart tor + sleep 2m - name: Test - run: dotnet test --no-restore --verbosity normal + run: dotnet test --no-restore --verbosity normal ${{ matrix.flag }} sanity_check: name: Sanity Check diff --git a/NOnion.Tests/HiddenServicesTests.cs b/NOnion.Tests/HiddenServicesTests.cs index 2079c957..a675ed2d 100644 --- a/NOnion.Tests/HiddenServicesTests.cs +++ b/NOnion.Tests/HiddenServicesTests.cs @@ -2,9 +2,12 @@ using System; using System.IO; using System.Linq; +using System.Net; +using System.Net.Http; using System.Net.Security; using System.Security.Authentication; using System.Security.Cryptography; +using System.Text; using System.Threading.Tasks; using NUnit.Framework; @@ -133,7 +136,7 @@ public void CanBrowseFacebookOverHSWithTLS() Assert.DoesNotThrowAsync(BrowseFacebookOverHSWithTLS); } - public async Task EstablishAndCommunicateOverHSConnectionOnionStyle() + private async Task<(TorDirectory, TorServiceHost)> BootstrapDirectoryAndStartHost() { int descriptorUploadRetryLimit = 2; @@ -151,6 +154,13 @@ public async Task EstablishAndCommunicateOverHSConnectionOnionStyle() TorLogger.Log("Finished starting HS host"); + return (directory, host); + } + + public async Task EstablishAndCommunicateOverHSConnectionOnionStyle() + { + (var directory, var host) = await BootstrapDirectoryAndStartHost(); + var dataToSendAndReceive = new byte[] { 1, 2, 3, 4 }; var serverSide = @@ -185,6 +195,68 @@ public void CanEstablishAndCommunicateOverHSConnectionOnionStyle() { Assert.DoesNotThrowAsync(EstablishAndCommunicateOverHSConnectionOnionStyle); } + +#if NET6_0_OR_GREATER + [Test] + [Retry(TestsRetryCount)] + public void CanConnectToHiddenServiceUsingTorClient() + { + Assert.DoesNotThrowAsync(ConnectToHiddenServiceUsingTorClient); + } + + private async Task ConnectToHiddenServiceUsingTorClient() + { + (_, var host) = await BootstrapDirectoryAndStartHost(); + + var stringToSendAndReceive = + "We are using tor!"; + + var serverSide = + Task.Run(async () => { + var stream = await host.AcceptClientAsync(); + + var httpResponse = + "HTTP/1.1 200 OK\r\n" + + "Server: NOnion\r\n" + + $"Content-Length: {stringToSendAndReceive.Length}\r\n" + + "Connection: close\r\n" + + "Content-Type: text/plain" + + "\r\n" + + "\r\n" + + stringToSendAndReceive + + "\r\n"; + var httpResponseBytes = + Encoding.ASCII.GetBytes(httpResponse); + + await stream.WriteAsync(httpResponseBytes, 0, httpResponseBytes.Length); + await stream.EndAsync(); + }); + + var clientSide = + Task.Run(async () => { + var handler = new HttpClientHandler + { + Proxy = new WebProxy(new Uri("socks5://localhost:9050")) + }; + + TestContext.Progress.WriteLine("Trying to connect to hidden service..."); + using (handler) + using (var httpClient = new HttpClient(handler)) + { + // Sometimes tor client takes a while to bootstrap and stalls + // the request. + httpClient.Timeout = TimeSpan.FromMinutes(20); + var result = await httpClient.GetStringAsync("http://" + host.ExportUrl()); + Assert.AreEqual(result, stringToSendAndReceive); + } + } + ); + + await TaskUtils.WhenAllFailFast(serverSide, clientSide); + + ((IDisposable)host).Dispose(); + } +#endif } } diff --git a/NOnion.Tests/NOnion.Tests.csproj b/NOnion.Tests/NOnion.Tests.csproj index e9a8683d..ac97323d 100644 --- a/NOnion.Tests/NOnion.Tests.csproj +++ b/NOnion.Tests/NOnion.Tests.csproj @@ -1,8 +1,8 @@  - netcoreapp3.1 - + netcoreapp3.1 + net7.0 false