Utiliser WebClient avec Socks proxy

Est-il possible d'utiliser un proxy socks avec WebClient? Spécifiquement avec le DownloadString méthode qu'il fournit?

Je ne veux pas utiliser des trucs de tiers comme privoxy, freecap ou autre et je ne peux pas utiliser des bibliothèques commerciales comme celles de Chilkat. J'ai essayé d'utiliser des trucs de http://www.mentalis.org/ en fait, j'ai utilisé leur WebRequest implémentation mais ils ne semblent pas avoir quelque chose de similaire pour WebClient.

17
demandé sur Laurel 2012-10-29 17:13:49

4 réponses

chaussettes n'est pas supporté directement par le WebRequest/WebResponse classes et par extension, le WebClient classe (il s'appuie sur WebRequest pour faire son travail).

il ne peut vraiment pas, car il fonctionne sur la couche transport (TCP / IP) et non par une simple redirection vers un serveur qui transmet les requêtes HTTP (ce qui est le niveau que le WebRequest/WebResponse cours).

Vous pouvez créer un dérivation spécialisée de WebRequest/WebResponse (qui utilise ProxySocket pour gérer le faible niveau de prise de contact et ensuite), puis de créer un spécialisé WebClient classe qui l'emporte sur le GetWebRequest et GetWebResponse méthodes.

