From 420e8dba624076bb87f61879a5d3093ce34446f5 Mon Sep 17 00:00:00 2001 From: Afshin Arani Date: Sun, 23 Apr 2023 16:19:49 +0330 Subject: [PATCH 1/4] Client,Network,Services: add TorClient This commit aims to introduce a simple API for end users. Working with network especially Tor routers is flaky and delegating retry logic implementation to users causes NOnion to be unreliable in CI and in normal use, this commit introduces retry logic in some places where it's needed the most. This should hopefully make NOnion more reliable. --- NOnion.Tests/HiddenServicesTests.cs | 59 +- NOnion.Tests/TorClientTests.cs | 47 ++ NOnion/Client/TorClient.fs | 280 +++++++ NOnion/Exceptions.fs | 3 + NOnion/NOnion.fsproj | 2 + NOnion/Services/TorServiceClient.fs | 83 +- NOnion/Services/TorServiceHost.fs | 162 ++-- NOnion/fallback_dirs.inc | 1102 +++++++++++++++++++++++++++ 8 files changed, 1558 insertions(+), 180 deletions(-) create mode 100644 NOnion.Tests/TorClientTests.cs create mode 100644 NOnion/Client/TorClient.fs create mode 100644 NOnion/fallback_dirs.inc diff --git a/NOnion.Tests/HiddenServicesTests.cs b/NOnion.Tests/HiddenServicesTests.cs index f75c1473..72ddbd2e 100644 --- a/NOnion.Tests/HiddenServicesTests.cs +++ b/NOnion.Tests/HiddenServicesTests.cs @@ -16,6 +16,7 @@ using NOnion.Network; using NOnion.Http; using NOnion.Cells.Relay; +using NOnion.Client; using NOnion.Directory; using NOnion.Tests.Utility; using NOnion.Services; @@ -24,6 +25,23 @@ namespace NOnion.Tests { public class HiddenServicesTests { + [OneTimeSetUp] + public void Init() + { + cachePath = + new DirectoryInfo( + Path.Combine( + Path.GetTempPath(), + Path.GetFileNameWithoutExtension( + Path.GetRandomFileName() + ) + ) + ); + cachePath.Create(); + } + + private DirectoryInfo cachePath = null; + /* It's possible that the router returned by GetRandomFallbackDirectory or * GetRandomRoutersForDirectoryBrowsing be inaccessable so we need to continue * retrying if an exceptions happened to make sure the issues are not related @@ -33,11 +51,8 @@ public class HiddenServicesTests private async Task CreateIntroductionCircuit() { - var node = (CircuitNodeDetail.Create)(await CircuitHelper.GetRandomRoutersForDirectoryBrowsingWithRetry()).First(); - using TorGuard guard = await TorGuard.NewClientAsync(node.EndPoint); - var circuit = new TorCircuit(guard); - - await circuit.CreateAsync(CircuitNodeDetail.FastCreate); + using TorClient torClient = await TorClient.BootstrapWithGithubAsync(cachePath); + var circuit = await torClient.CreateCircuitAsync(1, CircuitPurpose.Unknown, FSharpOption.None); await circuit.RegisterAsIntroductionPointAsync(FSharpOption.None, StubCallback, DisconnectionCallback); } @@ -61,12 +76,8 @@ private async Task CreateRendezvousCircuit() var array = new byte[Constants.RendezvousCookieLength]; RandomNumberGenerator.Create().GetNonZeroBytes(array); - var nodes = await CircuitHelper.GetRandomRoutersForDirectoryBrowsingWithRetry(2); - using TorGuard guard = await TorGuard.NewClientAsync(((CircuitNodeDetail.Create)nodes[0]).EndPoint); - var circuit = new TorCircuit(guard); - - await circuit.CreateAsync(nodes[0]); - await circuit.ExtendAsync(nodes[1]); + using TorClient torClient = await TorClient.BootstrapWithGithubAsync(cachePath); + var circuit = await torClient.CreateCircuitAsync(2, CircuitPurpose.Unknown, FSharpOption.None); await circuit.RegisterAsRendezvousPointAsync(array); } @@ -92,10 +103,10 @@ private async Task ReadExact(TorStream stream, byte[] buffer, int off, int public async Task BrowseFacebookOverHS() { - TorDirectory directory = await TorDirectory.BootstrapAsync(FallbackDirectorySelector.GetRandomFallbackDirectory(), new DirectoryInfo(Path.GetTempPath())); + using TorClient torClient = await TorClient.BootstrapWithGithubAsync(cachePath); - var client = await TorServiceClient.ConnectAsync(directory, "facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion"); - var httpClient = new TorHttpClient(client.GetStream(), "facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion"); + var serviceClient = await TorServiceClient.ConnectAsync(torClient, "facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion"); + var httpClient = new TorHttpClient(serviceClient.GetStream(), "facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion"); try { @@ -117,11 +128,11 @@ public void CanBrowseFacebookOverHS() public async Task BrowseFacebookOverHSWithTLS() { - TorDirectory directory = await TorDirectory.BootstrapAsync(FallbackDirectorySelector.GetRandomFallbackDirectory(), new DirectoryInfo(Path.GetTempPath())); - - var client = await TorServiceClient.ConnectAsync(directory, "facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion:443"); + using TorClient torClient = await TorClient.BootstrapWithGithubAsync(cachePath); + + var serviceClient = await TorServiceClient.ConnectAsync(torClient, "facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion:443"); - var sslStream = new SslStream(client.GetStream(), true, (sender, cert, chain, sslPolicyErrors) => true); + var sslStream = new SslStream(serviceClient.GetStream(), true, (sender, cert, chain, sslPolicyErrors) => true); await sslStream.AuthenticateAsClientAsync(string.Empty, null, SslProtocols.Tls12, false); var httpClientOverSslStream = new TorHttpClient(sslStream, "www.facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion"); @@ -147,10 +158,8 @@ public void CanBrowseFacebookOverHSWithTLS() public async Task EstablishAndCommunicateOverHSConnectionOnionStyle() { - int descriptorUploadRetryLimit = 2; - - TorDirectory directory = await TorDirectory.BootstrapAsync(FallbackDirectorySelector.GetRandomFallbackDirectory(), new DirectoryInfo(Path.GetTempPath())); - + using TorClient torClient = await TorClient.BootstrapWithGithubAsync(cachePath); + TorLogger.Log("Finished bootstraping"); SecureRandom random = new SecureRandom(); @@ -158,7 +167,7 @@ public async Task EstablishAndCommunicateOverHSConnectionOnionStyle() kpGen.Init(new Ed25519KeyGenerationParameters(random)); Ed25519PrivateKeyParameters masterPrivateKey = (Ed25519PrivateKeyParameters)kpGen.GenerateKeyPair().Private; - TorServiceHost host = new TorServiceHost(directory, descriptorUploadRetryLimit, TestsRetryCount, FSharpOption.Some(masterPrivateKey)); + TorServiceHost host = new TorServiceHost(torClient, FSharpOption.Some(masterPrivateKey)); await host.StartAsync(); TorLogger.Log("Finished starting HS host"); @@ -175,8 +184,8 @@ public async Task EstablishAndCommunicateOverHSConnectionOnionStyle() var clientSide = Task.Run(async () => { - var client = await TorServiceClient.ConnectAsync(directory, host.ExportUrl()); - var stream = client.GetStream(); + var serviceClient = await TorServiceClient.ConnectAsync(torClient, host.ExportUrl()); + var stream = serviceClient.GetStream(); var lengthBytes = new byte[sizeof(int)]; await ReadExact(stream, lengthBytes, 0, lengthBytes.Length); var length = BitConverter.ToInt32(lengthBytes); diff --git a/NOnion.Tests/TorClientTests.cs b/NOnion.Tests/TorClientTests.cs new file mode 100644 index 00000000..c7cb3ef4 --- /dev/null +++ b/NOnion.Tests/TorClientTests.cs @@ -0,0 +1,47 @@ +using Microsoft.FSharp.Core; +using System.IO; +using System.Threading.Tasks; + +using NUnit.Framework; + +using NOnion.Client; + +namespace NOnion.Tests +{ + public class TorClientTests + { + private async Task BootstrapWithGithub() + { + await TorClient.BootstrapWithGithubAsync(FSharpOption.None); + } + + [Test] + public void CanBootstrapWithGithub() + { + Assert.DoesNotThrowAsync(BootstrapWithGithub); + } + + private async Task BootstrapWithEmbeddedList() + { + await TorClient.BootstrapWithEmbeddedListAsync(FSharpOption.None); + } + + [Test] + public void CanBootstrapWithEmbeddedList() + { + Assert.DoesNotThrowAsync(BootstrapWithEmbeddedList); + } + + private async Task CreateCircuit() + { + using TorClient client = await TorClient.BootstrapWithEmbeddedListAsync(FSharpOption.None); + await client.CreateCircuitAsync(3, CircuitPurpose.Unknown, FSharpOption.None); + } + + [Test] + public void CanCreateCircuit() + { + Assert.DoesNotThrowAsync(CreateCircuit); + } + } +} diff --git a/NOnion/Client/TorClient.fs b/NOnion/Client/TorClient.fs new file mode 100644 index 00000000..b23b02d0 --- /dev/null +++ b/NOnion/Client/TorClient.fs @@ -0,0 +1,280 @@ +namespace NOnion.Client + +open System +open System.Collections.Concurrent +open System.IO +open System.Net +open System.Net.Http +open System.Text.RegularExpressions + +open NOnion.Directory +open NOnion.Utility +open NOnion +open NOnion.Network + +type CircuitPurpose = + | Unknown + | Exit + +type TorClient internal (directory: TorDirectory) = + static let maximumBootstrapTries = 5 + + static let maximumExtendByNodeRetry = 5 + + static let ConvertFallbackIncToList(fallbackIncString: string) = + let ipv4Pattern = "\"([0-9\\.]+)\\sorport=(\\S*)\\sid=(\\S*)\"" + let matches = Regex.Matches(fallbackIncString, ipv4Pattern) + + matches + |> Seq.cast + |> Seq.map(fun (regMatch: Match) -> + regMatch.Groups.[1].Value, int regMatch.Groups.[2].Value + ) + |> Seq.toList + + static let SelectRandomEndpoints(fallbackList: List) = + fallbackList + |> SeqUtils.TakeRandom maximumBootstrapTries + |> Seq.map(fun (ipString, port) -> + let ipAddress = IPAddress.Parse ipString + IPEndPoint(ipAddress, port) + ) + |> Seq.toList + + static let BootstrapDirectory + (cachePath: Option) + (ipEndPointList: List) + = + async { + let rec tryBootstrap(ipEndPointList: List) = + async { + match ipEndPointList with + | ipEndPoint :: tail -> + try + let cacheDirectory = + match cachePath with + | None -> + let tempDir = + DirectoryInfo( + Path.Combine( + Path.GetTempPath(), + Path.GetFileNameWithoutExtension( + Path.GetRandomFileName() + ) + ) + ) + + tempDir.Create() + tempDir + | Some path -> path + + let! directory = + TorDirectory.Bootstrap ipEndPoint cacheDirectory + + return directory + with + | :? NOnionException -> return! tryBootstrap tail + | [] -> return failwith "Maximum bootstrap tries reached!" + } + + return! tryBootstrap ipEndPointList + } + + static let CreateClientFromFallbackString + (fallbackListString: string) + (cachePath: Option) + = + async { + let! directory = + fallbackListString + |> ConvertFallbackIncToList + |> SelectRandomEndpoints + |> BootstrapDirectory cachePath + + return new TorClient(directory) + } + + let guardsToDispose = ConcurrentBag() + + static member AsyncBootstrapWithEmbeddedList + (cachePath: Option) + = + async { + let fallbackListString = + EmbeddedResourceUtility.ExtractEmbeddedResourceFileContents( + "fallback_dirs.inc" + ) + + return! CreateClientFromFallbackString fallbackListString cachePath + } + + static member BootstrapWithEmbeddedListAsync + (cachePath: Option) + = + TorClient.AsyncBootstrapWithEmbeddedList cachePath |> Async.StartAsTask + + static member AsyncBootstrapWithGithub(cachePath: Option) = + async { + // Don't put this inside the fallbackListString or it gets disposed + // before the task gets executed + use httpClient = new HttpClient() + + let! fallbackListString = + let urlToTorServerList = + "https://raw.githubusercontent.com/torproject/tor/main/src/app/config/fallback_dirs.inc" + + httpClient.GetStringAsync urlToTorServerList |> Async.AwaitTask + + return! CreateClientFromFallbackString fallbackListString cachePath + } + + static member BootstrapWithGithubAsync(cachePath: Option) = + TorClient.AsyncBootstrapWithGithub cachePath |> Async.StartAsTask + + member __.Directory = directory + + member internal __.AsyncCreateCircuitWithCallback + (hopsCount: int) + (purpose: CircuitPurpose) + (extendByNodeOpt: Option) + (serviceStream: uint16 -> TorCircuit -> Async) + = + async { + let rec createNewGuard() = + async { + let! ipEndPoint, nodeDetail = + directory.GetRouter RouterType.Guard + + try + let! guard = + TorGuard.NewClientWithIdentity + ipEndPoint + (nodeDetail.GetIdentityKey() |> Some) + + guardsToDispose.Add guard + return guard, nodeDetail + with + | :? GuardConnectionFailedException -> + return! createNewGuard() + } + + let rec tryCreateCircuit(tryNumber: int) = + async { + if tryNumber > maximumExtendByNodeRetry then + return raise <| DestinationNodeCantBeReachedException() + else + try + let! guard, guardDetail = createNewGuard() + let circuit = TorCircuit(guard, serviceStream) + + do! + circuit.Create guardDetail + |> Async.Ignore + + let rec extend + (numHopsToExtend: int) + (nodesSoFar: List) + = + async { + if numHopsToExtend > 0 then + let rec findUnusedNode() = + async { + let! _ipEndPoint, nodeDetail = + if numHopsToExtend = 1 then + match purpose with + | Unknown -> + directory.GetRouter + RouterType.Normal + | Exit -> + directory.GetRouter + RouterType.Exit + else + directory.GetRouter + RouterType.Normal + + if (List.contains + nodeDetail + nodesSoFar) then + return! findUnusedNode() + else + return nodeDetail + } + + let! newUnusedNode = findUnusedNode() + + do! + circuit.Extend newUnusedNode + |> Async.Ignore + + return! + extend + (numHopsToExtend - 1) + (newUnusedNode :: nodesSoFar) + else + () + } + + do! + extend + (hopsCount - 1) + (List.singleton guardDetail) + + match extendByNodeOpt with + | Some extendByNode -> + try + do! + circuit.Extend extendByNode + |> Async.Ignore + with + | :? NOnionException -> + return + raise + <| DestinationNodeCantBeReachedException + () + | None -> () + + return circuit + with + | :? DestinationNodeCantBeReachedException -> + return! tryCreateCircuit(tryNumber + 1) + | ex -> + match FSharpUtil.FindException ex + with + | Some _nonionEx -> + return! tryCreateCircuit tryNumber + | None -> return raise <| FSharpUtil.ReRaise ex + } + + let startTryNumber = 1 + + return! tryCreateCircuit startTryNumber + } + + member self.AsyncCreateCircuit + (hopsCount: int) + (purpose: CircuitPurpose) + (extendByNodeOpt: Option) + = + let noop _ _ = + async { return () } + + self.AsyncCreateCircuitWithCallback + hopsCount + purpose + extendByNodeOpt + noop + + member self.CreateCircuitAsync + ( + hopsCount: int, + purpose: CircuitPurpose, + extendByNode: Option + ) = + self.AsyncCreateCircuit hopsCount purpose extendByNode + |> Async.StartAsTask + + + interface IDisposable with + member __.Dispose() = + for guard in guardsToDispose do + (guard :> IDisposable).Dispose() diff --git a/NOnion/Exceptions.fs b/NOnion/Exceptions.fs index 98c7ab94..757f34ab 100644 --- a/NOnion/Exceptions.fs +++ b/NOnion/Exceptions.fs @@ -53,3 +53,6 @@ type NOnionSocketException "Got socket exception during data transfer", innerException ) + +type DestinationNodeCantBeReachedException() = + inherit NOnionException("Destination node can't be reached") diff --git a/NOnion/NOnion.fsproj b/NOnion/NOnion.fsproj index 904f1ae7..c5e3b282 100644 --- a/NOnion/NOnion.fsproj +++ b/NOnion/NOnion.fsproj @@ -13,6 +13,7 @@ + @@ -85,6 +86,7 @@ + diff --git a/NOnion/Services/TorServiceClient.fs b/NOnion/Services/TorServiceClient.fs index 9264dfbc..074de3e3 100644 --- a/NOnion/Services/TorServiceClient.fs +++ b/NOnion/Services/TorServiceClient.fs @@ -12,6 +12,7 @@ open Org.BouncyCastle.Security open NOnion open NOnion.Cells.Relay +open NOnion.Client open NOnion.Crypto open NOnion.Utility open NOnion.Directory @@ -21,7 +22,7 @@ open NOnion.Network type TorServiceClient = private { - RendezvousGuard: TorGuard + TorClient: TorClient RendezvousCircuit: TorCircuit Stream: TorStream } @@ -29,16 +30,16 @@ type TorServiceClient = member self.GetStream() = self.Stream - static member ConnectAsync (directory: TorDirectory) (url: string) = - TorServiceClient.Connect directory url |> Async.StartAsTask + static member ConnectAsync (client: TorClient) (url: string) = + TorServiceClient.Connect client url |> Async.StartAsTask - static member Connect (directory: TorDirectory) (url: string) = + static member Connect (client: TorClient) (url: string) = async { let publicKey, port = HiddenServicesUtility.DecodeOnionUrl url let getIntroductionPointInfo() = async { - let! networkStatus = directory.GetLiveNetworkStatus() + let! networkStatus = client.Directory.GetLiveNetworkStatus() let periodNum, periodLength = networkStatus.GetTimePeriod() let srv = networkStatus.GetCurrentSRVForClient() @@ -49,7 +50,7 @@ type TorServiceClient = publicKey let! responsibleDirs = - directory.GetResponsibleHiddenServiceDirectories + client.Directory.GetResponsibleHiddenServiceDirectories blindedPublicKey srv periodNum @@ -64,36 +65,16 @@ type TorServiceClient = raise <| DescriptorDownloadFailedException() | hsDirectory :: tail -> try - let! guardEndPoint, randomGuardNode = - directory.GetRouter RouterType.Guard - - let! _, randomMiddleNode = - directory.GetRouter RouterType.Normal - let! hsDirectoryNode = - directory.GetCircuitNodeDetailByIdentity + client.Directory.GetCircuitNodeDetailByIdentity hsDirectory - use! guardNode = - TorGuard.NewClientWithIdentity - guardEndPoint - (randomGuardNode.GetIdentityKey() - |> Some) - - let circuit = TorCircuit guardNode - - do! - circuit.Create randomGuardNode - |> Async.Ignore - - do! - circuit.Extend randomMiddleNode - |> Async.Ignore - try - do! - circuit.Extend hsDirectoryNode - |> Async.Ignore + let! circuit = + client.AsyncCreateCircuit + 2 + CircuitPurpose.Unknown + (Some hsDirectoryNode) use dirStream = new TorStream(circuit) @@ -394,18 +375,14 @@ type TorServiceClient = .Create() .GetNonZeroBytes randomGeneratedCookie - let! endpoint, guardnode = directory.GetRouter RouterType.Guard - let! _, rendezvousNode = directory.GetRouter RouterType.Normal + let! _, rendezvousNode = + client.Directory.GetRouter RouterType.Normal - let! rendezvousGuard = - TorGuard.NewClientWithIdentity - endpoint - (guardnode.GetIdentityKey() |> Some) - - let rendezvousCircuit = TorCircuit rendezvousGuard - - do! rendezvousCircuit.Create guardnode |> Async.Ignore - do! rendezvousCircuit.Extend rendezvousNode |> Async.Ignore + let! rendezvousCircuit = + client.AsyncCreateCircuit + 1 + CircuitPurpose.Unknown + (Some rendezvousNode) do! rendezvousCircuit.RegisterAsRendezvousPoint @@ -438,7 +415,7 @@ type TorServiceClient = ] } - let! networkStatus = directory.GetLiveNetworkStatus() + let! networkStatus = client.Directory.GetLiveNetworkStatus() let periodInfo = networkStatus.GetTimePeriod() let data, macKey = @@ -471,13 +448,11 @@ type TorServiceClient = macKey } - let introCircuit = TorCircuit rendezvousGuard - - do! introCircuit.Create guardnode |> Async.Ignore - - do! - introCircuit.Extend introductionPointNodeDetail - |> Async.Ignore + let! introCircuit = + client.AsyncCreateCircuit + 1 + Unknown + (Some introductionPointNodeDetail) let rendezvousJoin = rendezvousCircuit.WaitingForRendezvousJoin @@ -507,7 +482,7 @@ type TorServiceClient = return { - RendezvousGuard = rendezvousGuard + TorClient = client RendezvousCircuit = rendezvousCircuit Stream = serviceStream } @@ -515,7 +490,3 @@ type TorServiceClient = return failwith "Never happens. GetRouter never returns FastCreate" } - - interface IDisposable with - member self.Dispose() = - (self.RendezvousGuard :> IDisposable).Dispose() diff --git a/NOnion/Services/TorServiceHost.fs b/NOnion/Services/TorServiceHost.fs index 2fb2beab..25f9b595 100644 --- a/NOnion/Services/TorServiceHost.fs +++ b/NOnion/Services/TorServiceHost.fs @@ -19,6 +19,7 @@ open Org.BouncyCastle.Security open NOnion open NOnion.Cells.Relay open NOnion.Crypto +open NOnion.Client open NOnion.Directory open NOnion.Utility open NOnion.Network @@ -36,9 +37,7 @@ type IntroductionPointInfo = type TorServiceHost ( - directory: TorDirectory, - maxDescriptorUploadRetryCount: int, - maxRendezvousConnectRetryCount: int, + client: TorClient, maybeMasterPrivateKey: Option ) = @@ -125,28 +124,19 @@ type TorServiceHost introEncPubKey = async { - let! endPoint, randomNodeDetails = - directory.GetRouter RouterType.Guard - - let! guard = - TorGuard.NewClientWithIdentity - endPoint - (randomNodeDetails.GetIdentityKey() |> Some) - - let rendezvousCircuit = - TorCircuit(guard, self.IncomingServiceStreamCallback) - - do! rendezvousCircuit.Create randomNodeDetails |> Async.Ignore - - do! - rendezvousCircuit.Extend( - CircuitNodeDetail.Create( - rendezvousEndpoint, - onionKey, - rendezvousFingerPrint - ) + let lastNodeDetails = + CircuitNodeDetail.Create( + rendezvousEndpoint, + onionKey, + rendezvousFingerPrint ) - |> Async.Ignore + + let! rendezvousCircuit = + client.AsyncCreateCircuitWithCallback + 2 + CircuitPurpose.Unknown + (Some lastNodeDetails) + self.IncomingServiceStreamCallback do! rendezvousCircuit.Rendezvous @@ -181,7 +171,7 @@ type TorServiceHost introductionPointDetails.EncryptionKey.Private :?> X25519PrivateKeyParameters - let! networkStatus = directory.GetLiveNetworkStatus() + let! networkStatus = client.Directory.GetLiveNetworkStatus() let periodInfo = networkStatus.GetTimePeriod() let decryptedData, macKey = @@ -237,7 +227,7 @@ type TorServiceHost | Some linkSpecifier -> linkSpecifier.Data | None -> failwith "No rendezvous fingerprint found!" - let connectToRendezvousJob = + do! tryConnectingToRendezvous rendezvousEndpoint rendezvousFingerPrint @@ -248,11 +238,6 @@ type TorServiceHost introEncPrivKey introEncPubKey - do! - FSharpUtil.Retry - connectToRendezvousJob - maxRendezvousConnectRetryCount - return () } @@ -265,10 +250,10 @@ type TorServiceHost async { try let! guardEndPoint, guardNodeDetail = - directory.GetRouter RouterType.Guard + client.Directory.GetRouter RouterType.Guard let! _, introNodeDetail = - directory.GetRouter RouterType.Normal + client.Directory.GetRouter RouterType.Normal match introNodeDetail with | FastCreate -> @@ -368,73 +353,52 @@ type TorServiceHost member self.UploadDescriptor (directoryToUploadTo: string) (document: HiddenServiceFirstLayerDescriptorDocument) - (retry: int) = async { - if retry > maxDescriptorUploadRetryCount then - return () - else - try - let! hsDirectoryNode = - directory.GetCircuitNodeDetailByIdentity - directoryToUploadTo - - let! guardEndPoint, randomGuardNode = - directory.GetRouter RouterType.Guard - - let! _, randomMiddleNode = - directory.GetRouter RouterType.Normal - - use! guardNode = - TorGuard.NewClientWithIdentity - guardEndPoint - (randomGuardNode.GetIdentityKey() |> Some) - - let circuit = TorCircuit guardNode - do! circuit.Create randomGuardNode |> Async.Ignore - do! circuit.Extend randomMiddleNode |> Async.Ignore - do! circuit.Extend hsDirectoryNode |> Async.Ignore - - use dirStream = new TorStream(circuit) - do! dirStream.ConnectToDirectory() |> Async.Ignore - - let! _response = - TorHttpClient( - dirStream, - Constants.DefaultHttpHost - ) - .PostString - (sprintf - "/tor/hs/%i/publish" - Constants.HiddenServices.Version) - (document.ToString()) - - TorLogger.Log( - sprintf - "TorServiceHost: descriptor uploaded to node with identity %s" - directoryToUploadTo - ) - - return () - with - | :? UnsuccessfulHttpResponseException -> - // During testing, after migration to microdescriptor, we saw instances of - // 404 error msg when trying to publish our descriptors which mean for - // some reason we're trying to upload descriptor to a directory that - // is not a hidden service directory, there is no point in retrying here. - return () - | ex -> - TorLogger.Log( - sprintf - "TorServiceHost: hs descriptor upload failed, ex=%s" - (ex.ToString()) + try + let! hsDirectoryNode = + client.Directory.GetCircuitNodeDetailByIdentity + directoryToUploadTo + + let! circuit = + client.AsyncCreateCircuit + 2 + CircuitPurpose.Unknown + (Some hsDirectoryNode) + + use dirStream = new TorStream(circuit) + do! dirStream.ConnectToDirectory() |> Async.Ignore + + let! _response = + TorHttpClient( + dirStream, + Constants.DefaultHttpHost ) + .PostString + (sprintf + "/tor/hs/%i/publish" + Constants.HiddenServices.Version) + (document.ToString()) + + TorLogger.Log( + sprintf + "TorServiceHost: descriptor uploaded to node with identity %s" + directoryToUploadTo + ) - return! - self.UploadDescriptor - directoryToUploadTo - document - (retry + 1) + return () + with + | :? DestinationNodeCantBeReachedException + | :? UnsuccessfulHttpResponseException -> + // During testing, after migration to microdescriptor, we saw instances of + // 404 error msg when trying to publish our descriptors which mean for + // some reason we're trying to upload descriptor to a directory that + // is not a hidden service directory, there is no point in retrying here. + + // TorClient tries multiple times with different circuit to connect to + // the directory, if destination node can't be reached with any circuit + // we stop trying. + return () } member self.BuildAndUploadDescriptor @@ -450,7 +414,7 @@ type TorServiceHost (masterPublicKey.GetEncoded()) let! responsibleDirs = - directory.GetResponsibleHiddenServiceDirectories + client.Directory.GetResponsibleHiddenServiceDirectories blindedPublicKey srv periodNum @@ -698,7 +662,7 @@ type TorServiceHost let jobs = responsibleDirs - |> Seq.map(fun dir -> self.UploadDescriptor dir outerWrapper 1) + |> Seq.map(fun dir -> self.UploadDescriptor dir outerWrapper) do! Async.Parallel( @@ -756,7 +720,7 @@ type TorServiceHost //TODO: this should refresh every 60-120min member self.KeepDescriptorsUpToDate() = async { - let! networkStatus = directory.GetLiveNetworkStatus() + let! networkStatus = client.Directory.GetLiveNetworkStatus() let firstDescriptorBuildJob = self.UpdateFirstDescriptor networkStatus diff --git a/NOnion/fallback_dirs.inc b/NOnion/fallback_dirs.inc new file mode 100644 index 00000000..1302099e --- /dev/null +++ b/NOnion/fallback_dirs.inc @@ -0,0 +1,1102 @@ +/* type=fallback */ +/* version=4.0.0 */ +/* timestamp=20210412000000 */ +/* source=offer-list */ +// +// Generated on: Thu, 12 Jan 2023 16:00:16 +0000 + +"142.132.165.154 orport=443 id=6D9E22C1F4F0E99867F98F2546A9B76D5F08B4CF" +" ipv6=[2a01:4f8:1c1c:43c::1]:443" +/* nickname=libreapp01 */ +/* extrainfo=0 */ +/* ===== */ +, +"18.18.82.18 orport=9001 id=BF54EE3193751481579BA7CC7D8E1DF0A01AFB30" +/* nickname=gesdm */ +/* extrainfo=0 */ +/* ===== */ +, +"72.92.146.128 orport=9001 id=C5E420FAF05680EE590542AE7216C77602FE68DC" +/* nickname=TreeFiddy */ +/* extrainfo=0 */ +/* ===== */ +, +"116.203.17.238 orport=9001 id=28090710ABE433A47021F22208B3EC245A912900" +/* nickname=dismail */ +/* extrainfo=0 */ +/* ===== */ +, +"116.203.50.182 orport=8080 id=00E1649E69FF91D7F01E74A5E62EF14F7D9915E4" +" ipv6=[2a01:4f8:1c1c:b16b::1]:8080" +/* nickname=dragonhoard */ +/* extrainfo=0 */ +/* ===== */ +, +"144.76.154.13 orport=9001 id=10A5EFCCD2FB9C1A4AC20FB779A5DB11B58957A7" +" ipv6=[2a01:4f8:200:2211::2]:9001" +/* nickname=eridanus */ +/* extrainfo=0 */ +/* ===== */ +, +"94.46.171.245 orport=9001 id=904F36E7AFE6346F5D1D66971F920FFCC47DF120" +/* nickname=sunandfun03 */ +/* extrainfo=0 */ +/* ===== */ +, +"176.9.38.121 orport=9100 id=8284C8A45D22F2981C4B6287C7FB4367116E7CCE" +" ipv6=[2a01:4f8:161:353a::2]:9100" +/* nickname=Turik */ +/* extrainfo=0 */ +/* ===== */ +, +"78.31.67.22 orport=9001 id=6982D789D3875C21433D6EE10838AC5FDC6BA82C" +/* nickname=tor2lhvmct */ +/* extrainfo=0 */ +/* ===== */ +, +"185.220.101.206 orport=443 id=EB9DD80E64DD829A5F7C7ACA5D5FEADFEBFDD847" +" ipv6=[2a0b:f4c2:2:1::206]:443" +/* nickname=ForPrivacyNET */ +/* extrainfo=0 */ +/* ===== */ +, +"185.175.158.198 orport=9090 id=A489D37070A5081D814C1F112139EEF0DDC03A48" +/* nickname=Trurangers2 */ +/* extrainfo=0 */ +/* ===== */ +, +"87.62.96.246 orport=9032 id=E384748293FC4429E2B427360DB4F9D4C3D619D1" +/* nickname=PXArelay02 */ +/* extrainfo=0 */ +/* ===== */ +, +"94.130.246.106 orport=9001 id=1C0736CF3744A3B87C2D2269B8BD3388C7E60552" +" ipv6=[2a01:4f8:10b:3344:106::106]:9001" +/* nickname=FreedomFries2 */ +/* extrainfo=0 */ +/* ===== */ +, +"95.214.54.80 orport=443 id=5A79BD5CC6C128D7D8DFB4969B0246794F117FC6" +" ipv6=[2a03:cfc0:8000:7::5fd6:3647]:443" +/* nickname=bauruine */ +/* extrainfo=0 */ +/* ===== */ +, +"185.220.101.72 orport=9100 id=D3DFB8F9A878F44ED80E2B34F794FDF6334FC5F9" +/* nickname=CCCStuttgartBer */ +/* extrainfo=0 */ +/* ===== */ +, +"51.15.150.228 orport=443 id=46E0487EEEFD694CE625CC6E12D032395C01DB82" +/* nickname=NTH100 */ +/* extrainfo=0 */ +/* ===== */ +, +"51.15.75.120 orport=444 id=0040A5B04C7E309D37CBE7EDB2B72D3E15D057C1" +" ipv6=[2001:bc8:1860:1329::1]:444" +/* nickname=dc6jgk11d */ +/* extrainfo=0 */ +/* ===== */ +, +"185.181.229.77 orport=9001 id=44730B2450213BC3E2DAA4854458D134F0644FF2" +/* nickname=RedLightDistrict */ +/* extrainfo=0 */ +/* ===== */ +, +"91.219.29.94 orport=9001 id=09E0BD68FBAEB7C10107DE67624D25B007FF26A2" +/* nickname=Unnamed */ +/* extrainfo=0 */ +/* ===== */ +, +"51.81.56.195 orport=443 id=EEDB9FEFC9165F9B41B515A282F95A574A807FBA" +/* nickname=trash1 */ +/* extrainfo=0 */ +/* ===== */ +, +"89.147.108.35 orport=9105 id=B30D36FBA3DD300E11916A086D7166A6BE3169FE" +/* nickname=LessIsMore */ +/* extrainfo=0 */ +/* ===== */ +, +"5.255.98.7 orport=443 id=37788F0C00728A44ED8202780D853223EDCA3D3F" +" ipv6=[2a04:52c0:103:ba24::1]:443" +/* nickname=vhult4 */ +/* extrainfo=0 */ +/* ===== */ +, +"144.91.125.15 orport=9001 id=F15A2A08BF91017DCFB6042171635661E13A8256" +" ipv6=[2a02:c207:2033:4966::1]:9001" +/* nickname=WitchNode */ +/* extrainfo=0 */ +/* ===== */ +, +"172.98.15.136 orport=9001 id=518B031A3DF503E08F6F815DB194DBD7B15C9C57" +/* nickname=FrozenChosen */ +/* extrainfo=0 */ +/* ===== */ +, +"138.201.123.109 orport=9001 id=2C13A54E3E8A6AFB18E0DE5890E5B08AAF5B0F36" +/* nickname=history */ +/* extrainfo=0 */ +/* ===== */ +, +"216.250.119.225 orport=9001 id=A56B3845D290791CB26BCE89FE4CE08CF7DC8A2C" +/* nickname=QECm1r4 */ +/* extrainfo=0 */ +/* ===== */ +, +"89.58.54.129 orport=443 id=3B642FF7FE3915C42E20445A1C725A75BAA0A9E3" +" ipv6=[2a03:4000:69:e40::1]:443" +/* nickname=TorRelay1a */ +/* extrainfo=0 */ +/* ===== */ +, +"185.232.70.209 orport=443 id=D36EFFB24481694E384787FAAB80F56AAA5CCD9A" +" ipv6=[2a03:4000:4e:f48:54ac:99ff:fee4:b238]:443" +/* nickname=08eRPfaL2Relay2 */ +/* extrainfo=0 */ +/* ===== */ +, +"109.202.212.1 orport=9001 id=196ABA69C056520E041FAE26EFB329940AB110AF" +" ipv6=[2001:1620:4:d401:29:64aa:f77f:d8e0]:9001" +/* nickname=habo01 */ +/* extrainfo=0 */ +/* ===== */ +, +"185.195.71.3 orport=443 id=3C5915348D731505C48112F4F03235FDE7B8C837" +/* nickname=AccessNow001 */ +/* extrainfo=0 */ +/* ===== */ +, +"212.83.43.93 orport=443 id=B86137AE9681701901C6720E55C16805B46BD8E3" +" ipv6=[2a00:f48:2000:1038:72a7:e81a:29ff:abba]:443" +/* nickname=BeastieJoy60 */ +/* extrainfo=0 */ +/* ===== */ +, +"79.137.196.223 orport=9091 id=47A77C3BC4E50D6DE2D3BF24046C57A72ED1E45F" +/* nickname=VitaminCoin */ +/* extrainfo=0 */ +/* ===== */ +, +"91.208.162.197 orport=8081 id=D3D2E42D8E625D36489015AB1E8081CE520DF2FE" +" ipv6=[2001:678:6d4:5100::a1b]:8081" +/* nickname=pissnissemoldova */ +/* extrainfo=0 */ +/* ===== */ +, +"45.91.77.77 orport=443 id=C2B6ADF4EFEA73CA2EFB2789E2B74C1034C1F5F2" +" ipv6=[2a0f:4ac4:42::704:c0ca:1eaf]:443" +/* nickname=c0ca1eaf */ +/* extrainfo=0 */ +/* ===== */ +, +"82.66.61.19 orport=995 id=40FA09C151C3893B7018DEF55A9854BC9768B82C" +" ipv6=[2a01:e0a:5d6:6de0:acab:3:3:3]:995" +/* nickname=Abeille */ +/* extrainfo=0 */ +/* ===== */ +, +"185.243.218.27 orport=8443 id=5B9086D4BFB9EA36C95897DAED72FC3973847B43" +" ipv6=[2a03:94e0:ffff:185:243:218:0:27]:8443" +/* nickname=bauruine */ +/* extrainfo=0 */ +/* ===== */ +, +"212.83.61.218 orport=443 id=D0562BB74A5CC8872D11B222677009A8922FC38C" +/* nickname=mitropoulos */ +/* extrainfo=0 */ +/* ===== */ +, +"37.200.99.251 orport=9001 id=F6EC46933CE8D4FAD5CCDAA8B1C5A377685FC521" +" ipv6=[2a00:1158:3::1ba]:9001" +/* nickname=JPsi2 */ +/* extrainfo=0 */ +/* ===== */ +, +"94.230.208.147 orport=8443 id=311A4533F7A2415F42346A6C8FA77E6FD279594C" +" ipv6=[2a02:418:6017::147]:8443" +/* nickname=DigiGesTor3e2 */ +/* extrainfo=0 */ +/* ===== */ +, +"54.36.120.156 orport=443 id=D0273C8566CC9AECE4C762376C9B066FE0F1DADD" +/* nickname=Kimchi */ +/* extrainfo=0 */ +/* ===== */ +, +"5.45.102.119 orport=9100 id=189C44DD06312D6DF8FB57A944E6819FF245740C" +" ipv6=[2a03:4000:6:608:942a:42ff:fe77:728c]:9100" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"199.249.230.74 orport=443 id=9C1E7D92115D431385B8CAEA6A7C15FB89CE236B" +" ipv6=[2620:7:6001::ffff:c759:e64a]:80" +/* nickname=QuintexAirVPN21 */ +/* extrainfo=0 */ +/* ===== */ +, +"145.239.206.31 orport=8001 id=912A7C57E05606AF602EC63D1D06BBD5C7AAE516" +" ipv6=[2001:41d0:800:b1f::]:8001" +/* nickname=0x3d02 */ +/* extrainfo=0 */ +/* ===== */ +, +"144.217.90.187 orport=9001 id=7040C1F5728746C5FB5E12845101A26EE8636D7E" +" ipv6=[2607:5300:201:3100::5b0d]:9001" +/* nickname=SaruTorUmidanuki */ +/* extrainfo=0 */ +/* ===== */ +, +"138.201.250.33 orport=9011 id=2BA2C8E96B2590E1072AECE2BDB5C48921BF8510" +/* nickname=storm */ +/* extrainfo=0 */ +/* ===== */ +, +"87.118.116.103 orport=443 id=26C28F29B611DF4DE23ACF5D9DC1EB4895EF5E8B" +" ipv6=[2001:1b60:3:221:4134:101:0:1]:443" +/* nickname=artikel5ev4 */ +/* extrainfo=0 */ +/* ===== */ +, +"199.249.230.110 orport=443 id=7FA8E7E44F1392A4E40FFC3B69DB3B00091B7FD3" +" ipv6=[2620:7:6001::110]:80" +/* nickname=Quintex20 */ +/* extrainfo=0 */ +/* ===== */ +, +"199.249.230.82 orport=443 id=A0DB820FEC87C0405F7BF05DEE5E4ADED2BB9904" +" ipv6=[2620:7:6001::ffff:c759:e652]:80" +/* nickname=QuintexAirVPN29 */ +/* extrainfo=0 */ +/* ===== */ +, +"5.2.72.110 orport=9001 id=5847D5A01C47166143F738C7703344517B39EB10" +/* nickname=7342426259276943 */ +/* extrainfo=0 */ +/* ===== */ +, +"50.39.143.177 orport=59090 id=A1C515432EF6BF2E699A6184ED78DF0B9A595655" +/* nickname=lilonionboi */ +/* extrainfo=0 */ +/* ===== */ +, +"174.128.250.163 orport=443 id=F7A052D4EEA2F4BC942DFB054AF2DC54A2A37E5D" +/* nickname=rockstars1 */ +/* extrainfo=0 */ +/* ===== */ +, +"163.172.213.212 orport=10010 id=CB7DB13172E15D4AD7F9404667021DF7DF6E9A4A" +/* nickname=noconname */ +/* extrainfo=0 */ +/* ===== */ +, +"65.108.10.141 orport=9001 id=7B46F20449D6F25150E189428B62E1E3BA5848A9" +" ipv6=[2a01:4f9:6a:4642::2]:9001" +/* nickname=galtlandeu */ +/* extrainfo=0 */ +/* ===== */ +, +"185.112.156.72 orport=443 id=089E8959D386C4DC283FFDA2B590A65FCE85C8B4" +/* nickname=TheAdoptee */ +/* extrainfo=0 */ +/* ===== */ +, +"15.235.29.234 orport=9001 id=1B3098A711D00ECD428576EB2E868ED4D22C96B1" +/* nickname=BSSP08 */ +/* extrainfo=0 */ +/* ===== */ +, +"135.125.202.252 orport=9001 id=720ABE4554C55EE6F6099491CA55D1F5550512C5" +/* nickname=slotor02 */ +/* extrainfo=0 */ +/* ===== */ +, +"135.148.52.231 orport=443 id=BA6E064596B86AF9F55F0603A82C90E958E86E7A" +/* nickname=twoandtwoone */ +/* extrainfo=0 */ +/* ===== */ +, +"92.222.79.186 orport=443 id=78AA54A1B4169242310499DD81C72EF519B070F3" +/* nickname=CebolaServer */ +/* extrainfo=0 */ +/* ===== */ +, +"213.144.135.21 orport=443 id=BB5FAE50BCE5B13C810CD17A931A0498E4681D41" +" ipv6=[2a02:168:6a16:1130::32:101]:443" +/* nickname=YoYuD1N01NoExit */ +/* extrainfo=0 */ +/* ===== */ +, +"139.162.166.237 orport=443 id=8BEA5AB8F95DE1920775A1A8F4C34B947A7DE505" +/* nickname=shadowdancer */ +/* extrainfo=0 */ +/* ===== */ +, +"95.216.101.247 orport=443 id=38CC95A8CE92A591D4A5779359BEFFBA13FA1B88" +" ipv6=[2a01:4f9:2b:151f:95:216:101:247]:443" +/* nickname=TykRelay02 */ +/* extrainfo=0 */ +/* ===== */ +, +"191.252.111.55 orport=443 id=1D1FA50D605FDC8F6DC39A0A60A7233DD35D0001" +/* nickname=K4M1K4Z3 */ +/* extrainfo=0 */ +/* ===== */ +, +"131.188.40.188 orport=11180 id=EBE718E1A49EE229071702964F8DB1F318075FF8" +" ipv6=[2001:638:a000:4140::ffff:188]:11180" +/* nickname=fluxe4 */ +/* extrainfo=0 */ +/* ===== */ +, +"50.236.201.218 orport=9001 id=B5053ABFF845C96B1DD8F45DCF32E6BE1E63F127" +/* nickname=Stephen304 */ +/* extrainfo=0 */ +/* ===== */ +, +"5.182.211.119 orport=9001 id=DD7BD3E5BD0BA48A8C70B0CDF017FA5988B87E27" +/* nickname=Assange014nl */ +/* extrainfo=0 */ +/* ===== */ +, +"209.51.188.48 orport=443 id=CEE804FA03A87A65CAA6BCB3A250B5ED923C08BD" +" ipv6=[2001:470:142:5::48]:443" +/* nickname=FSF */ +/* extrainfo=0 */ +/* ===== */ +, +"185.228.136.146 orport=9100 id=F0D01EB1FDC508279AB3412AF3FC950BB1DA2AD1" +" ipv6=[2a03:4000:23:50:c8ed:bcff:fe13:ee61]:9100" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"89.58.52.189 orport=9001 id=C3277FBEAB946672D468E90A16BB027B4CACC537" +" ipv6=[2a03:4000:69:d5d::2]:9001" +/* nickname=itrickl02 */ +/* extrainfo=0 */ +/* ===== */ +, +"188.40.147.177 orport=443 id=1D702DA43D588FE9D308D3879A6F5E61BB2ECCFA" +/* nickname=schumacher */ +/* extrainfo=0 */ +/* ===== */ +, +"82.220.38.150 orport=443 id=A4DE3FC1ACEC3767F5C4049BCEF57317E7B0583C" +/* nickname=eclipse12 */ +/* extrainfo=0 */ +/* ===== */ +, +"65.39.97.13 orport=9001 id=0D1AD0392583CBC22B5F712165D9D752D35F0699" +/* nickname=TorNodeAlpha */ +/* extrainfo=0 */ +/* ===== */ +, +"23.137.251.61 orport=8443 id=B558F456FB410E6CDF3D33AC5EB5305D66DA8B19" +" ipv6=[2602:fc24:13:e::fefe]:8443" +/* nickname=bauruine */ +/* extrainfo=0 */ +/* ===== */ +, +"81.6.40.139 orport=995 id=E36536404200A74930DB165858BD5BB554D2BEA2" +" ipv6=[2a02:168:2000:5f:7b5c:fee4:84b2:30b]:995" +/* nickname=naiveTorer */ +/* extrainfo=0 */ +/* ===== */ +, +"185.194.141.178 orport=9100 id=1B6BCBCDB384364B6FB4F3576CA70AECFC083641" +" ipv6=[2a03:4000:1c:7e3:e8aa:c8ff:fe36:66ee]:9100" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"185.220.101.206 orport=8443 id=ADF0D51946DA3294C1F242B0ACADC91FF5F058EF" +" ipv6=[2a0b:f4c2:2:1::206]:8443" +/* nickname=ForPrivacyNET */ +/* extrainfo=0 */ +/* ===== */ +, +"158.69.207.216 orport=9001 id=6565F31D9EC0C7DFFEA1920BE3BA4C73EF35B5C4" +" ipv6=[2607:5300:201:3000::dfc]:9001" +/* nickname=oscar */ +/* extrainfo=0 */ +/* ===== */ +, +"199.249.230.141 orport=443 id=B7ECD9C6A910A170B55165742049CBCC777494F2" +" ipv6=[2620:7:6001::141]:80" +/* nickname=Quintex52 */ +/* extrainfo=0 */ +/* ===== */ +, +"178.175.148.205 orport=9001 id=8769AF6DCC45DAB9C219CD9F464EAE3268550CFD" +" ipv6=[2a00:1dc0:caff:ad::e746]:9001" +/* nickname=yellowsun */ +/* extrainfo=0 */ +/* ===== */ +, +"51.15.59.15 orport=444 id=B1F926DA3895A89AF288623F5A4F913979299C53" +" ipv6=[2001:bc8:1860:1419::1]:444" +/* nickname=artikel5ev13b */ +/* extrainfo=0 */ +/* ===== */ +, +"192.42.116.17 orport=443 id=0485027A0A349D454D978F6C1CECDD29EA17769A" +" ipv6=[2001:67c:6ec:203:218:33ff:fe44:5517]:443" +/* nickname=hviv117 */ +/* extrainfo=0 */ +/* ===== */ +, +"193.108.118.218 orport=443 id=79D9E66BB2FDBF25E846B635D8248FE1194CFD26" +" ipv6=[2604:86c0:f001:2:9baf:37c2:e99e:babe]:443" +/* nickname=BeastieJoy65 */ +/* extrainfo=0 */ +/* ===== */ +, +"83.78.216.58 orport=43633 id=7ACCD860B360118F43275FCF215F6A4C9D5E016B" +/* nickname=bauruine */ +/* extrainfo=0 */ +/* ===== */ +, +"23.154.177.3 orport=443 id=76CA636C1D33E3E8630B7AC22A1D07420FCE8761" +/* nickname=UnredactedManning */ +/* extrainfo=0 */ +/* ===== */ +, +"213.149.82.60 orport=9001 id=45D8C1EEFF044043AA6806C4B9130F8F189EF316" +" ipv6=[2a02:2488:4211:3400::3]:9001" +/* nickname=Feuermagier */ +/* extrainfo=0 */ +/* ===== */ +, +"49.12.225.94 orport=9001 id=EE2A9108A9EDBFCB5C44F2993267573188176AA4" +/* nickname=myzwiebel03 */ +/* extrainfo=0 */ +/* ===== */ +, +"172.107.202.142 orport=443 id=036E015AD84D3C605666E3A3306B1E3E18A89482" +/* nickname=parsel */ +/* extrainfo=0 */ +/* ===== */ +, +"94.199.217.225 orport=443 id=05D01D243BB76468B80670CCF8F07F5E9296736D" +/* nickname=madblock */ +/* extrainfo=0 */ +/* ===== */ +, +"185.233.100.23 orport=443 id=F47B13BFCE4EF48CDEF6C4D7C7A99208EBB972B5" +" ipv6=[2a0c:e300::23]:443" +/* nickname=Elenagb */ +/* extrainfo=0 */ +/* ===== */ +, +"213.135.244.242 orport=24071 id=2D938F19EAF660D902C656B5E6002F39B45C4BE4" +/* nickname=VoxBox */ +/* extrainfo=0 */ +/* ===== */ +, +"45.132.246.38 orport=9001 id=431702B3A68A6015F9955DD4FD0129175B43EA0F" +" ipv6=[2a03:4000:48:182:74dd:c1ff:fea8:d21e]:9001" +/* nickname=bituman */ +/* extrainfo=0 */ +/* ===== */ +, +"82.223.23.176 orport=443 id=C22A591FF4EE577C408DAFD26C75302615E5165E" +" ipv6=[2001:ba0:1800:8188::1]:443" +/* nickname=FrankyThePooper */ +/* extrainfo=0 */ +/* ===== */ +, +"23.175.32.11 orport=443 id=56BAF2F6CAE76B1AC6C1F08C148D04C219E85E70" +" ipv6=[2606:d680:cafe:80:23:175:32:11]:443" +/* nickname=Wat1E1TorNodeIo */ +/* extrainfo=0 */ +/* ===== */ +, +"91.203.5.165 orport=443 id=AF1F15819AC766D6508A2B05DA989E99AB511F9F" +/* nickname=duchin */ +/* extrainfo=0 */ +/* ===== */ +, +"96.126.105.219 orport=5353 id=60A5547B2203DD2E148EF9BDD6FF3891081C5DF4" +" ipv6=[2600:3c03::f03c:91ff:fe93:5318]:5353" +/* nickname=HotPotato */ +/* extrainfo=0 */ +/* ===== */ +, +"212.32.240.165 orport=9001 id=CFDF99EE1923D870329F8DAE54398FD45409F01F" +/* nickname=UlhasTor */ +/* extrainfo=0 */ +/* ===== */ +, +"185.140.251.125 orport=9001 id=215CC28D7E273AE3308F041E45A8EE3BA6D85658" +/* nickname=HoarseSupernova */ +/* extrainfo=0 */ +/* ===== */ +, +"38.145.211.218 orport=9010 id=3FAFFA13BC88AB28EBA464A902FDED2EA453A581" +" ipv6=[2605:f700:40:401::2efa:261a]:9010" +/* nickname=edaks */ +/* extrainfo=0 */ +/* ===== */ +, +"217.112.131.24 orport=443 id=7896A8075D51F60B950D8E63AAC2899731060843" +/* nickname=licinius */ +/* extrainfo=0 */ +/* ===== */ +, +"46.38.232.203 orport=443 id=8B3A07D9155E76BB4AE922C8F99AE3AB7D88DD23" +/* nickname=ConcordiaConstanzia */ +/* extrainfo=0 */ +/* ===== */ +, +"194.76.227.152 orport=9001 id=2F98E853A570AC7A79B4082364B781AD67705074" +/* nickname=FireMateria */ +/* extrainfo=0 */ +/* ===== */ +, +"192.99.43.171 orport=9001 id=C92ECAF73512E2CCB15827A192B7AF3E9DBC896E" +/* nickname=Unnamed */ +/* extrainfo=0 */ +/* ===== */ +, +"104.244.72.20 orport=9001 id=799E0B28F45548F545668A78DF04CD23490EC585" +" ipv6=[2605:6400:30:efe6:1313:cafe:dead:beef]:9001" +/* nickname=Hermes */ +/* extrainfo=0 */ +/* ===== */ +, +"89.58.4.238 orport=9001 id=4745ACB16234385EF1694D530E109F7A573E30C6" +" ipv6=[2a03:4000:5e:d48:acab::10]:9001" +/* nickname=tweinode3 */ +/* extrainfo=0 */ +/* ===== */ +, +"51.15.54.117 orport=443 id=547E6E68ADE1B6F492C44443588A939610401DFB" +" ipv6=[2001:bc8:1820:c0d::1]:443" +/* nickname=taki */ +/* extrainfo=0 */ +/* ===== */ +, +"37.235.48.247 orport=7654 id=1F2077BF01CAF23F819D4892A89883196ABA842A" +" ipv6=[2a03:f80:48:37:235:48:247:1]:7654" +/* nickname=plutoa */ +/* extrainfo=0 */ +/* ===== */ +, +"51.159.184.219 orport=9001 id=6BE5AA34A5C391724677A3FDC2AA77B3768F6E26" +" ipv6=[2001:bc8:1200:4137::1]:9001" +/* nickname=tormaumauhosting */ +/* extrainfo=0 */ +/* ===== */ +, +"85.239.34.40 orport=9001 id=8E97A9FDBC262A2DB1C87B53F12CF1925866F355" +" ipv6=[2001:678:6d4:7410::12e]:9001" +/* nickname=itsnotjesse */ +/* extrainfo=0 */ +/* ===== */ +, +"198.251.68.144 orport=9001 id=83AEDBDB4BE3AD0ED91850BF1A521B843077759E" +/* nickname=focaltohr */ +/* extrainfo=0 */ +/* ===== */ +, +"89.58.3.65 orport=443 id=FF8B7CAD5F508972509D79F933FB24D2F524AB75" +" ipv6=[2a03:4000:5d:b8f:1478:68ff:fec4:27c7]:443" +/* nickname=einNettesRelay */ +/* extrainfo=0 */ +/* ===== */ +, +"172.106.112.50 orport=443 id=996F4CFD78130203B80E854A4EF6CA2355C6C72C" +/* nickname=Reeses1 */ +/* extrainfo=0 */ +/* ===== */ +, +"37.252.190.176 orport=443 id=81A59766272894D27FE8375C4F83A6BA453671EF" +/* nickname=chutney */ +/* extrainfo=0 */ +/* ===== */ +, +"185.25.51.138 orport=9001 id=D2380745937A994FE1E19859CBEBF181DBB80443" +" ipv6=[2a04:2180:0:1::fb6f:72f2]:9001" +/* nickname=IndigoMagick */ +/* extrainfo=0 */ +/* ===== */ +, +"93.95.231.115 orport=9001 id=3417F1F24A7CA4033DB514610321A1A9F410CC31" +/* nickname=MetalsAG */ +/* extrainfo=0 */ +/* ===== */ +, +"104.192.3.74 orport=443 id=849626A2A3DD1364E8C51423D6F3213A3AE16FFD" +" ipv6=[2605:aa80:0:9::3]:443" +/* nickname=OnionsHaveLayers */ +/* extrainfo=0 */ +/* ===== */ +, +"193.108.117.103 orport=9001 id=438F3EA4C9FB0DB63F5377A3271AB5435FAD7E04" +/* nickname=dolemite */ +/* extrainfo=0 */ +/* ===== */ +, +"68.67.32.33 orport=9001 id=4338C8026D468B811D3EB11AE9E421E2089B8239" +/* nickname=kgXuCTCWVMALFMb74Ld */ +/* extrainfo=0 */ +/* ===== */ +, +"199.249.230.118 orport=443 id=5F4CD12099AF20FAF9ADFDCEC65316A376D0201C" +" ipv6=[2620:7:6001::118]:80" +/* nickname=QuintexAirVPN7 */ +/* extrainfo=0 */ +/* ===== */ +, +"140.78.100.42 orport=5443 id=9D970B7FBAC353D8F6049AD4E0CEE06BBDE4E17E" +/* nickname=INSRelay42at5443 */ +/* extrainfo=0 */ +/* ===== */ +, +"190.211.254.182 orport=9001 id=3B557E3F0C29D4339A904AD8C641F582151FEF71" +/* nickname=ForestIsland */ +/* extrainfo=0 */ +/* ===== */ +, +"74.82.47.194 orport=9001 id=80E23F24D5BE0195D2827557D260D1676DEA5451" +" ipv6=[2001:470:1:908::9001]:9001" +/* nickname=deadbabecafe */ +/* extrainfo=0 */ +/* ===== */ +, +"130.61.174.201 orport=9001 id=519351E3D54202933F85E608D88484A5DC4E4EF0" +/* nickname=bigman */ +/* extrainfo=0 */ +/* ===== */ +, +"185.220.101.203 orport=8443 id=8F11B2E253CEC4C5C463BF38AB1CA645B7294D52" +" ipv6=[2a0b:f4c2:2:1::203]:8443" +/* nickname=ForPrivacyNET */ +/* extrainfo=0 */ +/* ===== */ +, +"185.241.208.204 orport=9000 id=9A8902B985E2F58BC740671040E7165AC904DD40" +/* nickname=Aramis */ +/* extrainfo=0 */ +/* ===== */ +, +"85.208.144.164 orport=443 id=B13C2C569F3FD0C530B7D96E5FF7933DF7A0E834" +" ipv6=[2a09:8740:0:3::13:4008]:443" +/* nickname=porte */ +/* extrainfo=0 */ +/* ===== */ +, +"185.14.30.57 orport=9001 id=58FC2AAB3792AC37897D34331F4F4E00341DEC0C" +" ipv6=[2a02:27ab:0:2::22]:9001" +/* nickname=zwewwlNL1 */ +/* extrainfo=0 */ +/* ===== */ +, +"193.56.240.157 orport=443 id=8E6225BC8A770DF63B20A2FDAC1ABCD795A18987" +/* nickname=skaalz */ +/* extrainfo=0 */ +/* ===== */ +, +"185.244.195.103 orport=9100 id=DFA97DED4CE79FF6F31DAF917C2810CCE8729E9D" +" ipv6=[2a03:4000:27:713:4489:4cff:feab:96fc]:9100" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"155.248.212.228 orport=443 id=E5E553F51D82035A2CE555DBC7D883FAA32ED0B5" +" ipv6=[2603:c024:c000:e400:5d76:a308:5c3a:b70]:443" +/* nickname=yyzz1 */ +/* extrainfo=0 */ +/* ===== */ +, +"95.216.27.105 orport=9001 id=0B45375A2CE8065E8A649D52CC35F39D128745A8" +" ipv6=[2a01:4f9:2a:1b96:2::2]:443" +/* nickname=Ranlvor */ +/* extrainfo=0 */ +/* ===== */ +, +"185.220.101.68 orport=9000 id=42438E63C78CF0624BD7D212524FFE292D8FE3D5" +/* nickname=CCCStuttgartBer */ +/* extrainfo=0 */ +/* ===== */ +, +"103.28.52.93 orport=443 id=C5A6FEE5BC3BE19F5B9EB086CA95DAD393D8A4F6" +/* nickname=jivin */ +/* extrainfo=0 */ +/* ===== */ +, +"82.66.10.17 orport=19001 id=8F7521CEDA9AB705A42254E1E829268DEF57C70E" +/* nickname=bigbrother23470 */ +/* extrainfo=0 */ +/* ===== */ +, +"185.247.226.98 orport=443 id=9AB4B4F5B279DC611BEB62E4528EB91F59A6BB14" +" ipv6=[2a06:1700:2:17:0:5232:2d:4432]:443" +/* nickname=R2D2 */ +/* extrainfo=0 */ +/* ===== */ +, +"178.27.106.248 orport=9031 id=9C305BC09852C7CB62E9A41F9ECA108BBFB23521" +/* nickname=Feidhlim04 */ +/* extrainfo=0 */ +/* ===== */ +, +"140.78.100.28 orport=5443 id=0DBA891A70AE95D4AD77593A936E6C04ABF2E7CE" +/* nickname=INSRelay28at5443 */ +/* extrainfo=0 */ +/* ===== */ +, +"65.108.136.183 orport=443 id=C3F7F3E1E32A64B22B2F0734E7C7A312F993D102" +" ipv6=[2a01:4f9:6b:3408::4]:443" +/* nickname=arbitraryKenzie4 */ +/* extrainfo=0 */ +/* ===== */ +, +"51.15.185.201 orport=443 id=1079E628FC6B0025656AC024F2D9975C441498CD" +/* nickname=PoochySloochy */ +/* extrainfo=0 */ +/* ===== */ +, +"171.25.193.234 orport=80 id=CF1C1804C33CD69D8A75587FABC63D5D0E2980FA" +" ipv6=[2001:67c:289c:2::234]:80" +/* nickname=DFRI10 */ +/* extrainfo=0 */ +/* ===== */ +, +"199.249.230.105 orport=443 id=9F2856F6D2B89AD4EF6D5723FAB167DB5A53519A" +" ipv6=[2620:7:6001::105]:80" +/* nickname=Quintex15 */ +/* extrainfo=0 */ +/* ===== */ +, +"89.236.112.100 orport=443 id=00CCE6A84E6D63A1A42E105839BC8ED5D4B16669" +/* nickname=effiorg1984 */ +/* extrainfo=0 */ +/* ===== */ +, +"209.209.11.184 orport=31289 id=21FFF594CFE691A4A03B828E9597A9F74F878053" +" ipv6=[2602:ffd5:1:112::1]:31288" +/* nickname=Woodman */ +/* extrainfo=0 */ +/* ===== */ +, +"93.95.230.85 orport=443 id=3B20B5D120AB8CC1780F43216DC9C6051ED5C387" +/* nickname=Unnamed */ +/* extrainfo=0 */ +/* ===== */ +, +"84.158.138.52 orport=10222 id=C4C462506D54EDC8EFC8E88E32F4AE014755035A" +/* nickname=s0yb3an */ +/* extrainfo=0 */ +/* ===== */ +, +"89.147.108.62 orport=443 id=F3A9588FB45F76DA4DE5B350C425C130F6FFA983" +/* nickname=Reichsfunkmast2 */ +/* extrainfo=0 */ +/* ===== */ +, +"46.4.103.29 orport=9001 id=46DB04323499DD535956531DF2BF7B03EB2AB15D" +" ipv6=[2a01:4f8:140:94d6::2]:9001" +/* nickname=mickymouse */ +/* extrainfo=0 */ +/* ===== */ +, +"199.249.230.168 orport=443 id=F664E5E50B4D216E5940DA7E9CF653F5F9DC561B" +" ipv6=[2620:7:6001::168]:80" +/* nickname=Quintex79 */ +/* extrainfo=0 */ +/* ===== */ +, +"185.239.222.245 orport=443 id=3DCECAF7089B1C2CE3EA9504EE05CE754F4CF9A8" +" ipv6=[2a09:2681:101:9001::6]:443" +/* nickname=BM06 */ +/* extrainfo=0 */ +/* ===== */ +, +"94.16.117.97 orport=9000 id=13FBC97516DC854399E70BC7CA9A4513FFD4F08C" +" ipv6=[2a03:4000:29:1:d4b9:91ff:fe6e:e48a]:9000" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"46.163.76.170 orport=9001 id=3E2C933BE54585C760FD6D2F3FA7A33E373A7145" +" ipv6=[2a01:488:66:1000:2ea3:4caa:0:1]:9001" +/* nickname=judas */ +/* extrainfo=0 */ +/* ===== */ +, +"204.85.191.8 orport=443 id=7C0AA4E3B73E407E9F5FEB1912F8BE26D8AA124D" +/* nickname=ibibUNC0 */ +/* extrainfo=0 */ +/* ===== */ +, +"109.190.177.33 orport=9999 id=A8874E2C45F445DBA462A914ED8D3AF045734FFB" +/* nickname=computel */ +/* extrainfo=0 */ +/* ===== */ +, +"176.10.119.69 orport=9001 id=FFC3F4BE4D5C392246DC7A37B256A6158C3D8562" +/* nickname=euler */ +/* extrainfo=0 */ +/* ===== */ +, +"162.251.116.106 orport=443 id=24A818D9F1E09F1845FC1589DE5AAF15C8E0867E" +/* nickname=goingin */ +/* extrainfo=0 */ +/* ===== */ +, +"198.50.238.128 orport=443 id=C7946D9A192BBE44C1C8A926A8B135AC495D6636" +/* nickname=t0adwarri0r */ +/* extrainfo=0 */ +/* ===== */ +, +"157.90.92.115 orport=9001 id=AC633C90E126E0BCA96F14ECE5D222B586FA0D56" +" ipv6=[2a01:4f8:252:3df0::2]:9001" +/* nickname=SODrelay */ +/* extrainfo=0 */ +/* ===== */ +, +"132.145.22.208 orport=443 id=A8FB73D917B7C2B851A358729359E13EBA5978FA" +" ipv6=[2603:c020:c007:cab:5235:2d:534b:31]:443" +/* nickname=R5SK1 */ +/* extrainfo=0 */ +/* ===== */ +, +"91.203.144.194 orport=443 id=B1B687C3C4EF46249D638DCE77DDC7AAA39F2996" +/* nickname=yetiready */ +/* extrainfo=0 */ +/* ===== */ +, +"204.85.191.9 orport=443 id=C59E079437340E3AD14E6785C0A91A5B6F328566" +/* nickname=ibibUNC1 */ +/* extrainfo=0 */ +/* ===== */ +, +"46.232.250.51 orport=443 id=D1C60F9BCF2DBA07A775978F66C9927D3A9490BB" +" ipv6=[2a03:4000:2b:673:24da:28ff:feb5:e5c5]:443" +/* nickname=juggernautrelay */ +/* extrainfo=0 */ +/* ===== */ +, +"45.155.168.206 orport=443 id=6F9B7403B4CD1F48269730D1F9ED0E7A75C1F049" +/* nickname=WizardFair */ +/* extrainfo=0 */ +/* ===== */ +, +"185.243.218.27 orport=443 id=A5E42F1A3AFA948A7F2FDB1954A4CF6C6489D418" +" ipv6=[2a03:94e0:ffff:185:243:218:0:27]:443" +/* nickname=bauruine */ +/* extrainfo=0 */ +/* ===== */ +, +"51.75.129.204 orport=443 id=2CE9BE1FC88B9D0FA03F387C9E4F000B5D4B2AE9" +/* nickname=ridin */ +/* extrainfo=0 */ +/* ===== */ +, +"188.68.36.28 orport=9001 id=7260949459C2D4D4A5ABC3AC10C1AD6939E6525C" +" ipv6=[2a03:4000:13:7c3:a401:f1ff:fe45:7ffc]:9001" +/* nickname=Piratenpartei05 */ +/* extrainfo=0 */ +/* ===== */ +, +"82.149.227.124 orport=8080 id=7A6EC43FD4CD5990230FCE48EC37AFC578E36CE6" +" ipv6=[2a01:440:108:11:82:149:227:124]:8080" +/* nickname=cryzrelay03 */ +/* extrainfo=0 */ +/* ===== */ +, +"135.148.100.90 orport=443 id=728F97D5BCB131698814D8C713C2220C6E7267DE" +/* nickname=CanisLatrans */ +/* extrainfo=0 */ +/* ===== */ +, +"185.183.157.127 orport=9100 id=34B80D703F4D6350146B684E66D962A23A830117" +" ipv6=[2a03:4000:1d:b56:5850:c5ff:feca:c5b0]:9100" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"179.43.159.194 orport=9001 id=617C95FCF5F00E98E73E35A71C066ED20614F26D" +/* nickname=FreeExit */ +/* extrainfo=0 */ +/* ===== */ +, +"185.244.195.157 orport=9100 id=69042D6B301F080105D11478A5BC848EB0B5D5DB" +" ipv6=[2a03:4000:27:747:4804:22ff:fe7a:e606]:9100" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"178.254.6.130 orport=443 id=7A2D44E76934D709CBF0E0AE8FEB132B61B6F35D" +" ipv6=[2a00:6800:3:35b::2]:443" +/* nickname=zensursula */ +/* extrainfo=0 */ +/* ===== */ +, +"142.132.204.165 orport=4080 id=6CBA90E31188A65E2B6AC1EE8412E8DE571ECAD6" +" ipv6=[2a01:4f8:261:50da::2]:4080" +/* nickname=spicyavocado */ +/* extrainfo=0 */ +/* ===== */ +, +"66.183.173.29 orport=22 id=E8FA2C9B690F3BC16ADE9A4803CE2C51132F10A6" +/* nickname=tengu */ +/* extrainfo=0 */ +/* ===== */ +, +"31.171.154.165 orport=9001 id=A1177D4BF4698A74B926AE1E0FC533578FA55667" +/* nickname=Tirana */ +/* extrainfo=0 */ +/* ===== */ +, +"91.134.147.134 orport=9001 id=2AD82F3964D325B3FE2FF74E980FB006374EF190" +/* nickname=Unnamed */ +/* extrainfo=0 */ +/* ===== */ +, +"193.105.73.80 orport=9001 id=9DC8B0282A8D3C45212167C454B503243BC93957" +/* nickname=akira */ +/* extrainfo=0 */ +/* ===== */ +, +"140.78.100.22 orport=5443 id=69D7FEF9B0026393C2FD73E897C71C102ABACA5C" +/* nickname=INSRelay22at5443 */ +/* extrainfo=0 */ +/* ===== */ +, +"23.129.64.217 orport=443 id=41C80C52AC82295A4D4308D30DCCD3D4ABC4F66C" +" ipv6=[2620:18c:0:192::217]:443" +/* nickname=EO */ +/* extrainfo=0 */ +/* ===== */ +, +"65.108.253.128 orport=443 id=0B53BF919B9A01ED62ED10E51292ACA50DDB10EB" +" ipv6=[2a01:4f9:c011:9e93::1]:443" +/* nickname=l0z3rzb3d4m3d */ +/* extrainfo=0 */ +/* ===== */ +, +"198.98.60.107 orport=443 id=23C64D7C96C8390013C9E583230E81E70F81F756" +/* nickname=BingusBongus */ +/* extrainfo=0 */ +/* ===== */ +, +"188.68.40.46 orport=9100 id=2EFC2B8BC724CF435C14066087936BE7CA3C57A3" +" ipv6=[2a03:4000:17:5c:24df:84ff:fe54:82aa]:9100" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"138.201.35.6 orport=9001 id=94B710C41B9E8FB592D0916E71B5A89FF4995996" +" ipv6=[2a01:4f8:171:369a::2]:9001" +/* nickname=torrelay */ +/* extrainfo=0 */ +/* ===== */ +, +"51.81.208.164 orport=443 id=756576CF5DA387CDD7EABCCA3F8EAEF933CB4486" +/* nickname=screenslaver */ +/* extrainfo=0 */ +/* ===== */ +, +"89.147.109.91 orport=443 id=7155DE90C1C3C9BF4D637580C7F027E57227BD30" +/* nickname=Unnamed */ +/* extrainfo=0 */ +/* ===== */ +, +"152.70.197.164 orport=443 id=F882E4A4B73447C561617005C8E692B0A7080802" +/* nickname=screwTheNSA */ +/* extrainfo=0 */ +/* ===== */ +, +"163.172.211.16 orport=443 id=05F5062943054646CC7A65532CE52598052628FA" +/* nickname=FreeUyghur */ +/* extrainfo=0 */ +/* ===== */ +, +"174.128.250.164 orport=80 id=5197FC89F7A1623CA90D6E0254ABCCBC6D85A86E" +/* nickname=ready2 */ +/* extrainfo=0 */ +/* ===== */ +, +"13.211.32.165 orport=9001 id=956CD533B7C331C675D30A50900A2E9777D42782" +/* nickname=BlueMonkey */ +/* extrainfo=0 */ +/* ===== */ +, +"116.12.180.237 orport=7443 id=10805A3833774B812D07EB7D1D75A54021590F56" +/* nickname=tommyboy */ +/* extrainfo=0 */ +/* ===== */ +, +"212.192.246.55 orport=443 id=7B24FA67347BEAEC6923D884EACF1C123180DE32" +/* nickname=0x616e6f6e */ +/* extrainfo=0 */ +/* ===== */ +, +"150.246.240.221 orport=443 id=E3F7DA7CC7D5B6CC085799AE0404AA4D2D503E50" +/* nickname=90377Sedna */ +/* extrainfo=0 */ +/* ===== */ +, +"5.189.155.39 orport=9001 id=00962D2DD0B9BF3A6AF1D5EB201132388ACA1424" +/* nickname=BlackBeluga */ +/* extrainfo=0 */ +/* ===== */ +, +"104.244.72.91 orport=9001 id=BD140758135A15605996CCEE3BBFA4127F97B233" +/* nickname=Hydra44 */ +/* extrainfo=0 */ +/* ===== */ +, +"103.109.100.207 orport=9001 id=D08C694485A0031692FAFE8C3205FBBBDBCD9402" +/* nickname=thelastvampire */ +/* extrainfo=0 */ +/* ===== */ +, +"171.25.193.80 orport=80 id=491B4E55B4FD4FDEC63B229B0A3E59868FCA1F1F" +" ipv6=[2001:67c:289c:4::79]:80" +/* nickname=DFRI22 */ +/* extrainfo=0 */ +/* ===== */ +, +"199.249.230.152 orport=443 id=4EE488AC0742BC6B747BB637A5635CE14E877F39" +" ipv6=[2620:7:6001::152]:80" +/* nickname=Quintex63 */ +/* extrainfo=0 */ +/* ===== */ +, +"188.68.224.83 orport=443 id=A6BBD33695A4E3C4545BA370605A4DCD87D98BEE" +/* nickname=ATLANTIS */ +/* extrainfo=0 */ +/* ===== */ +, +"37.133.161.205 orport=9001 id=96C36107664B4406C38CD8676AEA85E4D8BCE825" +/* nickname=tor4win */ +/* extrainfo=0 */ +/* ===== */ +, +"198.180.150.9 orport=9001 id=60E4C5E306D2DB22890EE24A09F9B6C30AF396A8" +" ipv6=[2001:418:8006::9]:9001" +/* nickname=rgiad */ +/* extrainfo=0 */ +/* ===== */ +, +"129.151.246.99 orport=9001 id=439CD12F87CEB496D2601B5DC1FF5186BD9AC2D1" +/* nickname=tallinn21 */ +/* extrainfo=0 */ +/* ===== */ +, +"130.162.218.212 orport=9001 id=944E947CA80D1CF8B2EBE3C3247B2C11931438B8" +/* nickname=Perch */ +/* extrainfo=0 */ +/* ===== */ +, +"86.115.2.103 orport=9001 id=E816C4D4CDA9810D2CB1371257462FF6BCE4DF91" +/* nickname=homebox57 */ +/* extrainfo=0 */ +/* ===== */ +, From dc53d6913ae4ac95220c46b1e0576038bc85b8dc Mon Sep 17 00:00:00 2001 From: Afshin Arani Date: Sun, 29 Oct 2023 19:20:22 +0330 Subject: [PATCH 2/4] README: add F# documentation --- README.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/README.md b/README.md index d4463f7c..0392ccc9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + NOnion ------------------------------- [![Build Status](https://github.com/nblockchain/NOnion/actions/workflows/CI.yml/badge.svg?branch=master&event=push)](https://github.com/nblockchain/NOnion/actions/workflows/CI.yml) @@ -5,6 +6,7 @@ NOnion _Unofficial_ work in progress .NET TOR client library (implemented in F#) - [How do I add this to my project?](#how-do-i-add-this-to-my-project) +- [Getting Started](#getting-started) - [Contributing](#contributing) - [Contributors](https://github.com/nblockchain/NOnion/graphs/contributors) - [License](https://github.com/nblockchain/NOnion/blob/master/LICENSE) @@ -23,6 +25,76 @@ Install via NuGet: > Install-Package NOnion ``` +# Getting Started (F#) + +## Bootstrapping + +To utilize the Tor network, start by bootstrapping your directory. This step involves downloading the most recent information about available routers and their identity keys. + +To initiate the bootstrapping process, you require a list of initial nodes for communication. In NOnion, there are two methods to obtain this list: +1- [Download from Github](https://github.com/torproject/tor/blob/main/src/app/config/fallback_dirs.inc) +2- Utilize the embedded list in the NOnion binary (Note: this list could potentially be outdated) + +Based on what option you choose use one of the following commands to bootstrap a TorClient object: +``` +let! torClient = TorClient.AsyncBootstrapWithEmbeddedList None +``` +### OR +``` +let! torClient = TorClient.AsyncBootstrapWithGithub None +``` +## Browsing the web + +To route your traffic through Tor, you require a circuit, which consists of multiple hops or routers. NOnion simplifies this process for you. Just specify the desired length of your circuit and use the following command: +``` +let hopCount = 3 // any length you want +let! circuit = torClient.AsyncCreateCircuit hopCount Exit None +``` +Once the circuit is established, generate a stream to channel your traffic and establish a connection with your intended destination. +``` +let address = "google.com" // Hostname you want to connect to +let port = 80 // Port you want to connect it + +do! + stream.ConnectToOutside address port + |> Async.Ignore +``` +Now, utilize the stream just like any other `System.IO.Stream`: +``` +do! stream.AsyncWrite [|1uy; 2uy; 3uy; 4uy|] +``` + +## Connecting to hidden services + +To connect to a hidden service using the Tor network, use the folowing command: +``` +let onionAddress = "facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion" + +let! serviceClient = TorServiceClient.Connect torClient onionAddress +let stream = serviceClient.GetStream() +``` +Now, utilize the stream just like any other `System.IO.Stream`: +``` +do! + sprintf "GET / HTTP/1.0\r\n\r\n" + |> System.Text.Encoding.ASCII.GetBytes + |> stream.AsyncWrite +``` +## Hosting a hidden service +Start a hidden service, use the following command: +``` +let serviceHost = new TorServiceHost(torClient, None) +do! serviceHost.Start() +``` +*Note: use TorServiceHost's `maybeMasterPrivateKey` parameter to supply your existing bouncy castle private key* + +Now use the following command to wait for incoming streams/clients: +``` +let! incomingStream = serviceHost.AcceptClient() +``` +Now, utilize the stream just like any other `System.IO.Stream`. + +#### Everything mentioned above can be accomplished in C#. Our test project is also written in C#, so feel free to examine it. # Contributing Don't underestimate the power of your contribution - even a small pull request can make a big difference in a small project, so submit yours today! From 1938e690faf09c1b6bdb27603917ad18b415bffd Mon Sep 17 00:00:00 2001 From: Afshin Arani Date: Sun, 3 Dec 2023 18:04:02 +0200 Subject: [PATCH 3/4] README: change fork url --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d4463f7c..28e3dfcd 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ NOnion ------------------------------- -[![Build Status](https://github.com/nblockchain/NOnion/actions/workflows/CI.yml/badge.svg?branch=master&event=push)](https://github.com/nblockchain/NOnion/actions/workflows/CI.yml) +[![Build Status](https://github.com/aarani/NOnion/actions/workflows/CI.yml/badge.svg?branch=master&event=push)](https://github.com/aarani/NOnion/actions/workflows/CI.yml) _Unofficial_ work in progress .NET TOR client library (implemented in F#) - [How do I add this to my project?](#how-do-i-add-this-to-my-project) - [Contributing](#contributing) -- [Contributors](https://github.com/nblockchain/NOnion/graphs/contributors) -- [License](https://github.com/nblockchain/NOnion/blob/master/LICENSE) +- [Contributors](https://github.com/aarani/NOnion/graphs/contributors) +- [License](https://github.com/aarani/NOnion/blob/master/LICENSE) # How do I add this to my project? From 05da762bbfe544fd58ff45b7dde536ec9c8e4dd1 Mon Sep 17 00:00:00 2001 From: Afshin Arani Date: Fri, 27 Oct 2023 15:36:22 +0330 Subject: [PATCH 4/4] Tests: upgrade to .NET 6 This commit upgrades test project and our CI to use .NET 6. There's no excuse to use .netcoreapp 3.1 anymore. It's noteworthy to say that we will keep NOnion target platform on netstandard2.0 for the time being. P.S: My reason for this upgrade was mostly lack of native apple silicon support in .NET Core 3.1. --- .github/workflows/CI.yml | 12 ++++++------ NOnion.Tests/NOnion.Tests.csproj | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 61e40c54..0eb2d907 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,10 +10,10 @@ jobs: - uses: actions/checkout@v2 with: submodules: recursive - - name: Setup .NET Core SDK 3.1.x + - name: Setup .NET SDK 6.0.x uses: actions/setup-dotnet@v1.7.2 with: - dotnet-version: '3.1.x' + dotnet-version: '6.0.x' - name: Install dependencies run: dotnet restore - name: Build @@ -31,10 +31,10 @@ jobs: submodules: recursive # needed because of commit-lint, see https://github.com/conventional-changelog/commitlint/issues/3376 fetch-depth: 0 - - name: Setup .NET SDK 5.0.x + - name: Setup .NET SDK 6.0.x uses: actions/setup-dotnet@v1.7.2 with: - dotnet-version: '5.0.x' + dotnet-version: '6.0.x' - name: Install dependencies run: dotnet restore - name: Build @@ -84,10 +84,10 @@ jobs: - uses: actions/checkout@v2 with: submodules: recursive - - name: Setup .NET Core SDK 3.1.x + - name: Setup .NET SDK 6.0.x uses: actions/setup-dotnet@v1.7.2 with: - dotnet-version: '3.1.x' + dotnet-version: '6.0.x' - name: Install dependencies run: dotnet restore - name: Build diff --git a/NOnion.Tests/NOnion.Tests.csproj b/NOnion.Tests/NOnion.Tests.csproj index 3be8df35..934851eb 100644 --- a/NOnion.Tests/NOnion.Tests.csproj +++ b/NOnion.Tests/NOnion.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net6.0 false