/// <summary> /// When Tor receives a "RESOLVE" SOCKS command, it initiates /// a remote lookup of the hostname provided as the target address in the SOCKS /// request. /// </summary> internal async Task <IPAddress> ResolveAsync(string host) { // https://gitweb.torproject.org/torspec.git/tree/socks-extensions.txt#n44 host = Guard.NotNullOrEmptyOrWhitespace(nameof(host), host, true); if (TorSocks5EndPoint is null) { var hostAddresses = await Dns.GetHostAddressesAsync(host); return(hostAddresses.First()); } var cmd = CmdField.Resolve; var dstAddr = new AddrField(host); var dstPort = new PortField(0); var resolveRequest = new TorSocks5Request(cmd, dstAddr, dstPort); var sendBuffer = resolveRequest.ToBytes(); var receiveBuffer = await SendAsync(sendBuffer); var resolveResponse = new TorSocks5Response(); resolveResponse.FromBytes(receiveBuffer); if (resolveResponse.Rep != RepField.Succeeded) { throw new TorSocks5FailureResponseException(resolveResponse.Rep); } return(IPAddress.Parse(resolveResponse.BndAddr.DomainOrIPv4)); }
public TorSocks5Request(CmdField cmd, AddrField dstAddr, PortField dstPort) { Cmd = Guard.NotNull(nameof(cmd), cmd); DstAddr = Guard.NotNull(nameof(dstAddr), dstAddr); DstPort = Guard.NotNull(nameof(dstPort), dstPort); Ver = VerField.Socks5; Rsv = RsvField.X00; Atyp = dstAddr.Atyp; }
public TorSocks5Response(RepField rep, AddrField bndAddr, PortField bndPort) { Rep = Guard.NotNull(nameof(rep), rep); BndAddr = Guard.NotNull(nameof(bndAddr), bndAddr); BndPort = Guard.NotNull(nameof(bndPort), bndPort); Ver = VerField.Socks5; Rsv = RsvField.X00; Atyp = bndAddr.Atyp; }
void ReleaseDesignerOutlets() { if (HostField != null) { HostField.Dispose(); HostField = null; } if (MessageField != null) { MessageField.Dispose(); MessageField = null; } if (PortField != null) { PortField.Dispose(); PortField = null; } if (StatusField != null) { StatusField.Dispose(); StatusField = null; } if (TargetField != null) { TargetField.Dispose(); TargetField = null; } if (UseridField != null) { UseridField.Dispose(); UseridField = null; } if (PasswordField != null) { PasswordField.Dispose(); PasswordField = null; } }
public override void FromBytes(byte[] bytes) { Guard.NotNullOrEmpty(nameof(bytes), bytes); Guard.MinimumAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, 6); Ver = new VerField(); Ver.FromByte(bytes[0]); Cmd = new CmdField(); Cmd.FromByte(bytes[1]); Rsv = new RsvField(); Rsv.FromByte(bytes[2]); Atyp = new AtypField(); Atyp.FromByte(bytes[3]); DstAddr = new AddrField(); DstAddr.FromBytes(bytes.Skip(4).Take(bytes.Length - 4 - 2).ToArray()); DstPort = new PortField(); DstPort.FromBytes(bytes.Skip(bytes.Length - 2).ToArray()); }
public static void ShowBackingValueField( PortField data, SerializedProperty property, bool isConnected, bool includeChildren, GUIStyle style = null, params GUILayoutOption[] options) { var portData = data.PortData; var labelContent = portData.ItemName != null ? new GUIContent(portData.ItemName) : new GUIContent(property.displayName); switch (portData.ShowBackingValue) { case ShowBackingValue.Unconnected: // Display a label if port is connected if (isConnected) { EditorDrawerUtils.DrawLabelField(labelContent, style, options); } // Display an editable property field if port is not connected else { ReactivePortDrawer.DrawPropertyValue(data.Value, property, labelContent); } break; case ShowBackingValue.Never: // Display a label EditorDrawerUtils.DrawLabelField(labelContent, style, options); break; case ShowBackingValue.Always: // Display an editable property field ReactivePortDrawer.DrawPropertyValue(data.Value, property, labelContent); break; } }
/// <summary> /// Tor attempts to find the canonical hostname for that IPv4 record /// </summary> internal async Task <string> ReverseResolveAsync(IPAddress iPv4) { // https://gitweb.torproject.org/torspec.git/tree/socks-extensions.txt#n55 Guard.NotNull(nameof(iPv4), iPv4); if (TorSocks5EndPoint is null) // Only Tor is iPv4 dependent { var host = await Dns.GetHostEntryAsync(iPv4); return(host.HostName); } Guard.Same($"{nameof(iPv4)}.{nameof(iPv4.AddressFamily)}", AddressFamily.InterNetwork, iPv4.AddressFamily); var cmd = CmdField.ResolvePtr; var dstAddr = new AddrField(iPv4.ToString()); var dstPort = new PortField(0); var resolveRequest = new TorSocks5Request(cmd, dstAddr, dstPort); var sendBuffer = resolveRequest.ToBytes(); var receiveBuffer = await SendAsync(sendBuffer); var resolveResponse = new TorSocks5Response(); resolveResponse.FromBytes(receiveBuffer); if (resolveResponse.Rep != RepField.Succeeded) { throw new TorSocks5FailureResponseException(resolveResponse.Rep); } return(resolveResponse.BndAddr.DomainOrIPv4); }
/// <param name="host">IPv4 or domain</param> internal async Task ConnectToDestinationAsync(string host, int port, bool isRecursiveCall = false) { host = Guard.NotNullOrEmptyOrWhitespace(nameof(host), host, true); Guard.MinimumAndNotNull(nameof(port), port, 0); if (TorSocks5EndPoint is null) { using (await AsyncLock.LockAsync().ConfigureAwait(false)) { TcpClient?.Dispose(); TcpClient = IPAddress.TryParse(host, out IPAddress ip) ? new TcpClient(ip.AddressFamily) : new TcpClient(); await TcpClient.ConnectAsync(host, port).ConfigureAwait(false); Stream = TcpClient.GetStream(); RemoteEndPoint = TcpClient.Client.RemoteEndPoint; } return; } var cmd = CmdField.Connect; var dstAddr = new AddrField(host); DestinationHost = dstAddr.DomainOrIPv4; var dstPort = new PortField(port); DestinationPort = dstPort.DstPort; var connectionRequest = new TorSocks5Request(cmd, dstAddr, dstPort); var sendBuffer = connectionRequest.ToBytes(); var receiveBuffer = await SendAsync(sendBuffer, isRecursiveCall : isRecursiveCall).ConfigureAwait(false); var connectionResponse = new TorSocks5Response(); connectionResponse.FromBytes(receiveBuffer); if (connectionResponse.Rep != RepField.Succeeded) { // https://www.ietf.org/rfc/rfc1928.txt // When a reply(REP value other than X'00') indicates a failure, the // SOCKS server MUST terminate the TCP connection shortly after sending // the reply.This must be no more than 10 seconds after detecting the // condition that caused a failure. DisposeTcpClient(); throw new TorSocks5FailureResponseException(connectionResponse.Rep); } // Do not check the Bnd. Address and Bnd. Port. because Tor does not seem to return any, ever. It returns zeros instead. // Generally also do not check anything but the success response, according to Socks5 RFC // If the reply code(REP value of X'00') indicates a success, and the // request was either a BIND or a CONNECT, the client may now start // passing data. If the selected authentication method supports // encapsulation for the purposes of integrity, authentication and / or // confidentiality, the data are encapsulated using the method-dependent // encapsulation.Similarly, when data arrives at the SOCKS server for // the client, the server MUST encapsulate the data as appropriate for // the authentication method in use. }
void ReleaseDesignerOutlets() { if (ServiceOptionsLabel != null) { ServiceOptionsLabel.Dispose(); ServiceOptionsLabel = null; } if (ProtocolLabel != null) { ProtocolLabel.Dispose(); ProtocolLabel = null; } if (RecordNameLabel != null) { RecordNameLabel.Dispose(); RecordNameLabel = null; } if (PortField != null) { PortField.Dispose(); PortField = null; } if (RecordNameField != null) { RecordNameField.Dispose(); RecordNameField = null; } if (PriorityField != null) { PriorityField.Dispose(); PriorityField = null; } if (ProtocolOptionsField != null) { ProtocolOptionsField.Dispose(); ProtocolOptionsField = null; } if (ServiceOptionsField != null) { ServiceOptionsField.Dispose(); ServiceOptionsField = null; } if (TargetHostField != null) { TargetHostField.Dispose(); TargetHostField = null; } if (WeightField != null) { WeightField.Dispose(); WeightField = null; } }