Class HttpProxyClient
- Namespace
- VpnHood.Net.Proxies.HttpProxyClients
- Assembly
- VpnHood.Net.Proxies.dll
Opens TCP tunnels through an HTTP proxy with the CONNECT method, optionally over TLS to the proxy itself (an HTTPS proxy) and with Basic authentication.
public class HttpProxyClient : IProxyClient
- Inheritance
-
HttpProxyClient
- Implements
- Inherited Members
Examples
var client = new HttpProxyClient(new HttpProxyClientOptions {
ProxyEndPoint = proxyEndPoint,
Username = "user", // Basic authentication, sent with every request
Password = "pass",
UseTls = false // true for an HTTPS proxy, with ProxyHost as the name on its certificate
});
using var tcp = new TcpClient();
await client.ConnectAsync(tcp, destinationHost, destinationPort, CancellationToken.None);
// Take the tunnel from the client: with UseTls, the connection's own stream would bypass TLS.
var stream = client.GetStream(tcp);
Remarks
One instance can serve many connections at once. With UseTls, a tunnel runs inside a TLS session, so read and write it through GetStream(TcpClient), not GetStream().
Any 2xx answer opens the tunnel. The answer is read only up to its end, so data that a destination sends first, such as an SMTP or SSH banner, stays in the stream for the caller.
Constructors
HttpProxyClient(HttpProxyClientOptions, ILogger<HttpProxyClient>?)
Opens TCP tunnels through an HTTP proxy with the CONNECT method, optionally over TLS to the proxy itself (an HTTPS proxy) and with Basic authentication.
public HttpProxyClient(HttpProxyClientOptions options, ILogger<HttpProxyClient>? logger = null)
Parameters
optionsHttpProxyClientOptionsThe proxy's address, credentials and TLS settings.
loggerILogger<HttpProxyClient>The logger for the client's progress and failures, or null for none.
Examples
var client = new HttpProxyClient(new HttpProxyClientOptions {
ProxyEndPoint = proxyEndPoint,
Username = "user", // Basic authentication, sent with every request
Password = "pass",
UseTls = false // true for an HTTPS proxy, with ProxyHost as the name on its certificate
});
using var tcp = new TcpClient();
await client.ConnectAsync(tcp, destinationHost, destinationPort, CancellationToken.None);
// Take the tunnel from the client: with UseTls, the connection's own stream would bypass TLS.
var stream = client.GetStream(tcp);
Remarks
One instance can serve many connections at once. With UseTls, a tunnel runs inside a TLS session, so read and write it through GetStream(TcpClient), not GetStream().
Any 2xx answer opens the tunnel. The answer is read only up to its end, so data that a destination sends first, such as an SMTP or SSH banner, stays in the stream for the caller.
Properties
ProxyEndPoint
Gets the address and port of the proxy server.
public IPEndPoint ProxyEndPoint { get; }
Property Value
Methods
CheckConnectionAsync(TcpClient, CancellationToken)
Connects to the proxy and, with UseTls, completes the TLS handshake, without asking for a tunnel.
public Task CheckConnectionAsync(TcpClient tcpClient, CancellationToken cancellationToken)
Parameters
tcpClientTcpClientA connection that is not connected yet. With TLS, close it after the check: its TLS session is not kept, so it cannot carry a tunnel; without TLS, a tunnel can follow on it. When the check fails, it is closed.
cancellationTokenCancellationTokenThe token to monitor for cancellation requests.
Returns
- Task
A task that represents the asynchronous operation. It completes when the check passes.
Exceptions
- ArgumentNullException
tcpClientis null.- AuthenticationException
The TLS handshake with the proxy failed.
- SocketException
The connection to the proxy failed.
- OperationCanceledException
cancellationTokenwas canceled.
ConnectAsync(TcpClient, IPEndPoint, CancellationToken)
Opens a tunnel through the proxy to an IP endpoint.
public Task ConnectAsync(TcpClient tcpClient, IPEndPoint destination, CancellationToken cancellationToken)
Parameters
tcpClientTcpClientThe connection to use. When it is not connected, it is connected to ProxyEndPoint first. When the task completes, GetStream(TcpClient) gives the tunnel; when the exchange with the proxy fails, it is closed.
destinationIPEndPointThe destination's address and port.
cancellationTokenCancellationTokenThe token to monitor for cancellation requests.
Returns
- Task
A task that represents the asynchronous operation. It completes when the tunnel is open.
Exceptions
- ArgumentNullException
tcpClientordestinationis null.- ArgumentOutOfRangeException
The port of
destinationis zero.- ProxyClientException
The proxy refused the request or did not answer as an HTTP proxy; SocketErrorCode tells why.
- AuthenticationException
The TLS handshake with the proxy failed.
- TimeoutException
The proxy's answer did not arrive within 30 seconds of the request.
- IOException
The proxy closed the connection before its answer was complete.
- SocketException
The connection to the proxy failed.
- OperationCanceledException
cancellationTokenwas canceled.
ConnectAsync(TcpClient, string, int, CancellationToken)
Opens a tunnel through the proxy to a host, given by name or IP address.
public Task ConnectAsync(TcpClient tcpClient, string host, int port, CancellationToken cancellationToken)
Parameters
tcpClientTcpClientThe connection to use. When it is not connected, it is connected to ProxyEndPoint first. When the task completes, GetStream(TcpClient) gives the tunnel; when the exchange with the proxy fails, it is closed.
hoststringThe destination's host name or IP address literal. A name is sent for the proxy to resolve.
portintThe destination's port, from 1 to 65535.
cancellationTokenCancellationTokenThe token to monitor for cancellation requests.
Returns
- Task
A task that represents the asynchronous operation. It completes when the tunnel is open.
Exceptions
- ArgumentNullException
tcpClientorhostis null.- ArgumentException
hostis empty or white space.- ArgumentOutOfRangeException
portis less than 1 or greater than 65535.- ProxyClientException
The proxy refused the request, did not answer as an HTTP proxy, or sent headers over 8 KB; SocketErrorCode tells why. For example, 407 gives AccessDenied, and 502 gives HostUnreachable.
- AuthenticationException
The TLS handshake with the proxy failed.
- TimeoutException
The proxy's answer did not arrive within 30 seconds of the request.
- IOException
The proxy closed the connection before its answer was complete.
- SocketException
The connection to the proxy failed.
- OperationCanceledException
cancellationTokenwas canceled.
GetStream(TcpClient)
Gets the stream that carries the tunnel of a connection opened by ConnectAsync(TcpClient, string, int, CancellationToken).
public Stream GetStream(TcpClient tcpClient)
Parameters
tcpClientTcpClientThe connection.
Returns
- Stream
The TLS stream when UseTls is true; otherwise, and for a connection this client opened no tunnel on, the connection's NetworkStream.
Remarks
Dispose both: the TLS stream, whose disposal leaves the TCP connection open, and the TcpClient, which closes the tunnel.
Exceptions
- ArgumentNullException
tcpClientis null.- InvalidOperationException
No tunnel of this client is on
tcpClient, and it is not connected.- ObjectDisposedException
No tunnel of this client is on
tcpClient, and it is disposed.