Commit 00eaed63 authored by justcoding121's avatar justcoding121

Merge branch 'beta' into stable

parents 11632fe1 b64e703c
......@@ -6,8 +6,7 @@ $SolutionRoot = (Split-Path -parent $Here)
$ProjectName = "Titanium.Web.Proxy"
$SolutionFile14 = "$SolutionRoot\$ProjectName.sln"
$SolutionFile = "$SolutionRoot\$ProjectName.Standard.sln"
$SolutionFile = "$SolutionRoot\$ProjectName.sln"
## This comes from the build server iteration
if(!$BuildNumber) { $BuildNumber = $env:APPVEYOR_BUILD_NUMBER }
......@@ -29,8 +28,6 @@ Import-Module "$Here\Common" -DisableNameChecking
$NuGet = Join-Path $SolutionRoot ".nuget\nuget.exe"
$MSBuild14 = "${env:ProgramFiles(x86)}\MSBuild\14.0\Bin\msbuild.exe"
$MSBuild = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe"
$MSBuild -replace ' ', '` '
......@@ -40,32 +37,27 @@ FormatTaskName (("-"*25) + "[{0}]" + ("-"*25))
Task default -depends Clean, Build, Package
Task Build -depends Restore-Packages{
exec { . $MSBuild14 $SolutionFile14 /t:Build /v:normal /p:Configuration=$Configuration }
exec { . $MSBuild $SolutionFile /t:Build /v:normal /p:Configuration=$Configuration /t:restore }
}
Task Package -depends Build {
exec { . $NuGet pack "$SolutionRoot\Titanium.Web.Proxy\Titanium.Web.Proxy.nuspec" -Properties Configuration=$Configuration -OutputDirectory "$SolutionRoot" -Version "$Version" }
exec { . $NuGet pack "$SolutionRoot\Titanium.Web.Proxy\Titanium.Web.Proxy.nuspec" -Properties Configuration=$Configuration -OutputDirectory "$SolutionRoot" -Version "$Version" }
}
Task Clean -depends Install-BuildTools {
Get-ChildItem .\ -include bin,obj -Recurse | foreach ($_) { Remove-Item $_.fullname -Force -Recurse }
exec { . $MSBuild14 $SolutionFile14 /t:Clean /v:quiet }
exec { . $MSBuild $SolutionFile /t:Clean /v:quiet }
Get-ChildItem .\ -include bin,obj -Recurse | foreach ($_) { Remove-Item $_.fullname -Force -Recurse }
exec { . $MSBuild $SolutionFile /t:Clean /v:quiet }
}
Task Restore-Packages {
exec { . dotnet restore "$SolutionRoot\Titanium.Web.Proxy.sln" }
exec { . dotnet restore "$SolutionRoot\Titanium.Web.Proxy.Standard.sln" }
exec { . dotnet restore "$SolutionRoot\Titanium.Web.Proxy.sln" }
}
Task Install-MSBuild {
if(!(Test-Path $MSBuild14))
{
cinst microsoft-build-tools -y
}
{
cinst microsoft-build-tools -y
}
}
Task Install-BuildTools -depends Install-MSBuild
\ No newline at end of file
......@@ -2,11 +2,11 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Titanium.Web.Proxy\Titanium.Web.Proxy.Standard.csproj" />
<ProjectReference Include="..\..\Titanium.Web.Proxy\Titanium.Web.Proxy.csproj" />
</ItemGroup>
</Project>
\ No newline at end of file
......@@ -8,8 +8,14 @@ Kindly report only issues/bugs here . For programming help or questions use [Sta
([Wiki & Contribution guidelines](https://github.com/justcoding121/Titanium-Web-Proxy/wiki))
**Console example application screenshot**
![alt tag](https://raw.githubusercontent.com/justcoding121/Titanium-Web-Proxy/develop/Examples/Titanium.Web.Proxy.Examples.Basic/Capture.PNG)
**GUI example application screenshot**
![alt tag](https://raw.githubusercontent.com/justcoding121/Titanium-Web-Proxy/develop/Examples/Titanium.Web.Proxy.Examples.Wpf/Capture.PNG)
Features
========
......@@ -39,7 +45,7 @@ For stable releases on [stable branch](https://github.com/justcoding121/Titanium
Supports
* .Net Standard 1.6 or above
* .Net Standard 2.0 or above
* .Net Framework 4.5 or above
Setup HTTP proxy:
......

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{6FD3B84B-9283-4E9C-8C43-A234E9AA3EAA}"
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.Config = .nuget\NuGet.Config
.nuget\NuGet.exe = .nuget\NuGet.exe
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{38EA62D0-D2CB-465D-AF4F-407C5B4D4A1E}"
ProjectSection(SolutionItems) = preProject
LICENSE = LICENSE
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{AC9AE37A-3059-4FDB-9A5C-363AD86F2EEF}"
ProjectSection(SolutionItems) = preProject
.build\Bootstrap.ps1 = .build\Bootstrap.ps1
.build\Common.psm1 = .build\Common.psm1
.build\default.ps1 = .build\default.ps1
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BC1E0789-D348-49CF-8B67-5E99D50EDF64}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy.Standard", "Titanium.Web.Proxy\Titanium.Web.Proxy.Standard.csproj", "{9F983536-C482-4BA0-BEE9-C59FC4221F76}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy.Examples.Basic.Standard", "Examples\Titanium.Web.Proxy.Examples.Basic.Standard\Titanium.Web.Proxy.Examples.Basic.Standard.csproj", "{EEE97BBC-6898-41DE-B97B-BE0157A816CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9F983536-C482-4BA0-BEE9-C59FC4221F76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F983536-C482-4BA0-BEE9-C59FC4221F76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F983536-C482-4BA0-BEE9-C59FC4221F76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F983536-C482-4BA0-BEE9-C59FC4221F76}.Release|Any CPU.Build.0 = Release|Any CPU
{EEE97BBC-6898-41DE-B97B-BE0157A816CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EEE97BBC-6898-41DE-B97B-BE0157A816CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EEE97BBC-6898-41DE-B97B-BE0157A816CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EEE97BBC-6898-41DE-B97B-BE0157A816CD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EEE97BBC-6898-41DE-B97B-BE0157A816CD} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio 15
VisualStudioVersion = 15.0.26730.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}"
EndProject
......@@ -37,6 +37,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.Integrat
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.Examples.Wpf", "Examples\Titanium.Web.Proxy.Examples.Wpf\Titanium.Web.Proxy.Examples.Wpf.csproj", "{4406CE17-9A39-4F28-8363-6169A4F799C1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy.Examples.Basic.Standard", "Examples\Titanium.Web.Proxy.Examples.Basic.Standard\Titanium.Web.Proxy.Examples.Basic.Standard.csproj", "{75AEF54F-C3B7-43A8-8ECA-561FB21BC6AD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -63,6 +65,10 @@ Global
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|Any CPU.Build.0 = Release|Any CPU
{75AEF54F-C3B7-43A8-8ECA-561FB21BC6AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75AEF54F-C3B7-43A8-8ECA-561FB21BC6AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75AEF54F-C3B7-43A8-8ECA-561FB21BC6AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75AEF54F-C3B7-43A8-8ECA-561FB21BC6AD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......@@ -72,8 +78,10 @@ Global
{B517E3D0-D03B-436F-AB03-34BA0D5321AF} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
{4406CE17-9A39-4F28-8363-6169A4F799C1} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B}
{75AEF54F-C3B7-43A8-8ECA-561FB21BC6AD} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35
SolutionGuid = {625C1EB5-44CF-47DE-A85A-B4C8C40ED90A}
EndGlobalSection
EndGlobal
using System;
#if NET45
using System;
using System.IO;
namespace Titanium.Web.Proxy.Helpers
......@@ -50,3 +51,4 @@ namespace Titanium.Web.Proxy.Helpers
}
}
}
#endif
using System;
#if NET45
using System;
using System.Runtime.InteropServices;
namespace Titanium.Web.Proxy.Helpers
......@@ -20,4 +21,5 @@ namespace Titanium.Web.Proxy.Helpers
// Pinvoke
internal delegate bool ConsoleEventDelegate(int eventType);
}
}
\ No newline at end of file
}
#endif
#if NET45
using System;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
......@@ -58,4 +59,5 @@ namespace Titanium.Web.Proxy.Helpers
[DllImport("iphlpapi.dll", SetLastError = true)]
internal static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int size, bool sort, int ipVersion, int tableClass, int reserved);
}
}
\ No newline at end of file
}
#endif
using System;
#if NET45
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
......@@ -198,3 +199,4 @@ namespace Titanium.Web.Proxy.Helpers
}
}
}
#endif
using System;
#if NET45
using System;
namespace Titanium.Web.Proxy.Helpers
{
......@@ -19,3 +20,4 @@ namespace Titanium.Web.Proxy.Helpers
internal static bool IsRunningOnMono => isRunningOnMono.Value;
}
}
#endif
using System;
#if NET45
using System;
using System.Linq;
using Microsoft.Win32;
......@@ -327,3 +328,4 @@ namespace Titanium.Web.Proxy.Helpers
}
}
}
#endif
using System;
#if NET45
using System;
using System.Runtime.InteropServices;
// Helper classes for setting system proxy settings
......@@ -130,3 +131,4 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
}
}
}
#endif
#if NET45
using System;
using System.Runtime.InteropServices;
......@@ -17,3 +18,4 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
public override bool IsInvalid => handle == IntPtr.Zero;
}
}
#endif
#if NET45
using System;
using System.Collections.Generic;
using System.Net;
......@@ -330,3 +331,4 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
}
}
}
#endif
using System;
#if NET45
using System;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
......@@ -296,3 +297,4 @@ namespace Titanium.Web.Proxy.Network.Certificate
}
}
}
#endif
using System.Net;
#if NET45
using System.Net;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
......@@ -61,3 +62,4 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal int ProcessId { get; }
}
}
#endif
using System.Collections;
#if NET45
using System.Collections;
using System.Collections.Generic;
namespace Titanium.Web.Proxy.Network.Tcp
......@@ -44,3 +45,4 @@ namespace Titanium.Web.Proxy.Network.Tcp
}
}
}
#endif
using System;
#if NET45
using System;
using System.Runtime.InteropServices;
namespace Titanium.Web.Proxy.Network.WinAuth.Security
......@@ -280,3 +281,4 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
#endregion
}
}
#endif
#if NET45
//
// Mono.Security.BitConverterLE.cs
// Like System.BitConverter but always little endian
......@@ -250,3 +251,4 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
}
}
}
#endif
#if NET45
//
// Nancy.Authentication.Ntlm.Protocol.Type3Message - Authentication
//
......@@ -128,3 +129,4 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
}
}
}
#endif
using System;
#if NET45
using System;
namespace Titanium.Web.Proxy.Network.WinAuth.Security
{
......@@ -42,3 +43,4 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
}
}
}
#endif
// http://pinvoke.net/default.aspx/secur32/InitializeSecurityContext.html
#if NET45
// http://pinvoke.net/default.aspx/secur32/InitializeSecurityContext.html
using System;
using System.Collections.Concurrent;
......@@ -211,3 +212,4 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
#endregion
}
}
#endif
using System;
#if NET45
using System;
using Titanium.Web.Proxy.Network.WinAuth.Security;
namespace Titanium.Web.Proxy.Network.WinAuth
......@@ -40,3 +41,4 @@ namespace Titanium.Web.Proxy.Network.WinAuth
}
}
}
#endif
using StreamExtended.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
#if NET45
using Titanium.Web.Proxy.Helpers.WinHttp;
#endif
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
#if NET45
using Titanium.Web.Proxy.Network.WinAuth.Security;
#endif
namespace Titanium.Web.Proxy
{
/// <summary>
/// Proxy Server Main class
/// </summary>
public partial class ProxyServer : IDisposable
{
#if NET45
internal static readonly string UriSchemeHttp = Uri.UriSchemeHttp;
internal static readonly string UriSchemeHttps = Uri.UriSchemeHttps;
#else
internal const string UriSchemeHttp = "http";
internal const string UriSchemeHttps = "https";
#endif
/// <summary>
/// Is the proxy currently running
/// </summary>
private bool proxyRunning { get; set; }
/// <summary>
/// An default exception log func
/// </summary>
private readonly Lazy<Action<Exception>> defaultExceptionFunc = new Lazy<Action<Exception>>(() => (e => { }));
/// <summary>
/// backing exception func for exposed public property
/// </summary>
private Action<Exception> exceptionFunc;
/// <summary>
/// Backing field for corresponding public property
/// </summary>
private bool trustRootCertificate;
/// <summary>
/// Backing field for corresponding public property
/// </summary>
private int clientConnectionCount;
/// <summary>
/// Backing field for corresponding public property
/// </summary>
private int serverConnectionCount;
/// <summary>
/// A object that creates tcp connection to server
/// </summary>
private TcpConnectionFactory tcpConnectionFactory { get; }
#if NET45
private WinHttpWebProxyFinder systemProxyResolver;
/// <summary>
/// Manage system proxy settings
/// </summary>
private SystemProxyManager systemProxySettingsManager { get; }
/// <summary>
/// Set firefox to use default system proxy
/// </summary>
private readonly FireFoxProxySettingsManager firefoxProxySettingsManager = new FireFoxProxySettingsManager();
#endif
/// <summary>
/// Buffer size used throughout this proxy
/// </summary>
public int BufferSize { get; set; } = 8192;
/// <summary>
/// Manages certificates used by this proxy
/// </summary>
public CertificateManager CertificateManager { get; }
/// <summary>
/// The root certificate
/// </summary>
public X509Certificate2 RootCertificate
{
get { return CertificateManager.RootCertificate; }
set { CertificateManager.RootCertificate = value; }
}
/// <summary>
/// Name of the root certificate issuer
/// (This is valid only when RootCertificate property is not set)
/// </summary>
public string RootCertificateIssuerName
{
get { return CertificateManager.Issuer; }
set { CertificateManager.Issuer = value; }
}
/// <summary>
/// Name of the root certificate
/// (This is valid only when RootCertificate property is not set)
/// If no certificate is provided then a default Root Certificate will be created and used
/// The provided root certificate will be stored in proxy exe directory with the private key
/// Root certificate file will be named as "rootCert.pfx"
/// </summary>
public string RootCertificateName
{
get { return CertificateManager.RootCertificateName; }
set { CertificateManager.RootCertificateName = value; }
}
/// <summary>
/// Trust the RootCertificate used by this proxy server
/// Note that this do not make the client trust the certificate!
/// This would import the root certificate to the certificate store of machine that runs this proxy server
/// </summary>
public bool TrustRootCertificate
{
get { return trustRootCertificate; }
set
{
trustRootCertificate = value;
if (value)
{
EnsureRootCertificate();
}
}
}
/// <summary>
/// Select Certificate Engine
/// Optionally set to BouncyCastle
/// Mono only support BouncyCastle and it is the default
/// </summary>
public CertificateEngine CertificateEngine
{
get { return CertificateManager.Engine; }
set { CertificateManager.Engine = value; }
}
/// <summary>
/// Should we check for certificare revocation during SSL authentication to servers
/// Note: If enabled can reduce performance (Default disabled)
/// </summary>
public bool CheckCertificateRevocation { get; set; }
/// <summary>
/// Does this proxy uses the HTTP protocol 100 continue behaviour strictly?
/// Broken 100 contunue implementations on server/client may cause problems if enabled
/// </summary>
public bool Enable100ContinueBehaviour { get; set; }
/// <summary>
/// Minutes certificates should be kept in cache when not used
/// </summary>
public int CertificateCacheTimeOutMinutes { get; set; }
/// <summary>
/// Seconds client/server connection are to be kept alive when waiting for read/write to complete
/// </summary>
public int ConnectionTimeOutSeconds { get; set; }
/// <summary>
/// Intercept request to server
/// </summary>
public event Func<object, SessionEventArgs, Task> BeforeRequest;
/// <summary>
/// Intercept response from server
/// </summary>
public event Func<object, SessionEventArgs, Task> BeforeResponse;
/// <summary>
/// Intercept tunnel connect reques
/// </summary>
public event Func<object, TunnelConnectSessionEventArgs, Task> TunnelConnectRequest;
/// <summary>
/// Intercept tunnel connect response
/// </summary>
public event Func<object, TunnelConnectSessionEventArgs, Task> TunnelConnectResponse;
/// <summary>
/// Occurs when client connection count changed.
/// </summary>
public event EventHandler ClientConnectionCountChanged;
/// <summary>
/// Occurs when server connection count changed.
/// </summary>
public event EventHandler ServerConnectionCountChanged;
/// <summary>
/// External proxy for Http
/// </summary>
public ExternalProxy UpStreamHttpProxy { get; set; }
/// <summary>
/// External proxy for Http
/// </summary>
public ExternalProxy UpStreamHttpsProxy { get; set; }
/// <summary>
/// Local adapter/NIC endpoint (where proxy makes request via)
/// default via any IP addresses of this machine
/// </summary>
public IPEndPoint UpStreamEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
/// <summary>
/// Is the proxy currently running
/// </summary>
public bool ProxyRunning => proxyRunning;
/// <summary>
/// Gets or sets a value indicating whether requests will be chained to upstream gateway.
/// </summary>
public bool ForwardToUpstreamGateway { get; set; }
/// <summary>
/// Enable disable Windows Authentication (NTLM/Kerberos)
/// Note: NTLM/Kerberos will always send local credentials of current user
/// who is running the proxy process. This is because a man
/// in middle attack is not currently supported
/// (which would require windows delegation enabled for this server process)
/// </summary>
public bool EnableWinAuth { get; set; }
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
/// </summary>
public event Func<object, CertificateValidationEventArgs, Task> ServerCertificateValidationCallback;
/// <summary>
/// Callback tooverride client certificate during SSL mutual authentication
/// </summary>
public event Func<object, CertificateSelectionEventArgs, Task> ClientCertificateSelectionCallback;
/// <summary>
/// Callback for error events in proxy
/// </summary>
public Action<Exception> ExceptionFunc
{
get { return exceptionFunc ?? defaultExceptionFunc.Value; }
set { exceptionFunc = value; }
}
/// <summary>
/// A callback to authenticate clients
/// Parameters are username, password provided by client
/// return true for successful authentication
/// </summary>
public Func<string, string, Task<bool>> AuthenticateUserFunc { get; set; }
/// <summary>
/// Realm used during Proxy Basic Authentication
/// </summary>
public string ProxyRealm { get; set; } = "TitaniumProxy";
/// <summary>
/// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP requests
/// return the ExternalProxy object with valid credentials
/// </summary>
public Func<SessionEventArgs, Task<ExternalProxy>> GetCustomUpStreamHttpProxyFunc { get; set; }
/// <summary>
/// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTPS requests
/// return the ExternalProxy object with valid credentials
/// </summary>
public Func<SessionEventArgs, Task<ExternalProxy>> GetCustomUpStreamHttpsProxyFunc { get; set; }
/// <summary>
/// A list of IpAddress and port this proxy is listening to
/// </summary>
using StreamExtended.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
#if NET45
using Titanium.Web.Proxy.Helpers.WinHttp;
#endif
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
#if NET45
using Titanium.Web.Proxy.Network.WinAuth.Security;
#endif
namespace Titanium.Web.Proxy
{
/// <summary>
/// Proxy Server Main class
/// </summary>
public partial class ProxyServer : IDisposable
{
#if NET45
internal static readonly string UriSchemeHttp = Uri.UriSchemeHttp;
internal static readonly string UriSchemeHttps = Uri.UriSchemeHttps;
#else
internal const string UriSchemeHttp = "http";
internal const string UriSchemeHttps = "https";
#endif
/// <summary>
/// Is the proxy currently running
/// </summary>
private bool proxyRunning { get; set; }
/// <summary>
/// An default exception log func
/// </summary>
private readonly Lazy<Action<Exception>> defaultExceptionFunc = new Lazy<Action<Exception>>(() => (e => { }));
/// <summary>
/// backing exception func for exposed public property
/// </summary>
private Action<Exception> exceptionFunc;
/// <summary>
/// Backing field for corresponding public property
/// </summary>
private bool trustRootCertificate;
/// <summary>
/// Backing field for corresponding public property
/// </summary>
private int clientConnectionCount;
/// <summary>
/// Backing field for corresponding public property
/// </summary>
private int serverConnectionCount;
/// <summary>
/// A object that creates tcp connection to server
/// </summary>
private TcpConnectionFactory tcpConnectionFactory { get; }
#if NET45
private WinHttpWebProxyFinder systemProxyResolver;
/// <summary>
/// Manage system proxy settings
/// </summary>
private SystemProxyManager systemProxySettingsManager { get; }
/// <summary>
/// Set firefox to use default system proxy
/// </summary>
private readonly FireFoxProxySettingsManager firefoxProxySettingsManager = new FireFoxProxySettingsManager();
#endif
/// <summary>
/// Buffer size used throughout this proxy
/// </summary>
public int BufferSize { get; set; } = 8192;
/// <summary>
/// Manages certificates used by this proxy
/// </summary>
public CertificateManager CertificateManager { get; }
/// <summary>
/// The root certificate
/// </summary>
public X509Certificate2 RootCertificate
{
get { return CertificateManager.RootCertificate; }
set { CertificateManager.RootCertificate = value; }
}
/// <summary>
/// Name of the root certificate issuer
/// (This is valid only when RootCertificate property is not set)
/// </summary>
public string RootCertificateIssuerName
{
get { return CertificateManager.Issuer; }
set { CertificateManager.Issuer = value; }
}
/// <summary>
/// Name of the root certificate
/// (This is valid only when RootCertificate property is not set)
/// If no certificate is provided then a default Root Certificate will be created and used
/// The provided root certificate will be stored in proxy exe directory with the private key
/// Root certificate file will be named as "rootCert.pfx"
/// </summary>
public string RootCertificateName
{
get { return CertificateManager.RootCertificateName; }
set { CertificateManager.RootCertificateName = value; }
}
/// <summary>
/// Trust the RootCertificate used by this proxy server
/// Note that this do not make the client trust the certificate!
/// This would import the root certificate to the certificate store of machine that runs this proxy server
/// </summary>
public bool TrustRootCertificate
{
get { return trustRootCertificate; }
set
{
trustRootCertificate = value;
if (value)
{
EnsureRootCertificate();
}
}
}
/// <summary>
/// Select Certificate Engine
/// Optionally set to BouncyCastle
/// Mono only support BouncyCastle and it is the default
/// </summary>
public CertificateEngine CertificateEngine
{
get { return CertificateManager.Engine; }
set { CertificateManager.Engine = value; }
}
/// <summary>
/// Should we check for certificare revocation during SSL authentication to servers
/// Note: If enabled can reduce performance (Default disabled)
/// </summary>
public bool CheckCertificateRevocation { get; set; }
/// <summary>
/// Does this proxy uses the HTTP protocol 100 continue behaviour strictly?
/// Broken 100 contunue implementations on server/client may cause problems if enabled
/// </summary>
public bool Enable100ContinueBehaviour { get; set; }
/// <summary>
/// Minutes certificates should be kept in cache when not used
/// </summary>
public int CertificateCacheTimeOutMinutes { get; set; }
/// <summary>
/// Seconds client/server connection are to be kept alive when waiting for read/write to complete
/// </summary>
public int ConnectionTimeOutSeconds { get; set; }
/// <summary>
/// Intercept request to server
/// </summary>
public event Func<object, SessionEventArgs, Task> BeforeRequest;
/// <summary>
/// Intercept response from server
/// </summary>
public event Func<object, SessionEventArgs, Task> BeforeResponse;
/// <summary>
/// Intercept tunnel connect reques
/// </summary>
public event Func<object, TunnelConnectSessionEventArgs, Task> TunnelConnectRequest;
/// <summary>
/// Intercept tunnel connect response
/// </summary>
public event Func<object, TunnelConnectSessionEventArgs, Task> TunnelConnectResponse;
/// <summary>
/// Occurs when client connection count changed.
/// </summary>
public event EventHandler ClientConnectionCountChanged;
/// <summary>
/// Occurs when server connection count changed.
/// </summary>
public event EventHandler ServerConnectionCountChanged;
/// <summary>
/// External proxy for Http
/// </summary>
public ExternalProxy UpStreamHttpProxy { get; set; }
/// <summary>
/// External proxy for Http
/// </summary>
public ExternalProxy UpStreamHttpsProxy { get; set; }
/// <summary>
/// Local adapter/NIC endpoint (where proxy makes request via)
/// default via any IP addresses of this machine
/// </summary>
public IPEndPoint UpStreamEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
/// <summary>
/// Is the proxy currently running
/// </summary>
public bool ProxyRunning => proxyRunning;
/// <summary>
/// Gets or sets a value indicating whether requests will be chained to upstream gateway.
/// </summary>
public bool ForwardToUpstreamGateway { get; set; }
/// <summary>
/// Enable disable Windows Authentication (NTLM/Kerberos)
/// Note: NTLM/Kerberos will always send local credentials of current user
/// who is running the proxy process. This is because a man
/// in middle attack is not currently supported
/// (which would require windows delegation enabled for this server process)
/// </summary>
public bool EnableWinAuth { get; set; }
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
/// </summary>
public event Func<object, CertificateValidationEventArgs, Task> ServerCertificateValidationCallback;
/// <summary>
/// Callback tooverride client certificate during SSL mutual authentication
/// </summary>
public event Func<object, CertificateSelectionEventArgs, Task> ClientCertificateSelectionCallback;
/// <summary>
/// Callback for error events in proxy
/// </summary>
public Action<Exception> ExceptionFunc
{
get { return exceptionFunc ?? defaultExceptionFunc.Value; }
set { exceptionFunc = value; }
}
/// <summary>
/// A callback to authenticate clients
/// Parameters are username, password provided by client
/// return true for successful authentication
/// </summary>
public Func<string, string, Task<bool>> AuthenticateUserFunc { get; set; }
/// <summary>
/// Realm used during Proxy Basic Authentication
/// </summary>
public string ProxyRealm { get; set; } = "TitaniumProxy";
/// <summary>
/// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP requests
/// return the ExternalProxy object with valid credentials
/// </summary>
public Func<SessionEventArgs, Task<ExternalProxy>> GetCustomUpStreamHttpProxyFunc { get; set; }
/// <summary>
/// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTPS requests
/// return the ExternalProxy object with valid credentials
/// </summary>
public Func<SessionEventArgs, Task<ExternalProxy>> GetCustomUpStreamHttpsProxyFunc { get; set; }
/// <summary>
/// A list of IpAddress and port this proxy is listening to
/// </summary>
public List<ProxyEndPoint> ProxyEndPoints { get; set; }
/// <summary>
/// List of supported Ssl versions
/// </summary>
#if NET45
public SslProtocols SupportedSslProtocols { get; set; } = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Ssl3;
#else
public SslProtocols SupportedSslProtocols { get; set; } = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
#endif
/// <summary>
/// Total number of active client connections
/// </summary>
public int ClientConnectionCount => clientConnectionCount;
/// <summary>
/// Total number of active server connections
/// </summary>
public int ServerConnectionCount => serverConnectionCount;
/// <summary>
/// Constructor
/// </summary>
public ProxyServer() : this(null, null)
{
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="rootCertificateName">Name of root certificate.</param>
/// <param name="rootCertificateIssuerName">Name of root certificate issuer.</param>
public ProxyServer(string rootCertificateName, string rootCertificateIssuerName)
{
//default values
ConnectionTimeOutSeconds = 30;
CertificateCacheTimeOutMinutes = 60;
ProxyEndPoints = new List<ProxyEndPoint>();
tcpConnectionFactory = new TcpConnectionFactory();
#if NET45
if (!RunTime.IsRunningOnMono)
{
systemProxySettingsManager = new SystemProxyManager();
}
#endif
CertificateManager = new CertificateManager(ExceptionFunc);
if (rootCertificateName != null)
{
RootCertificateName = rootCertificateName;
}
if (rootCertificateIssuerName != null)
{
RootCertificateIssuerName = rootCertificateIssuerName;
}
}
/// <summary>
/// Add a proxy end point
/// </summary>
/// <param name="endPoint"></param>
public void AddEndPoint(ProxyEndPoint endPoint)
{
if (ProxyEndPoints.Any(x => x.IpAddress.Equals(endPoint.IpAddress) && endPoint.Port != 0 && x.Port == endPoint.Port))
{
throw new Exception("Cannot add another endpoint to same port & ip address");
}
ProxyEndPoints.Add(endPoint);
if (proxyRunning)
{
Listen(endPoint);
}
}
/// <summary>
/// Remove a proxy end point
/// Will throw error if the end point does'nt exist
/// </summary>
/// <param name="endPoint"></param>
public void RemoveEndPoint(ProxyEndPoint endPoint)
{
if (ProxyEndPoints.Contains(endPoint) == false)
{
throw new Exception("Cannot remove endPoints not added to proxy");
}
ProxyEndPoints.Remove(endPoint);
if (proxyRunning)
{
QuitListen(endPoint);
}
}
#if NET45
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// <param name="endPoint"></param>
public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint)
{
SetAsSystemProxy(endPoint, ProxyProtocolType.Http);
}
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// <param name="endPoint"></param>
public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint)
{
SetAsSystemProxy(endPoint, ProxyProtocolType.Https);
}
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// <param name="endPoint"></param>
/// <param name="protocolType"></param>
public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType)
{
if (RunTime.IsRunningOnMono)
{
throw new Exception("Mono Runtime do not support system proxy settings.");
}
ValidateEndPointAsSystemProxy(endPoint);
bool isHttp = (protocolType & ProxyProtocolType.Http) > 0;
bool isHttps = (protocolType & ProxyProtocolType.Https) > 0;
if (isHttps)
{
if (!endPoint.EnableSsl)
{
throw new Exception("Endpoint do not support Https connections");
}
EnsureRootCertificate();
//If certificate was trusted by the machine
if (!CertificateManager.CertValidated)
{
protocolType = protocolType & ~ProxyProtocolType.Https;
isHttps = false;
}
}
//clear any settings previously added
if (isHttp)
{
ProxyEndPoints.OfType<ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpProxy = false);
}
if (isHttps)
{
ProxyEndPoints.OfType<ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpsProxy = false);
}
systemProxySettingsManager.SetProxy(
Equals(endPoint.IpAddress, IPAddress.Any) |
Equals(endPoint.IpAddress, IPAddress.Loopback)
? "127.0.0.1"
: endPoint.IpAddress.ToString(),
endPoint.Port,
protocolType);
if (isHttp)
{
endPoint.IsSystemHttpsProxy = true;
}
if (isHttps)
{
endPoint.IsSystemHttpsProxy = true;
}
firefoxProxySettingsManager.UseSystemProxy();
string proxyType = null;
switch (protocolType)
{
case ProxyProtocolType.Http:
proxyType = "HTTP";
break;
case ProxyProtocolType.Https:
proxyType = "HTTPS";
break;
case ProxyProtocolType.AllHttp:
proxyType = "HTTP and HTTPS";
break;
}
if (protocolType != ProxyProtocolType.None)
{
Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System {2} Proxy", endPoint.IpAddress, endPoint.Port, proxyType);
}
}
/// <summary>
/// Remove any HTTP proxy setting of current machien
/// </summary>
public void DisableSystemHttpProxy()
{
DisableSystemProxy(ProxyProtocolType.Http);
}
/// <summary>
/// Remove any HTTPS proxy setting for current machine
/// </summary>
public void DisableSystemHttpsProxy()
{
DisableSystemProxy(ProxyProtocolType.Https);
}
/// <summary>
/// Remove the specified proxy settings for current machine
/// </summary>
public void DisableSystemProxy(ProxyProtocolType protocolType)
{
if (RunTime.IsRunningOnMono)
{
throw new Exception("Mono Runtime do not support system proxy settings.");
}
systemProxySettingsManager.RemoveProxy(protocolType);
}
/// <summary>
/// Clear all proxy settings for current machine
/// </summary>
public void DisableAllSystemProxies()
{
if (RunTime.IsRunningOnMono)
{
throw new Exception("Mono Runtime do not support system proxy settings.");
}
systemProxySettingsManager.DisableAllProxy();
}
#endif
/// <summary>
/// Start this proxy server
/// </summary>
public void Start()
{
if (proxyRunning)
{
throw new Exception("Proxy is already running.");
}
#if NET45
//clear any system proxy settings which is pointing to our own endpoint (causing a cycle)
//due to non gracious proxy shutdown before or something else
if (systemProxySettingsManager != null)
{
var proxyInfo = systemProxySettingsManager.GetProxyInfoFromRegistry();
if (proxyInfo.Proxies != null)
{
var protocolToRemove = ProxyProtocolType.None;
foreach (var proxy in proxyInfo.Proxies.Values)
{
/// <summary>
/// List of supported Ssl versions
/// </summary>
#if NET45
public SslProtocols SupportedSslProtocols { get; set; } = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Ssl3;
#else
public SslProtocols SupportedSslProtocols { get; set; } = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
#endif
/// <summary>
/// Total number of active client connections
/// </summary>
public int ClientConnectionCount => clientConnectionCount;
/// <summary>
/// Total number of active server connections
/// </summary>
public int ServerConnectionCount => serverConnectionCount;
/// <summary>
/// Constructor
/// </summary>
public ProxyServer() : this(null, null)
{
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="rootCertificateName">Name of root certificate.</param>
/// <param name="rootCertificateIssuerName">Name of root certificate issuer.</param>
public ProxyServer(string rootCertificateName, string rootCertificateIssuerName)
{
//default values
ConnectionTimeOutSeconds = 30;
CertificateCacheTimeOutMinutes = 60;
ProxyEndPoints = new List<ProxyEndPoint>();
tcpConnectionFactory = new TcpConnectionFactory();
#if NET45
if (!RunTime.IsRunningOnMono)
{
systemProxySettingsManager = new SystemProxyManager();
}
#endif
CertificateManager = new CertificateManager(ExceptionFunc);
if (rootCertificateName != null)
{
RootCertificateName = rootCertificateName;
}
if (rootCertificateIssuerName != null)
{
RootCertificateIssuerName = rootCertificateIssuerName;
}
}
/// <summary>
/// Add a proxy end point
/// </summary>
/// <param name="endPoint"></param>
public void AddEndPoint(ProxyEndPoint endPoint)
{
if (ProxyEndPoints.Any(x => x.IpAddress.Equals(endPoint.IpAddress) && endPoint.Port != 0 && x.Port == endPoint.Port))
{
throw new Exception("Cannot add another endpoint to same port & ip address");
}
ProxyEndPoints.Add(endPoint);
if (proxyRunning)
{
Listen(endPoint);
}
}
/// <summary>
/// Remove a proxy end point
/// Will throw error if the end point does'nt exist
/// </summary>
/// <param name="endPoint"></param>
public void RemoveEndPoint(ProxyEndPoint endPoint)
{
if (ProxyEndPoints.Contains(endPoint) == false)
{
throw new Exception("Cannot remove endPoints not added to proxy");
}
ProxyEndPoints.Remove(endPoint);
if (proxyRunning)
{
QuitListen(endPoint);
}
}
#if NET45
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// <param name="endPoint"></param>
public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint)
{
SetAsSystemProxy(endPoint, ProxyProtocolType.Http);
}
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// <param name="endPoint"></param>
public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint)
{
SetAsSystemProxy(endPoint, ProxyProtocolType.Https);
}
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// <param name="endPoint"></param>
/// <param name="protocolType"></param>
public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType)
{
if (RunTime.IsRunningOnMono)
{
throw new Exception("Mono Runtime do not support system proxy settings.");
}
ValidateEndPointAsSystemProxy(endPoint);
bool isHttp = (protocolType & ProxyProtocolType.Http) > 0;
bool isHttps = (protocolType & ProxyProtocolType.Https) > 0;
if (isHttps)
{
if (!endPoint.EnableSsl)
{
throw new Exception("Endpoint do not support Https connections");
}
EnsureRootCertificate();
//If certificate was trusted by the machine
if (!CertificateManager.CertValidated)
{
protocolType = protocolType & ~ProxyProtocolType.Https;
isHttps = false;
}
}
//clear any settings previously added
if (isHttp)
{
ProxyEndPoints.OfType<ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpProxy = false);
}
if (isHttps)
{
ProxyEndPoints.OfType<ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpsProxy = false);
}
systemProxySettingsManager.SetProxy(
Equals(endPoint.IpAddress, IPAddress.Any) |
Equals(endPoint.IpAddress, IPAddress.Loopback)
? "127.0.0.1"
: endPoint.IpAddress.ToString(),
endPoint.Port,
protocolType);
if (isHttp)
{
endPoint.IsSystemHttpsProxy = true;
}
if (isHttps)
{
endPoint.IsSystemHttpsProxy = true;
}
firefoxProxySettingsManager.UseSystemProxy();
string proxyType = null;
switch (protocolType)
{
case ProxyProtocolType.Http:
proxyType = "HTTP";
break;
case ProxyProtocolType.Https:
proxyType = "HTTPS";
break;
case ProxyProtocolType.AllHttp:
proxyType = "HTTP and HTTPS";
break;
}
if (protocolType != ProxyProtocolType.None)
{
Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System {2} Proxy", endPoint.IpAddress, endPoint.Port, proxyType);
}
}
/// <summary>
/// Remove any HTTP proxy setting of current machien
/// </summary>
public void DisableSystemHttpProxy()
{
DisableSystemProxy(ProxyProtocolType.Http);
}
/// <summary>
/// Remove any HTTPS proxy setting for current machine
/// </summary>
public void DisableSystemHttpsProxy()
{
DisableSystemProxy(ProxyProtocolType.Https);
}
/// <summary>
/// Remove the specified proxy settings for current machine
/// </summary>
public void DisableSystemProxy(ProxyProtocolType protocolType)
{
if (RunTime.IsRunningOnMono)
{
throw new Exception("Mono Runtime do not support system proxy settings.");
}
systemProxySettingsManager.RemoveProxy(protocolType);
}
/// <summary>
/// Clear all proxy settings for current machine
/// </summary>
public void DisableAllSystemProxies()
{
if (RunTime.IsRunningOnMono)
{
throw new Exception("Mono Runtime do not support system proxy settings.");
}
systemProxySettingsManager.DisableAllProxy();
}
#endif
/// <summary>
/// Start this proxy server
/// </summary>
public void Start()
{
if (proxyRunning)
{
throw new Exception("Proxy is already running.");
}
#if NET45
//clear any system proxy settings which is pointing to our own endpoint (causing a cycle)
//due to non gracious proxy shutdown before or something else
if (systemProxySettingsManager != null)
{
var proxyInfo = systemProxySettingsManager.GetProxyInfoFromRegistry();
if (proxyInfo.Proxies != null)
{
var protocolToRemove = ProxyProtocolType.None;
foreach (var proxy in proxyInfo.Proxies.Values)
{
if ((proxy.HostName == "127.0.0.1"
|| proxy.HostName.Equals("localhost", StringComparison.OrdinalIgnoreCase))
&& ProxyEndPoints.Any(x => x.Port == proxy.Port))
{
protocolToRemove |= proxy.ProtocolType;
}
}
if (protocolToRemove != ProxyProtocolType.None)
{
//do not restore to any of listening address when we quit
systemProxySettingsManager.RemoveProxy(protocolToRemove, false);
}
}
}
if (ForwardToUpstreamGateway
&& GetCustomUpStreamHttpProxyFunc == null && GetCustomUpStreamHttpsProxyFunc == null
&& systemProxySettingsManager != null)
{
// Use WinHttp to handle PAC/WAPD scripts.
systemProxyResolver = new WinHttpWebProxyFinder();
systemProxyResolver.LoadFromIE();
GetCustomUpStreamHttpProxyFunc = GetSystemUpStreamProxy;
GetCustomUpStreamHttpsProxyFunc = GetSystemUpStreamProxy;
}
#endif
foreach (var endPoint in ProxyEndPoints)
{
Listen(endPoint);
}
CertificateManager.ClearIdleCertificates(CertificateCacheTimeOutMinutes);
#if NET45
if (!RunTime.IsRunningOnMono)
{
//clear orphaned windows auth states every 2 minutes
WinAuthEndPoint.ClearIdleStates(2);
}
#endif
proxyRunning = true;
}
/// <summary>
/// Stop this proxy server
/// </summary>
public void Stop()
{
if (!proxyRunning)
{
throw new Exception("Proxy is not running.");
}
#if NET45
if (!RunTime.IsRunningOnMono)
{
bool setAsSystemProxy = ProxyEndPoints.OfType<ExplicitProxyEndPoint>().Any(x => x.IsSystemHttpProxy || x.IsSystemHttpsProxy);
if (setAsSystemProxy)
{
systemProxySettingsManager.RestoreOriginalSettings();
}
}
#endif
foreach (var endPoint in ProxyEndPoints)
{
QuitListen(endPoint);
}
ProxyEndPoints.Clear();
CertificateManager?.StopClearIdleCertificates();
proxyRunning = false;
}
/// <summary>
/// Handle dispose of a client/server session
/// </summary>
/// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="serverConnection"></param>
private void Dispose(CustomBufferedStream clientStream, CustomBinaryReader clientStreamReader, HttpResponseWriter clientStreamWriter, TcpConnection serverConnection)
{
clientStream?.Dispose();
clientStreamReader?.Dispose();
clientStreamWriter?.Dispose();
if (serverConnection != null)
{
serverConnection.Dispose();
serverConnection = null;
UpdateServerConnectionCount(false);
}
}
/// <summary>
/// Dispose Proxy.
/// </summary>
public void Dispose()
{
if (proxyRunning)
{
Stop();
}
CertificateManager?.Dispose();
}
#if NET45
/// <summary>
/// Listen on the given end point on local machine
/// </summary>
/// <param name="endPoint"></param>
private void Listen(ProxyEndPoint endPoint)
{
endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
endPoint.Listener.Start();
endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port;
// accept clients asynchronously
endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
}
#else
private async void Listen(ProxyEndPoint endPoint)
{
endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
endPoint.Listener.Start();
endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port;
while (true)
{
TcpClient tcpClient = await endPoint.Listener.AcceptTcpClientAsync();
if (tcpClient != null)
Task.Run(async () => HandleClient(tcpClient, endPoint));
}
}
#endif
/// <summary>
/// Verifiy if its safe to set this end point as System proxy
/// </summary>
/// <param name="endPoint"></param>
private void ValidateEndPointAsSystemProxy(ExplicitProxyEndPoint endPoint)
{
if (endPoint == null)
throw new ArgumentNullException(nameof(endPoint));
if (ProxyEndPoints.Contains(endPoint) == false)
{
throw new Exception("Cannot set endPoints not added to proxy as system proxy");
}
if (!proxyRunning)
{
throw new Exception("Cannot set system proxy settings before proxy has been started.");
}
}
#if NET45
/// <summary>
/// Gets the system up stream proxy.
/// </summary>
/// <param name="sessionEventArgs">The <see cref="SessionEventArgs"/> instance containing the event data.</param>
/// <returns><see cref="ExternalProxy"/> instance containing valid proxy configuration from PAC/WAPD scripts if any exists.</returns>
private Task<ExternalProxy> GetSystemUpStreamProxy(SessionEventArgs sessionEventArgs)
{
var proxy = systemProxyResolver.GetProxy(sessionEventArgs.WebSession.Request.RequestUri);
return Task.FromResult(proxy);
}
#endif
private void EnsureRootCertificate()
{
if (!CertificateManager.CertValidated)
{
CertificateManager.CreateTrustedRootCertificate();
if (TrustRootCertificate)
{
CertificateManager.TrustRootCertificate();
}
}
}
#if NET45
/// <summary>
/// When a connection is received from client act
/// </summary>
/// <param name="asyn"></param>
private void OnAcceptConnection(IAsyncResult asyn)
{
var endPoint = (ProxyEndPoint)asyn.AsyncState;
TcpClient tcpClient = null;
try
{
//based on end point type call appropriate request handlers
tcpClient = endPoint.Listener.EndAcceptTcpClient(asyn);
}
catch (ObjectDisposedException)
{
// The listener was Stop()'d, disposing the underlying socket and
// triggering the completion of the callback. We're already exiting,
// so just return.
return;
}
catch
{
//Other errors are discarded to keep proxy running
}
if (tcpClient != null)
{
Task.Run(async () =>
{
await HandleClient(tcpClient, endPoint);
});
}
// Get the listener that handles the client request.
endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
}
#endif
private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint)
{
UpdateClientConnectionCount(true);
tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000;
try
{
if (endPoint.GetType() == typeof(TransparentProxyEndPoint))
{
await HandleClient(endPoint as TransparentProxyEndPoint, tcpClient);
}
else
{
await HandleClient(endPoint as ExplicitProxyEndPoint, tcpClient);
}
}
finally
{
UpdateClientConnectionCount(false);
try
{
if (tcpClient != null)
{
//This line is important!
//contributors please don't remove it without discussion
//It helps to avoid eventual deterioration of performance due to TCP port exhaustion
//due to default TCP CLOSE_WAIT timeout for 4 minutes
tcpClient.LingerState = new LingerOption(true, 0);
tcpClient.Dispose();
}
}
catch
{
}
}
}
/// <summary>
/// Quit listening on the given end point
/// </summary>
/// <param name="endPoint"></param>
private void QuitListen(ProxyEndPoint endPoint)
{
endPoint.Listener.Stop();
endPoint.Listener.Server.Dispose();
}
internal void UpdateClientConnectionCount(bool increment)
{
if (increment)
{
Interlocked.Increment(ref clientConnectionCount);
}
else
{
Interlocked.Decrement(ref clientConnectionCount);
}
ClientConnectionCountChanged?.Invoke(this, EventArgs.Empty);
}
internal void UpdateServerConnectionCount(bool increment)
{
if (increment)
{
Interlocked.Increment(ref serverConnectionCount);
}
else
{
Interlocked.Decrement(ref serverConnectionCount);
}
ServerConnectionCountChanged?.Invoke(this, EventArgs.Empty);
}
}
}
{
protocolToRemove |= proxy.ProtocolType;
}
}
if (protocolToRemove != ProxyProtocolType.None)
{
//do not restore to any of listening address when we quit
systemProxySettingsManager.RemoveProxy(protocolToRemove, false);
}
}
}
if (ForwardToUpstreamGateway
&& GetCustomUpStreamHttpProxyFunc == null && GetCustomUpStreamHttpsProxyFunc == null
&& systemProxySettingsManager != null)
{
// Use WinHttp to handle PAC/WAPD scripts.
systemProxyResolver = new WinHttpWebProxyFinder();
systemProxyResolver.LoadFromIE();
GetCustomUpStreamHttpProxyFunc = GetSystemUpStreamProxy;
GetCustomUpStreamHttpsProxyFunc = GetSystemUpStreamProxy;
}
#endif
foreach (var endPoint in ProxyEndPoints)
{
Listen(endPoint);
}
CertificateManager.ClearIdleCertificates(CertificateCacheTimeOutMinutes);
#if NET45
if (!RunTime.IsRunningOnMono)
{
//clear orphaned windows auth states every 2 minutes
WinAuthEndPoint.ClearIdleStates(2);
}
#endif
proxyRunning = true;
}
/// <summary>
/// Stop this proxy server
/// </summary>
public void Stop()
{
if (!proxyRunning)
{
throw new Exception("Proxy is not running.");
}
#if NET45
if (!RunTime.IsRunningOnMono)
{
bool setAsSystemProxy = ProxyEndPoints.OfType<ExplicitProxyEndPoint>().Any(x => x.IsSystemHttpProxy || x.IsSystemHttpsProxy);
if (setAsSystemProxy)
{
systemProxySettingsManager.RestoreOriginalSettings();
}
}
#endif
foreach (var endPoint in ProxyEndPoints)
{
QuitListen(endPoint);
}
ProxyEndPoints.Clear();
CertificateManager?.StopClearIdleCertificates();
proxyRunning = false;
}
/// <summary>
/// Handle dispose of a client/server session
/// </summary>
/// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="serverConnection"></param>
private void Dispose(CustomBufferedStream clientStream, CustomBinaryReader clientStreamReader, HttpResponseWriter clientStreamWriter, TcpConnection serverConnection)
{
clientStream?.Dispose();
clientStreamReader?.Dispose();
clientStreamWriter?.Dispose();
if (serverConnection != null)
{
serverConnection.Dispose();
serverConnection = null;
UpdateServerConnectionCount(false);
}
}
/// <summary>
/// Dispose Proxy.
/// </summary>
public void Dispose()
{
if (proxyRunning)
{
Stop();
}
CertificateManager?.Dispose();
}
#if NET45
/// <summary>
/// Listen on the given end point on local machine
/// </summary>
/// <param name="endPoint"></param>
private void Listen(ProxyEndPoint endPoint)
{
endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
endPoint.Listener.Start();
endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port;
// accept clients asynchronously
endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
}
#else
private async void Listen(ProxyEndPoint endPoint)
{
endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
endPoint.Listener.Start();
endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port;
while (true)
{
TcpClient tcpClient = await endPoint.Listener.AcceptTcpClientAsync();
if (tcpClient != null)
Task.Run(async () => HandleClient(tcpClient, endPoint));
}
}
#endif
/// <summary>
/// Verifiy if its safe to set this end point as System proxy
/// </summary>
/// <param name="endPoint"></param>
private void ValidateEndPointAsSystemProxy(ExplicitProxyEndPoint endPoint)
{
if (endPoint == null)
throw new ArgumentNullException(nameof(endPoint));
if (ProxyEndPoints.Contains(endPoint) == false)
{
throw new Exception("Cannot set endPoints not added to proxy as system proxy");
}
if (!proxyRunning)
{
throw new Exception("Cannot set system proxy settings before proxy has been started.");
}
}
#if NET45
/// <summary>
/// Gets the system up stream proxy.
/// </summary>
/// <param name="sessionEventArgs">The <see cref="SessionEventArgs"/> instance containing the event data.</param>
/// <returns><see cref="ExternalProxy"/> instance containing valid proxy configuration from PAC/WAPD scripts if any exists.</returns>
private Task<ExternalProxy> GetSystemUpStreamProxy(SessionEventArgs sessionEventArgs)
{
var proxy = systemProxyResolver.GetProxy(sessionEventArgs.WebSession.Request.RequestUri);
return Task.FromResult(proxy);
}
#endif
private void EnsureRootCertificate()
{
if (!CertificateManager.CertValidated)
{
CertificateManager.CreateTrustedRootCertificate();
if (TrustRootCertificate)
{
CertificateManager.TrustRootCertificate();
}
}
}
#if NET45
/// <summary>
/// When a connection is received from client act
/// </summary>
/// <param name="asyn"></param>
private void OnAcceptConnection(IAsyncResult asyn)
{
var endPoint = (ProxyEndPoint)asyn.AsyncState;
TcpClient tcpClient = null;
try
{
//based on end point type call appropriate request handlers
tcpClient = endPoint.Listener.EndAcceptTcpClient(asyn);
}
catch (ObjectDisposedException)
{
// The listener was Stop()'d, disposing the underlying socket and
// triggering the completion of the callback. We're already exiting,
// so just return.
return;
}
catch
{
//Other errors are discarded to keep proxy running
}
if (tcpClient != null)
{
Task.Run(async () =>
{
await HandleClient(tcpClient, endPoint);
});
}
// Get the listener that handles the client request.
endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
}
#endif
private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint)
{
UpdateClientConnectionCount(true);
tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000;
try
{
if (endPoint.GetType() == typeof(TransparentProxyEndPoint))
{
await HandleClient(endPoint as TransparentProxyEndPoint, tcpClient);
}
else
{
await HandleClient(endPoint as ExplicitProxyEndPoint, tcpClient);
}
}
finally
{
UpdateClientConnectionCount(false);
try
{
if (tcpClient != null)
{
//This line is important!
//contributors please don't remove it without discussion
//It helps to avoid eventual deterioration of performance due to TCP port exhaustion
//due to default TCP CLOSE_WAIT timeout for 4 minutes
tcpClient.LingerState = new LingerOption(true, 0);
tcpClient.Dispose();
}
}
catch
{
}
}
}
/// <summary>
/// Quit listening on the given end point
/// </summary>
/// <param name="endPoint"></param>
private void QuitListen(ProxyEndPoint endPoint)
{
endPoint.Listener.Stop();
endPoint.Listener.Server.Dispose();
}
internal void UpdateClientConnectionCount(bool increment)
{
if (increment)
{
Interlocked.Increment(ref clientConnectionCount);
}
else
{
Interlocked.Decrement(ref clientConnectionCount);
}
ClientConnectionCountChanged?.Invoke(this, EventArgs.Empty);
}
internal void UpdateServerConnectionCount(bool increment)
{
if (increment)
{
Interlocked.Increment(ref serverConnectionCount);
}
else
{
Interlocked.Decrement(ref serverConnectionCount);
}
ServerConnectionCountChanged?.Invoke(this, EventArgs.Empty);
}
}
}
......@@ -132,7 +132,6 @@ namespace Titanium.Web.Proxy
try
{
sslStream = new SslStream(clientStream);
string certName = HttpHelper.GetWildCardDomainName(httpRemoteUri.Host);
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
<RootNamespace>Titanium.Web.Proxy</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Helpers\WinHttp\NativeMethods.WinHttp.cs" />
<Compile Remove="Helpers\WinHttp\WinHttpHandle.cs" />
<Compile Remove="Helpers\WinHttp\WinHttpWebProxyFinder.cs" />
<Compile Remove="Helpers\NativeMethods.SystemProxy.cs" />
<Compile Remove="Helpers\NativeMethods.Tcp.cs" />
<Compile Remove="Helpers\Firefox.cs" />
<Compile Remove="Helpers\ProxyInfo.cs" />
<Compile Remove="Helpers\RunTime.cs" />
<Compile Remove="Helpers\SystemProxy.cs" />
<Compile Remove="Network\Certificate\WinCertificateMaker.cs" />
<Compile Remove="Network\Tcp\TcpRow.cs" />
<Compile Remove="Network\Tcp\TcpTable.cs" />
<Compile Remove="Network\WinAuth\Security\Common.cs" />
<Compile Remove="Network\WinAuth\Security\LittleEndian.cs" />
<Compile Remove="Network\WinAuth\Security\Message.cs" />
<Compile Remove="Network\WinAuth\Security\State.cs" />
<Compile Remove="Network\WinAuth\Security\WinAuthEndPoint.cs" />
<Compile Remove="Network\WinAuth\WinAuthHandler.cs" />
<Compile Remove="WinAuthHandler.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Portable.BouncyCastle" Version="1.8.1.2" />
<PackageReference Include="StreamExtended" Version="1.0.18" />
<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
<PackageReference Include="System.Net.Security" Version="4.3.1" />
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
<PackageReference Include="System.Security.SecureString" Version="4.3.0" />
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
<RootNamespace>Titanium.Web.Proxy</RootNamespace>
<AssemblyName>Titanium.Web.Proxy</AssemblyName>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;NET45</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<Prefer32Bit>false</Prefer32Bit>
<DocumentationFile>bin\Debug\Titanium.Web.Proxy.XML</DocumentationFile>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>bin\Release\</OutputPath>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<DefineConstants>NET45</DefineConstants>
<Prefer32Bit>false</Prefer32Bit>
<DocumentationFile>bin\Release\Titanium.Web.Proxy.XML</DocumentationFile>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\Portable.BouncyCastle.1.8.1.2\lib\net4\BouncyCastle.Crypto.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="StreamExtended, Version=1.0.1.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
<HintPath>..\packages\StreamExtended.1.0.18\lib\net45\StreamExtended.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="Compression\CompressionFactory.cs" />
<Compile Include="Compression\DeflateCompression.cs" />
<Compile Include="Compression\GZipCompression.cs" />
<Compile Include="Compression\ICompression.cs" />
<Compile Include="Decompression\DecompressionFactory.cs" />
<Compile Include="Decompression\DefaultDecompression.cs" />
<Compile Include="Decompression\DeflateDecompression.cs" />
<Compile Include="Decompression\GZipDecompression.cs" />
<Compile Include="Decompression\IDecompression.cs" />
<Compile Include="EventArguments\CertificateSelectionEventArgs.cs" />
<Compile Include="EventArguments\CertificateValidationEventArgs.cs" />
<Compile Include="EventArguments\DataEventArgs.cs" />
<Compile Include="EventArguments\SessionEventArgs.cs" />
<Compile Include="EventArguments\TunnelConnectEventArgs.cs" />
<Compile Include="Exceptions\BodyNotFoundException.cs" />
<Compile Include="Exceptions\ProxyAuthorizationException.cs" />
<Compile Include="Exceptions\ProxyException.cs" />
<Compile Include="Exceptions\ProxyHttpException.cs" />
<Compile Include="Extensions\ByteArrayExtensions.cs" />
<Compile Include="Extensions\DotNet45Extensions.cs" />
<Compile Include="Extensions\FuncExtensions.cs" />
<Compile Include="Extensions\HttpWebRequestExtensions.cs" />
<Compile Include="Extensions\HttpWebResponseExtensions.cs" />
<Compile Include="Extensions\StreamExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Extensions\TcpExtensions.cs" />
<Compile Include="Helpers\Firefox.cs" />
<Compile Include="Helpers\HttpRequestWriter.cs" />
<Compile Include="Helpers\HttpResponseWriter.cs" />
<Compile Include="Helpers\HttpWriter.cs" />
<Compile Include="Helpers\HttpHelper.cs" />
<Compile Include="Helpers\Network.cs" />
<Compile Include="Helpers\Tcp.cs" />
<Compile Include="Http\ConnectRequest.cs" />
<Compile Include="Http\ConnectResponse.cs" />
<Compile Include="Http\HeaderCollection.cs" />
<Compile Include="Http\HeaderParser.cs" />
<Compile Include="Http\HttpWebClient.cs" />
<Compile Include="Http\Request.cs" />
<Compile Include="Http\Response.cs" />
<Compile Include="Http\Responses\GenericResponse.cs" />
<Compile Include="Http\Responses\OkResponse.cs" />
<Compile Include="Http\Responses\RedirectResponse.cs" />
<Compile Include="Models\EndPoint.cs" />
<Compile Include="Models\ExternalProxy.cs" />
<Compile Include="Models\HttpHeader.cs" />
<Compile Include="Network\CachedCertificate.cs" />
<Compile Include="Network\Certificate\BCCertificateMaker.cs" />
<Compile Include="Network\Certificate\ICertificateMaker.cs" />
<Compile Include="Network\Certificate\WinCertificateMaker.cs" />
<Compile Include="Network\CertificateManager.cs" />
<Compile Include="Network\ProxyClient.cs" />
<Compile Include="Network\Tcp\TcpConnection.cs" />
<Compile Include="Network\Tcp\TcpConnectionFactory.cs" />
<Compile Include="Network\WinAuth\Security\Common.cs" />
<Compile Include="Network\WinAuth\Security\LittleEndian.cs" />
<Compile Include="Network\WinAuth\Security\Message.cs" />
<Compile Include="Network\WinAuth\Security\State.cs" />
<Compile Include="Network\WinAuth\Security\WinAuthEndPoint.cs" />
<Compile Include="Network\WinAuth\WinAuthHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Shared\ProxyConstants.cs" />
<Compile Include="WinAuthHandler.cs" />
<Compile Include="CertificateHandler.cs" />
<Compile Include="ProxyAuthorizationHandler.cs" />
<Compile Include="ProxyServer.cs" />
<Compile Include="RequestHandler.cs" />
<Compile Include="ResponseHandler.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Helpers\WinHttp\NativeMethods.WinHttp.cs" />
<Compile Include="Helpers\WinHttp\WinHttpHandle.cs" />
<Compile Include="Helpers\WinHttp\WinHttpWebProxyFinder.cs" />
<Compile Include="Helpers\NativeMethods.SystemProxy.cs" />
<Compile Include="Helpers\NativeMethods.Tcp.cs" />
<Compile Include="Helpers\ProxyInfo.cs" />
<Compile Include="Helpers\RunTime.cs" />
<Compile Include="Helpers\SystemProxy.cs" />
<Compile Include="Network\Tcp\TcpRow.cs" />
<Compile Include="Network\Tcp\TcpTable.cs" />
</ItemGroup>
<ItemGroup>
<COMReference Include="CERTENROLLLib" Condition="'$(OS)' != 'Unix'">
<Guid>{728AB348-217D-11DA-B2A4-000E7BBB2B09}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="StrongNameKey.snk" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.1.2" />
<PackageReference Include="StreamExtended" Version="1.0.18" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
......@@ -13,13 +13,13 @@
<releaseNotes></releaseNotes>
<copyright>Copyright &#x00A9; Titanium. All rights reserved.</copyright>
<tags></tags>
<dependencies>
<dependency id="StreamExtended" version="1.0.18" />
<dependency id="Portable.BouncyCastle" version="1.8.1.2" />
<dependencies>
<dependency id="StreamExtended" version="1.0.18" />
<dependency id="Portable.BouncyCastle" version="1.8.1.2" />
</dependencies>
</metadata>
<files>
<file src="bin\$configuration$\Titanium.Web.Proxy.dll" target="lib\net45" />
<file src="bin\$configuration$\netstandard1.6\Titanium.Web.Proxy.*" target="lib\netstandard1.6" />
<file src="bin\$configuration$\net45\Titanium.Web.Proxy.dll" target="lib\net45" />
<file src="bin\$configuration$\netstandard2.0\Titanium.Web.Proxy.*" target="lib\netstandard2.0" />
</files>
</package>
using System;
#if NET45
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
......@@ -148,3 +149,4 @@ namespace Titanium.Web.Proxy
}
}
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment