private IDataAdapter ConnectUdp(IpProxyToken token, Logger logger, PropertyBag properties) { IDataAdapter adapter = null; try { UdpClient client = new UdpClient(IsTokenIpV6(token) ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork); if (token.Hostname == null) { client.Connect(token.Address, token.Port); } else { client.Connect(token.Hostname, token.Port); } NetUtils.PopulateBagFromSocket(client.Client, properties); adapter = new UdpClientDataAdapter(client, IpProxyClient.GetDescription(token)); } catch (SocketException ex) { logger.LogException(ex); token.Status = NetStatusCodes.ConnectFailure; } catch (IOException ex) { logger.LogException(ex); token.Status = NetStatusCodes.ConnectFailure; } return(adapter); }
private void ConnectVersion4a(Stream stm, IpProxyToken token, Logger logger) { byte[] req = new byte[9 + token.Hostname.Length + 1]; req[0] = 4; req[1] = 1; req[2] = (byte)(token.Port >> 8); req[3] = (byte)(token.Port & 0xFF); req[5] = 0; req[4] = 0; req[6] = 0; req[7] = 0x7F; Array.Copy(Encoding.ASCII.GetBytes(token.Hostname), 0, req, 9, token.Hostname.Length); stm.Write(req, 0, req.Length); byte[] resp = GeneralUtils.ReadBytes(stm, 8); if (resp[1] == 0x5A) { token.Status = NetStatusCodes.Success; } else { token.Status = NetStatusCodes.ConnectFailure; } }
private static bool IsTokenIpV6(IpProxyToken token) { bool ret = false; if (NetUtils.OSSupportsIPv6) { if (token.Ipv6) { ret = true; } else if (token.Hostname == null) { ret = token.Address.AddressFamily == AddressFamily.InterNetworkV6; } else { IPAddress addr; if (IPAddress.TryParse(token.Hostname, out addr)) { ret = addr.AddressFamily == AddressFamily.InterNetworkV6; } } } return(ret); }
////////////////////////////////// // Possible token permutations // Address set, no Hostname (use socks4 or socks5 with address) // Address set, Hostname set (use socks4a or socks5 with hostname if told to send, else resolve) // Address not set, Hostname set (use socks4a or socks5 with hostname if told to send, else resolve) private void ConnectVersion4(Stream stm, IpProxyToken token, Logger logger) { IPAddress address = token.Address; if (address == null) { address = GetAddressFromHost(token.Hostname, false); } byte[] req = new byte[9]; req[0] = 4; req[1] = 1; req[2] = (byte)(token.Port >> 8); req[3] = (byte)(token.Port & 0xFF); byte[] addrbytes = address.GetAddressBytes(); req[4] = addrbytes[0]; req[5] = addrbytes[1]; req[6] = addrbytes[2]; req[7] = addrbytes[3]; stm.Write(req, 0, req.Length); byte[] resp = GeneralUtils.ReadBytes(stm, 8); if (resp[1] == 0x5A) { token.Status = NetStatusCodes.Success; } else { token.Status = NetStatusCodes.ConnectFailure; } }
private IpProxyToken HandleConnect(HttpRequestHeader header, DataAdapterToStream stm) { string hostName = null; int port = 80; string[] connectHeader = header.Path.Split(':'); IpProxyToken ret = null; if (connectHeader.Length > 0) { hostName = connectHeader[0]; if (connectHeader.Length > 1) { if (!int.TryParse(connectHeader[1], out port)) { _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidConnect, connectHeader[1]); port = 0; } } if (port > 0) { ret = new IpProxyToken(null, hostName, port, IpProxyToken.IpClientType.Tcp, false); ret.State.Add("stm", stm); ret.State.Add("header", header); } else { ReturnResponse(null, 400, "Bad Request", header.Method, header.Version, stm); } } return(ret); }
/// <summary> /// Get a description of the token /// </summary> /// <param name="token">The token</param> /// <returns>The string description</returns> protected static string GetDescription(IpProxyToken token) { if (token.Hostname != null) { return(String.Format("{0}:{1}", token.Hostname, token.Port)); } return(null); }
/// <summary> /// Connect to the required service with the token /// </summary> /// <param name="token">The token recevied from proxy</param> /// <param name="globalMeta">The global meta</param> /// <param name="logger">The logger</param> /// <param name="meta">The meta</param> /// <param name="properties">Property bag to add any information to</param> /// <returns>The connected data adapter</returns> public override IDataAdapter Connect(ProxyToken token, Logger logger, MetaDictionary meta, MetaDictionary globalMeta, PropertyBag properties) { IpProxyToken iptoken = token as IpProxyToken; if ((iptoken != null) && IsFiltered(iptoken)) { return(base.Connect(token, logger, meta, globalMeta, properties)); } else { token.Status = NetStatusCodes.Blocked; return(null); } }
private static void ConnectWithIpProxyToken(Stream stm, IpProxyToken token, Logger logger) { string hostname = token.Hostname != null ? token.Hostname : token.Address.ToString(); string req = String.Format("CONNECT {0}:{1} HTTP/1.0\r\n\r\n", hostname, token.Port); byte[] reqBytes = Encoding.ASCII.GetBytes(req); stm.Write(reqBytes, 0, reqBytes.Length); List <string> headers = new List <string>(); // Read out response headers while (true) { string nextLine = GeneralUtils.ReadLine(stm); headers.Add(nextLine); if (nextLine.Trim().Length == 0) { break; } } if (headers.Count > 0) { string[] vals = headers[0].Split(' '); int res = 0; if (vals.Length >= 2) { if (int.TryParse(vals[1], out res) && (res == 200)) { token.Status = NetStatusCodes.Success; } else { logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyClient_ErrorOnConnect, res, hostname, token.Port); } } else { logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyClient_InvalidResponse); } } else { logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyClient_NoResponse); } }
/// <summary> /// Negotiate the layer /// </summary> /// <param name="server">The server data adapter</param> /// <param name="client">The client data adapter</param> /// <param name="token">The associated proxy token</param> /// <param name="logger">The current service's logger</param> /// <param name="meta">The current service's meta dictionary</param> /// <param name="globalMeta">The current global meta dictionary</param> /// <param name="properties">Additional properties</param> /// <param name="defaultBinding">The default binding</param> public void Negotiate(ref IDataAdapter server, ref IDataAdapter client, ProxyToken token, Logger logger, MetaDictionary meta, MetaDictionary globalMeta, PropertyBag properties, NetworkLayerBinding defaultBinding) { if (_config.Enabled) { if (defaultBinding == NetworkLayerBinding.Default) { defaultBinding = NetworkLayerBinding.ClientAndServer; } if (Binding != NetworkLayerBinding.Default) { defaultBinding = Binding; } if ((defaultBinding & NetworkLayerBinding.Client) == NetworkLayerBinding.Client) { if (_config.ClientProtocol != SslProtocols.None) { IpProxyToken iptoken = token as IpProxyToken; string serverName = null; if (iptoken != null) { if (!String.IsNullOrWhiteSpace(iptoken.Hostname)) { serverName = iptoken.Hostname; } else { serverName = iptoken.Address.ToString(); } } client = ConnectClient(client, logger, properties, serverName); } } if ((defaultBinding & NetworkLayerBinding.Server) == NetworkLayerBinding.Server) { if (_config.ServerProtocol != SslProtocols.None) { server = ConnectServerBC(server, logger, properties); } } } }
/// <summary> /// Apply the proxy filter to a token /// </summary> /// <param name="token">The tokeb</param> /// <param name="logger">A logger to log data to</param> public override void Apply(ProxyToken token, Logger logger) { base.Apply(token, logger); IpProxyToken t = token as IpProxyToken; if (t != null) { if (!String.IsNullOrWhiteSpace(RedirectAddress)) { t.Hostname = RedirectAddress; } if (RedirectPort != 0) { t.Port = RedirectPort; } } }
/// <summary> /// Bind to the required service with the token /// </summary> /// <param name="token">The token recevied from proxy</param> /// <param name="globalMeta">The global meta</param> /// <param name="logger">The logger</param> /// <param name="meta">The meta</param> /// <param name="properties">Property bag to add any information to</param> /// <returns>The connected data adapter</returns> public override IDataAdapter Bind(ProxyToken token, Logger logger, MetaDictionary meta, MetaDictionary globalMeta, PropertyBag properties) { IDataAdapter adapter = null; IpProxyToken iptoken = token as IpProxyToken; if (iptoken != null) { if (iptoken.ClientType == IpProxyToken.IpClientType.Tcp) { adapter = BindTcp(iptoken, logger, properties); } else { throw new ArgumentException(CANAPE.Net.Properties.Resources.IpProxyClient_InvalidTokenType); } } return(adapter); }
private ProxyToken HandleOtherRequest(HttpRequestHeader header, DataAdapterToStream stm, TcpClientDataAdapter tcpAdapter) { string host = null; foreach (KeyDataPair <string> pair in header.Headers) { if (pair.Name.Equals("host", StringComparison.OrdinalIgnoreCase)) { host = pair.Value; } } Uri url = GetUri(host, tcpAdapter); if (url != null) { // Use generic token so filters don't get used IpProxyToken ret = new IpProxyToken(null, url.Host, url.Port, IpProxyToken.IpClientType.Tcp, false); if (_config.SslConfig.Enabled) { ret.Layers = new INetworkLayer[1]; ret.Layers[0] = new SslNetworkLayer(new SslNetworkLayerConfig(false, true) { Enabled = true }); } ret.State.Add("url", url); ret.State.Add("stm", stm); ret.State.Add("header", header); return(ret); } else { _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidUrl, header.Path); ReturnResponse(null, 400, "Bad Request", header.Method, header.Version, stm); return(null); } }
/// <summary> /// Connect this instance. /// </summary> /// <param name="logger">Logger object</param> /// <returns>The connected data adapter</returns> public IDataAdapter Connect(Logger logger) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if ((Port <= 0) || (Port > 65535)) { throw new NetServiceException(Properties.Resources.FixedProxyDocument_MustProvideValidPort); } try { ProxyClient client = Client != null?Client.Create(logger) : new IpProxyClient(); IpProxyToken token = new IpProxyToken(null, Host, Port, UdpEnable ? IpProxyToken.IpClientType.Udp : IpProxyToken.IpClientType.Tcp, IPv6); IDataAdapter adapter = client.Connect(token, logger, new MetaDictionary(), new MetaDictionary(), new PropertyBag()); if (_layers.Count > 0) { MemoryStream initial_stm = new MemoryStream(InitialData ?? new byte[0]); StreamDataAdapter initial = new StreamDataAdapter(initial_stm); IDataAdapter client_adapter = initial; foreach (INetworkLayer layer in _layers.Select(f => f.CreateLayer(logger))) { layer.Negotiate(ref client_adapter, ref adapter, token, logger, new MetaDictionary(), new MetaDictionary(), new PropertyBag(), NetworkLayerBinding.Client); } } return(adapter); } catch (SocketException ex) { throw new NetServiceException(Properties.Resources.FixedProxyDocument_ErrorCreatingService, ex); } catch (IOException ex) { throw new NetServiceException(Properties.Resources.FixedProxyDocument_ErrorCreatingService, ex); } }
private ProxyClient BuildProxyClient(ProxyToken token, Logger logger) { Uri url = null; if (token is HttpProxyToken) { url = ((HttpProxyToken)token).Url; } else if (token is IpProxyToken) { IpProxyToken iptoken = token as IpProxyToken; UriBuilder builder = new UriBuilder(); switch (iptoken.Port) { case 443: builder.Scheme = "https"; break; case 21: builder.Scheme = "ftp"; break; default: builder.Scheme = "http"; break; } builder.Port = iptoken.Port; builder.Host = iptoken.Hostname ?? iptoken.Address.ToString(); builder.Path = "/"; url = builder.Uri; } else { throw new ArgumentException(CANAPE.Net.Properties.Resources.ScriptProxyClient_InvalidToken, "token"); } return(CreateClient(url, logger)); }
private bool IsFiltered(IpProxyToken token) { foreach (Regex re in _filters) { if (token.Hostname != null) { if (re.IsMatch(token.Hostname)) { return(true); } } if (re.IsMatch(token.Address.ToString())) { return(true); } } return(false); }
/// <summary> /// Check if the token matches this filter /// </summary> /// <param name="token">The token to match</param> /// <returns>True if it matches</returns> public override bool Match(ProxyToken token) { bool bMatch = base.Match(token); if (bMatch) { if (token is IpProxyToken) { IpProxyToken iptoken = (IpProxyToken)token; string hostName = iptoken.Hostname; string ipAddress = iptoken.Address != null?iptoken.Address.ToString() : "0.0.0.0"; bMatch = Address.IsMatch(ipAddress); if (!bMatch) { bMatch = Address.IsMatch(hostName); } if (Port != 0) { if (iptoken.Port != Port) { bMatch = false; } } if (iptoken.ClientType != ClientType) { bMatch = false; } } else { bMatch = false; } } return(bMatch); }
/// <summary> /// Connect to the required service with the token /// </summary> /// <param name="token">The token recevied from proxy</param> /// <param name="globalMeta">The global meta</param> /// <param name="logger">The logger</param> /// <param name="meta">The meta</param> /// <param name="properties">Property bag to add any information to</param> /// <param name="credmgr">Credentials manager</param> /// <returns>The connected data adapter</returns> public override IDataAdapter Connect(ProxyToken token, Logger logger, MetaDictionary meta, MetaDictionary globalMeta, PropertyBag properties, CredentialsManagerService credmgr) { IDataAdapter adapter = null; IpProxyToken iptoken = token as IpProxyToken; if (iptoken != null) { if (iptoken.ClientType == IpProxyToken.IpClientType.Tcp) { adapter = ConnectTcp(iptoken, logger, properties); } else if (iptoken.ClientType == IpProxyToken.IpClientType.Udp) { adapter = ConnectUdp(iptoken, logger, properties); } else { throw new ArgumentException(CANAPE.Net.Properties.Resources.IpProxyClient_InvalidTokenType); } } return(adapter); }
private IDataAdapter ConnectUdp(IpProxyToken token, Logger logger, PropertyBag properties) { IDataAdapter adapter = null; try { UdpClient client = new UdpClient(IsTokenIpV6(token) ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork); IPEndPoint endpoint; if (token.Hostname == null) { endpoint = new IPEndPoint(token.Address, token.Port); } else { endpoint = new IPEndPoint( Dns.GetHostEntryAsync(token.Hostname).GetAwaiter().GetResult().AddressList[0], token.Port); } NetUtils.PopulateBagFromSocket(client.Client, properties); adapter = new UdpClientDataAdapter(client, GetDescription(token), endpoint); } catch (SocketException ex) { logger.LogException(ex); token.Status = NetStatusCodes.ConnectFailure; } catch (IOException ex) { logger.LogException(ex); token.Status = NetStatusCodes.ConnectFailure; } return(adapter); }
private IDataAdapter BindTcp(IpProxyToken token, Logger logger, PropertyBag properties) { TcpListenerDataAdapter adapter = null; try { bool isIpv6 = IsTokenIpV6(token); adapter = new TcpListenerDataAdapter(new IPEndPoint(isIpv6 ? IPAddress.IPv6Any : IPAddress.Any, token.Port)); NetUtils.PopulateBagFromSocket(adapter.Listener.Server, properties); } catch (SocketException ex) { logger.LogException(ex); token.Status = NetStatusCodes.ConnectFailure; } catch (IOException ex) { logger.LogException(ex); token.Status = NetStatusCodes.ConnectFailure; } return(adapter); }
private void ConnectVersion5(Stream stm, IpProxyToken token, Logger logger) { byte[] req = new byte[3] { 5, 1, 0 }; stm.Write(req, 0, req.Length); byte[] resp = GeneralUtils.ReadBytes(stm, 2); if ((resp[0] == 5) && (resp[1] == 0)) { List <byte> connect = new List <byte>(); connect.Add(5); connect.Add(1); connect.Add(0); if (_sendHostName && !String.IsNullOrWhiteSpace(token.Hostname)) { connect.Add(3); connect.Add((byte)token.Hostname.Length); connect.AddRange(new BinaryEncoding().GetBytes(token.Hostname)); } else if (token.Address != null) { if (token.Address.AddressFamily == AddressFamily.InterNetwork) { connect.Add(1); } else if (token.Address.AddressFamily == AddressFamily.InterNetworkV6) { connect.Add(4); } else { throw new ArgumentException(CANAPE.Net.Properties.Resources.SocksProxyClient_InvalidProxyToken); } connect.AddRange(token.Address.GetAddressBytes()); } else { throw new ArgumentException(CANAPE.Net.Properties.Resources.SocksProxyClient_InvalidProxyToken2); } connect.Add((byte)(token.Port >> 8)); connect.Add((byte)(token.Port & 0xFF)); stm.Write(connect.ToArray(), 0, connect.Count); if (stm.ReadByte() != 5) { logger.LogError(CANAPE.Net.Properties.Resources.SocksProxyClient_InvalidV5Response); } int status = stm.ReadByte(); // Read out the rest of the data stm.ReadByte(); int addrType = stm.ReadByte(); switch (addrType) { case 1: GeneralUtils.ReadBytes(stm, 4); break; case 3: int len = stm.ReadByte(); if (len < 0) { throw new EndOfStreamException(CANAPE.Net.Properties.Resources.SocksProxyClient_EosInDomain); } GeneralUtils.ReadBytes(stm, len); break; case 4: GeneralUtils.ReadBytes(stm, 16); break; default: throw new ArgumentException(CANAPE.Net.Properties.Resources.SocksProxyClient_InvalidAddrType); } // Port GeneralUtils.ReadBytes(stm, 2); if (status == 0) { token.Status = NetStatusCodes.Success; } else { token.Status = NetStatusCodes.ConnectFailure; } } else { logger.LogError(CANAPE.Net.Properties.Resources.SocksProxyClient_InvalidV5Response2, resp[0], resp[1]); token.Status = NetStatusCodes.ConnectFailure; } }
/// <summary> /// Connection to the socks server /// </summary> /// <param name="token">The proxy token</param> /// <param name="logger">Logger</param> /// <param name="globalMeta">Global meta</param> /// <param name="meta">Meta</param> /// <param name="properties">Property bag to populate</param> /// <returns>A connected data adapter, or null if not available</returns> /// <exception cref="SocketException">Throw if cannot connect</exception> /// <exception cref="ArgumentException">Throw if invalid operation occurs</exception> /// <exception cref="EndOfStreamException">Throw if stream ends before reading all data</exception> public override IDataAdapter Connect(ProxyToken token, Logger logger, MetaDictionary meta, MetaDictionary globalMeta, PropertyBag properties) { IDataAdapter ret = null; if (token is IpProxyToken) { IpProxyToken iptoken = token as IpProxyToken; TcpClient client = new TcpClient(); try { client.ConnectAsync(_hostname, _port).Wait(); if (_version == SupportedVersion.Version4) { if (_sendHostName && !String.IsNullOrWhiteSpace(iptoken.Hostname)) { ConnectVersion4a(client.GetStream(), iptoken, logger); } else { ConnectVersion4(client.GetStream(), iptoken, logger); } } else { ConnectVersion5(client.GetStream(), iptoken, logger); } if (iptoken.Status == NetStatusCodes.Success) { NetUtils.PopulateBagFromSocket(client.Client, properties); ret = new TcpClientDataAdapter(client, IpProxyClient.GetDescription((IpProxyToken)token)); } } catch (SocketException ex) { logger.LogException(ex); token.Status = NetStatusCodes.ConnectFailure; } catch (IOException ex) { logger.LogException(ex); token.Status = NetStatusCodes.ConnectFailure; } finally { if (ret == null) { client.Dispose(); } } } else { throw new ArgumentException(CANAPE.Net.Properties.Resources.SocksProxyClient_InvalidProxyToken3); } return(ret); }