<PackageReference Include="SSH.NET" Version="2023.0.1" />

HttpConnector

sealed class HttpConnector : ProxyConnector
Establishes a tunnel via an HTTP proxy server.
using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using System; using System.Collections.Generic; using System.Globalization; using System.Net; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; namespace Renci.SshNet.Connection { internal sealed class HttpConnector : ProxyConnector { public HttpConnector(ISocketFactory socketFactory) : base(socketFactory) { } protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket) { Regex regex = new Regex("HTTP/(?<version>\\d[.]\\d) (?<statusCode>\\d{3}) (?<reasonPhrase>.+)$"); Regex regex2 = new Regex("(?<fieldName>[^\\[\\]()<>@,;:\\\"/?={} \\t]+):(?<fieldValue>.+)?"); SocketAbstraction.Send(socket, SshData.Ascii.GetBytes(string.Format(CultureInfo.InvariantCulture, "CONNECT {0}:{1} HTTP/1.0\r\n", connectionInfo.Host, connectionInfo.Port))); if (!string.IsNullOrEmpty(connectionInfo.ProxyUsername)) { string s = string.Format(CultureInfo.InvariantCulture, "Proxy-Authorization: Basic {0}\r\n", Convert.ToBase64String(SshData.Ascii.GetBytes(connectionInfo.ProxyUsername + ":" + connectionInfo.ProxyPassword))); SocketAbstraction.Send(socket, SshData.Ascii.GetBytes(s)); } SocketAbstraction.Send(socket, SshData.Ascii.GetBytes("\r\n")); HttpStatusCode? nullable = null; int num = 0; while (true) { string text = SocketReadLine(socket, connectionInfo.Timeout); if (text == null) break; if (!nullable.HasValue) { Match match = regex.Match(text); if (match.Success) { string text2 = match.Result("${statusCode}"); nullable = (HttpStatusCode)int.Parse(text2, CultureInfo.InvariantCulture); HttpStatusCode? nullable2 = nullable; HttpStatusCode httpStatusCode = HttpStatusCode.OK; if (!((nullable2.GetValueOrDefault() == httpStatusCode) & nullable2.HasValue)) throw new ProxyException("HTTP: Status code " + text2 + ", \"" + match.Result("${reasonPhrase}") + "\""); } } else { Match match2 = regex2.Match(text); if (match2.Success) { if (match2.Result("${fieldName}").Equals("Content-Length", StringComparison.OrdinalIgnoreCase)) num = int.Parse(match2.Result("${fieldValue}"), CultureInfo.InvariantCulture); } else if (text.Length == 0) { if (num > 0) { byte[] buffer = new byte[num]; ConnectorBase.SocketRead(socket, buffer, 0, num, connectionInfo.Timeout); } break; } } } if (!nullable.HasValue) throw new ProxyException("HTTP response does not contain status line."); } private static string SocketReadLine(Socket socket, TimeSpan readTimeout) { Encoding ascii = SshData.Ascii; List<byte> list = new List<byte>(); byte[] array = new byte[1]; while (SocketAbstraction.Read(socket, array, 0, array.Length, readTimeout) != 0) { byte b = array[0]; list.Add(b); if (b == 10 && list.Count > 1 && list[list.Count - 2] == 13) return ascii.GetString(list.ToArray(), 0, list.Count - 2); } if (list.Count == 0) return null; return ascii.GetString(list.ToArray(), 0, list.Count); } } }