コード例 #1
0
        /// <summary>
        /// Performs a mediated transfer, meaning we send the data over a proxy server.
        /// </summary>
        /// <param name="session">The SI session whose data to transfer.</param>
        /// <param name="proxies"></param>
        /// <exception cref="Socks5Exception">The SOCKS5 connection to the designated
        /// proxy server could not be established.</exception>
        /// <exception cref="XmppErrorException">The server returned an XMPP error code.
        /// Use the Error property of the XmppErrorException to obtain the specific
        /// error condition.</exception>
        /// <exception cref="XmppException">The server returned invalid data or another
        /// unspecified XMPP error occurred.</exception>
        void MediatedTransfer(SISession session, IEnumerable <Streamhost> proxies)
        {
            var proxy = NegotiateProxy(session, proxies);

            // Connect to the designated proxy.
            using (var client = new Socks5Client(proxy.Host, proxy.Port)) {
                // Send the SOCKS5 Connect command.
                string     hostname = Sha1(session.Sid + session.From + session.To);
                SocksReply reply    = client.Request(SocksCommand.Connect, hostname, 0);
                if (reply.Status != ReplyStatus.Succeeded)
                {
                    throw new Socks5Exception("SOCKS5 Connect request failed.");
                }
                // Activate the bytetream.
                var xml = Xml.Element("query", "http://jabber.org/protocol/bytestreams")
                          .Attr("sid", session.Sid).Child(
                    Xml.Element("activate").Text(session.To.ToString()));
                Iq iq = im.IqRequest(IqType.Set, proxy.Jid, im.Jid, xml);
                if (iq.Type == IqType.Error)
                {
                    throw Util.ExceptionFromError(iq, "Could not activate the bytestream.");
                }
                // Finally, go ahead and send the data to the proxy.
                SendData(session, client.GetStream());
            }
        }
コード例 #2
0
    /// <summary>
    /// Sends the specified SOCKS5 reply to the connected client.
    /// </summary>
    /// <param name="reply">The SOCKS5 reply to send to the connected
    /// client.</param>
    /// <exception cref="ArgumentNullException">The reply parameter is
    /// null.</exception>
    /// <exception cref="ObjectDisposedException">The object has been
    /// disposed.</exception>
    public void Reply(SocksReply reply)
    {
        AssertValid();
        var bytes = reply.Serialize();

        stream.Write(bytes, 0, bytes.Length);
    }
コード例 #3
0
    /// <summary>
    /// Performs the specified SOCKS5 request.
    /// </summary>
    /// <param name="request">The SOCKS5 request to issue to the server.</param>
    /// <returns>The SOCKS5 reply sent by the server.</returns>
    /// <exception cref="ArgumentNullException">The request parameter is
    /// null.</exception>
    /// <exception cref="ObjectDisposedException">The object has been
    /// disposed.</exception>
    /// <exception cref="Socks5Exception">The request could not be performed.
    /// Consult the InnerException property of the Socks5Exception to learn
    /// the reason.</exception>
    public SocksReply Request(SocksRequest request)
    {
        AssertValid();
        try
        {
            byte[] bytes = request.Serialize();
            stream.Write(bytes, 0, bytes.Length);
            ByteBuilder b = new ByteBuilder();
            using (var r = new BinaryReader(stream, Encoding.UTF8, true))
            {
                bytes = r.ReadBytes(4);
                b.Append(bytes);
                ATyp atyp = (ATyp)bytes[3];
                switch (atyp)
                {
                case ATyp.IPv4:
                case ATyp.IPv6:
                    b.Append(r.ReadBytes(atyp == ATyp.IPv4 ? 4 : 16));
                    break;

                case ATyp.Domain:
                    byte length = r.ReadByte();
                    b.Append(length).Append(r.ReadBytes(length));
                    break;
                }
                b.Append(r.ReadBytes(2));
            }
            return(SocksReply.Deserialize(b.ToArray()));
        }
        catch (Exception e)
        {
            throw new Socks5Exception("The request could not be performed.", e);
        }
    }
コード例 #4
0
        /// <summary>
        /// Establishes a SOCKS5 connection with one of the streamhosts in the
        /// specified collection of streamhosts.
        /// </summary>
        /// <param name="stanza">The original requesting IQ stanza.</param>
        /// <param name="sid">The session-id associated with this request.</param>
        /// <param name="hosts">An enumerable collection of Streamhost
        /// instances.</param>
        /// <returns>An initialized instance of the Socks5Client class
        /// representing the established SOCKS5 connection.</returns>
        /// <exception cref="Socks5Exception">An error occurred during SOCKS5
        /// negotiation.</exception>
        /// <exception cref="XmppException">No connection to any of the provided
        /// streamhosts could be established.</exception>
        private async Task <Socks5Client> EstablishConnection(Iq stanza, string sid, IEnumerable <Streamhost> hosts)
        {
            // Try to establish a SOCKS5 connection to any of the streamhosts in the
            // collection.
            bool connected = false;

            foreach (var host in hosts)
            {
                try
                {
                    var client = await Socks5Client.Create(host.Host, host.Port);

                    connected = true;
                    // Send the SOCKS5 Connect command.
                    string     hostname = Sha1(sid + stanza.From + stanza.To);
                    SocksReply reply    = await client.Request(SocksCommand.Connect, hostname, 0);

                    if (reply.Status != ReplyStatus.Succeeded)
                    {
                        throw new Socks5Exception("SOCKS5 Connect request failed.");
                    }
                    // Send acknowledging IQ-result.
                    await im.IqResult(stanza,
                                      Xml.Element("query", "http://jabber.org/protocol/bytestreams")
                                      .Attr("sid", sid).Child(Xml.Element("streamhost-used")
                                                              .Attr("jid", host.Jid.ToString()))
                                      );

                    return(client);
                }
                catch
                {
                    // Fall through and try the next streamhost.
                    if (connected)
                    {
                        break;
                    }
                }
            }
            // Still here means we couldn't connect to any of the streamhosts or
            // an error occurred during SOCKS5 negotiation.
            await im.IqError(stanza, ErrorType.Cancel, ErrorCondition.ItemNotFound);

            // Error out.
            throw new XmppException("Couldn't connect to streamhost.");
        }
コード例 #5
0
        private void HandleProxyCommandError(SocksReply replyCode)
        {
            string proxyErrorText;

            switch (replyCode)
            {
            case SocksReply.GeneralSOCKSServerFailure:
                proxyErrorText = "a general socks destination failure occurred";
                break;

            case SocksReply.NotAllowedByRuleset:
                proxyErrorText = "the connection is not allowed by proxy destination rule set";
                break;

            case SocksReply.NetworkUnreachable:
                proxyErrorText = "the network was unreachable";
                break;

            case SocksReply.HostUnreachable:
                proxyErrorText = "the host was unreachable";
                break;

            case SocksReply.ConnectionRefused:
                proxyErrorText = "the connection was refused by the remote network";
                break;

            case SocksReply.TTLExpired:
                proxyErrorText = "the time to live (TTL) has expired";
                break;

            case SocksReply.CommandNotSupported:
                proxyErrorText = "the command issued by the proxy client is not supported by the proxy destination";
                break;

            case SocksReply.AddressTypeNotSupported:
                proxyErrorText = "the address type specified is not supported";
                break;

            default:
                proxyErrorText = $"an unknown SOCKS reply with the code value '{replyCode}' was received";
                break;
            }

            _socketStream.Close();
            throw new SocksProxyException($"Proxy error: {proxyErrorText} for destination host {_destinationHost} port number {_destinationPort}.");
        }