une fois que vous avez cette classe substituée à votre WebClient les instances, cela devrait fonctionner normalement (vous pourriez avoir à configurer le proxy dans chaque cas où vous l'utilisez).

15
répondu casperOne 2012-10-29 14:36:29

Voici comment j'ai fini par le faire, merci casperOne pour la réponse

public class SocksWebClient : WebClient
    {
        public IProxyDetails ProxyDetails { get; set; }
        public string UserAgent { get; set; }

        protected override WebRequest GetWebRequest(Uri address)
        {
            WebRequest result = null;

            if (ProxyDetails != null)
            {
                if (ProxyDetails.ProxyType == ProxyType.Proxy)
                {
                    result = (HttpWebRequest)WebRequest.Create(address);
                    result.Proxy = new WebProxy(ProxyDetails.FullProxyAddress);
                    if (!string.IsNullOrEmpty(UserAgent))
                        ((HttpWebRequest)result).UserAgent = UserAgent;
                }
                else if (ProxyDetails.ProxyType == ProxyType.Socks)
                {
                    result = SocksHttpWebRequest.Create(address);
                    result.Proxy = new WebProxy(ProxyDetails.FullProxyAddress);
                    //TODO: implement user and password

                }
                else if (ProxyDetails.ProxyType == ProxyType.None)
                {
                    result = (HttpWebRequest)WebRequest.Create(address);
                    if (!string.IsNullOrEmpty(UserAgent))
                        ((HttpWebRequest)result).UserAgent = UserAgent;
                }
            }
            else
            {
                result = (HttpWebRequest)WebRequest.Create(address);
                if (!string.IsNullOrEmpty(UserAgent))
                    ((HttpWebRequest)result).UserAgent = UserAgent;
            }


            return result;
        }

    }

SocksHttpWebRequest la classe est tirée de la blog lié à @casperOne, dont le code est le suivant:

using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Org.Mentalis.Network.ProxySocket;

namespace Ditrans
{
    public class SocksHttpWebRequest : WebRequest
    {

        #region Member Variables

        private readonly Uri _requestUri;
        private WebHeaderCollection _requestHeaders;
        private string _method;
        private SocksHttpWebResponse _response;
        private string _requestMessage;
        private byte[] _requestContentBuffer;

        // darn MS for making everything internal (yeah, I'm talking about you, System.net.KnownHttpVerb)
        static readonly StringCollection validHttpVerbs =
            new StringCollection { "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "OPTIONS" };

        #endregion

        #region Constructor

        private SocksHttpWebRequest(Uri requestUri)
        {
            _requestUri = requestUri;
        }

        #endregion

        #region WebRequest Members

        public override WebResponse GetResponse()
        {
            if (Proxy == null)
            {
                throw new InvalidOperationException("Proxy property cannot be null.");
            }
            if (String.IsNullOrEmpty(Method))
            {
                throw new InvalidOperationException("Method has not been set.");
            }

            if (RequestSubmitted)
            {
                return _response;
            }
            _response = InternalGetResponse();
            RequestSubmitted = true;
            return _response;
        }

        public override Uri RequestUri
        {
            get { return _requestUri; }
        }

        public override IWebProxy Proxy { get; set; }

        public override WebHeaderCollection Headers
        {
            get
            {
                if (_requestHeaders == null)
                {
                    _requestHeaders = new WebHeaderCollection();
                }
                return _requestHeaders;
            }
            set
            {
                if (RequestSubmitted)
                {
                    throw new InvalidOperationException("This operation cannot be performed after the request has been submitted.");
                }
                _requestHeaders = value;
            }
        }

        public bool RequestSubmitted { get; private set; }

        public override string Method
        {
            get
            {
                return _method ?? "GET";
            }
            set
            {
                if (validHttpVerbs.Contains(value))
                {
                    _method = value;
                }
                else
                {
                    throw new ArgumentOutOfRangeException("value", string.Format("'{0}' is not a known HTTP verb.", value));
                }
            }
        }

        public override long ContentLength { get; set; }

        public override string ContentType { get; set; }

        public override Stream GetRequestStream()
        {
            if (RequestSubmitted)
            {
                throw new InvalidOperationException("This operation cannot be performed after the request has been submitted.");
            }

            if (_requestContentBuffer == null)
            {
                _requestContentBuffer = new byte[ContentLength];
            }
            else if (ContentLength == default(long))
            {
                _requestContentBuffer = new byte[int.MaxValue];
            }
            else if (_requestContentBuffer.Length != ContentLength)
            {
                Array.Resize(ref _requestContentBuffer, (int) ContentLength);
            }
            return new MemoryStream(_requestContentBuffer);
        }

        #endregion

        #region Methods

        public static new WebRequest Create(string requestUri)
        {
            return new SocksHttpWebRequest(new Uri(requestUri));
        }

        public static new WebRequest Create(Uri requestUri)
        {
            return new SocksHttpWebRequest(requestUri);
        }

        private string BuildHttpRequestMessage()
        {
            if (RequestSubmitted)
            {
                throw new InvalidOperationException("This operation cannot be performed after the request has been submitted.");
            }

            var message = new StringBuilder();
            message.AppendFormat("{0} {1} HTTP/1.0\r\nHost: {2}\r\n", Method, RequestUri.PathAndQuery, RequestUri.Host);

            // add the headers
            foreach (var key in Headers.Keys)
            {
                message.AppendFormat("{0}: {1}\r\n", key, Headers[key.ToString()]);
            }

            if (!string.IsNullOrEmpty(ContentType))
            {
                message.AppendFormat("Content-Type: {0}\r\n", ContentType);
            }
            if (ContentLength > 0)
            {
                message.AppendFormat("Content-Length: {0}\r\n", ContentLength);
            }

            // add a blank line to indicate the end of the headers
            message.Append("\r\n");

            // add content
            if(_requestContentBuffer != null && _requestContentBuffer.Length > 0)
            {
                using (var stream = new MemoryStream(_requestContentBuffer, false))
                {
                    using (var reader = new StreamReader(stream))
                    {
                        message.Append(reader.ReadToEnd());
                    }
                }
            }

            return message.ToString();
        }

        private SocksHttpWebResponse InternalGetResponse()
        {
            var response = new StringBuilder();
            using (var _socksConnection =
                new ProxySocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                var proxyUri = Proxy.GetProxy(RequestUri);
                var ipAddress = GetProxyIpAddress(proxyUri);
                _socksConnection.ProxyEndPoint = new IPEndPoint(ipAddress, proxyUri.Port);
                _socksConnection.ProxyType = ProxyTypes.Socks5;

                // open connection
                _socksConnection.Connect(RequestUri.Host, 80);
                // send an HTTP request
                _socksConnection.Send(Encoding.ASCII.GetBytes(RequestMessage));
                // read the HTTP reply
                var buffer = new byte[1024];

                var bytesReceived = _socksConnection.Receive(buffer);
                while (bytesReceived > 0)
                {
                    response.Append(Encoding.ASCII.GetString(buffer, 0, bytesReceived));
                    bytesReceived = _socksConnection.Receive(buffer);
                }
            }
            return new SocksHttpWebResponse(response.ToString());
        }

        private static IPAddress GetProxyIpAddress(Uri proxyUri)
        {
            IPAddress ipAddress;
            if (!IPAddress.TryParse(proxyUri.Host, out ipAddress))
            {
                try
                {
                    return Dns.GetHostEntry(proxyUri.Host).AddressList[0];
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException(
                        string.Format("Unable to resolve proxy hostname '{0}' to a valid IP address.", proxyUri.Host), e);
                }
            }
            return ipAddress;
        }

        #endregion

        #region Properties

        public string RequestMessage
        {
            get
            {
                if (string.IsNullOrEmpty(_requestMessage))
                {
                    _requestMessage = BuildHttpRequestMessage();
                }
                return _requestMessage;
            }
        }

        #endregion

    }
}

notez que, comme @casperOne l'a fait remarquer, cela fait usage d'une bibliothèque (gratuite) tierce appelée ProxySocket.

16
répondu Dan Parsonson 2017-11-22 15:34:48

je suis tombé sur cette aswell et a trouvé la belle Betterhtttpclient

Il dérive de WebClient et vous permet de spécifier un proxy socks:

BetterHttpClient.HttpClient client = new BetterHttpClient.HttpClient(new BetterHttpClient.Proxy("IP address", port, BetterHttpClient.ProxyTypeEnum.Socks));
2
répondu Martin 2017-10-26 23:05:48

Voici comment j'ai fini par le faire, merci casperOne pour la réponse

public class SocksWebClient : WebClient
{
    public IProxyDetails ProxyDetails { get; set; }
    public string UserAgent { get; set; }

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest result = null;

        if (ProxyDetails != null)
        {
            if (ProxyDetails.ProxyType == ProxyType.Proxy)
            {
                result = (HttpWebRequest)WebRequest.Create(address);
                result.Proxy = new WebProxy(ProxyDetails.FullProxyAddress);
                if (!string.IsNullOrEmpty(UserAgent))
                    ((HttpWebRequest)result).UserAgent = UserAgent;
            }
            else if (ProxyDetails.ProxyType == ProxyType.Socks)
            {
                result = SocksHttpWebRequest.Create(address);
                result.Proxy = new WebProxy(ProxyDetails.FullProxyAddress);
                //TODO: implement user and password

            }
            else if (ProxyDetails.ProxyType == ProxyType.None)
            {
                result = (HttpWebRequest)WebRequest.Create(address);
                if (!string.IsNullOrEmpty(UserAgent))
                    ((HttpWebRequest)result).UserAgent = UserAgent;
            }
        }
        else
        {
            result = (HttpWebRequest)WebRequest.Create(address);
            if (!string.IsNullOrEmpty(UserAgent))
                ((HttpWebRequest)result).UserAgent = UserAgent;
        }

        return result;
    }
}

je cherche le même code mais ça ne marche pas vraiment pour moi. Je me demande où vous avez le IProxyDetails-Objet. Il ne semble pas mis en œuvre dans le blog et pas dans les fichiers que j'ai obtenu à partir de là

-3
répondu Mandy Eichmann 2016-06-15 13:48:02