Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
T
Titanium-Web-Proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Titanium-Web-Proxy
Commits
00eaed63
Commit
00eaed63
authored
Sep 24, 2017
by
justcoding121
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'beta' into stable
parents
11632fe1
b64e703c
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
965 additions
and
1190 deletions
+965
-1190
default.ps1
.build/default.ps1
+8
-16
Titanium.Web.Proxy.Examples.Basic.Standard.csproj
...tandard/Titanium.Web.Proxy.Examples.Basic.Standard.csproj
+2
-2
Capture.PNG
Examples/Titanium.Web.Proxy.Examples.Wpf/Capture.PNG
+0
-0
README.md
README.md
+7
-1
Titanium.Web.Proxy.Standard.sln
Titanium.Web.Proxy.Standard.sln
+0
-58
Titanium.Web.Proxy.sln
Titanium.Web.Proxy.sln
+10
-2
Firefox.cs
Titanium.Web.Proxy/Helpers/Firefox.cs
+3
-1
NativeMethods.SystemProxy.cs
Titanium.Web.Proxy/Helpers/NativeMethods.SystemProxy.cs
+4
-2
NativeMethods.Tcp.cs
Titanium.Web.Proxy/Helpers/NativeMethods.Tcp.cs
+3
-1
ProxyInfo.cs
Titanium.Web.Proxy/Helpers/ProxyInfo.cs
+3
-1
RunTime.cs
Titanium.Web.Proxy/Helpers/RunTime.cs
+3
-1
SystemProxy.cs
Titanium.Web.Proxy/Helpers/SystemProxy.cs
+3
-1
NativeMethods.WinHttp.cs
Titanium.Web.Proxy/Helpers/WinHttp/NativeMethods.WinHttp.cs
+3
-1
WinHttpHandle.cs
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpHandle.cs
+2
-0
WinHttpWebProxyFinder.cs
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs
+2
-0
WinCertificateMaker.cs
...nium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs
+3
-1
TcpRow.cs
Titanium.Web.Proxy/Network/Tcp/TcpRow.cs
+3
-1
TcpTable.cs
Titanium.Web.Proxy/Network/Tcp/TcpTable.cs
+3
-1
Common.cs
Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs
+3
-1
LittleEndian.cs
Titanium.Web.Proxy/Network/WinAuth/Security/LittleEndian.cs
+2
-0
Message.cs
Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs
+2
-0
State.cs
Titanium.Web.Proxy/Network/WinAuth/Security/State.cs
+3
-1
WinAuthEndPoint.cs
...ium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs
+3
-1
WinAuthHandler.cs
Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs
+3
-1
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+868
-868
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+0
-1
Titanium.Web.Proxy.Standard.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.Standard.csproj
+0
-47
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+11
-174
Titanium.Web.Proxy.nuspec
Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
+5
-5
WinAuthHandler.cs
Titanium.Web.Proxy/WinAuthHandler.cs
+3
-1
No files found.
.build/default.ps1
View file @
00eaed63
...
...
@@ -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
Examples/Titanium.Web.Proxy.Examples.Basic.Standard/Titanium.Web.Proxy.Examples.Basic.Standard.csproj
View file @
00eaed63
...
...
@@ -2,11 +2,11 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp
1.1
</TargetFramework>
<TargetFramework>netcoreapp
2.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
Examples/Titanium.Web.Proxy.Examples.Wpf/Capture.PNG
0 → 100644
View file @
00eaed63
163 KB
README.md
View file @
00eaed63
...
...
@@ -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**

**GUI example application screenshot**

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:
...
...
Titanium.Web.Proxy.Standard.sln
deleted
100644 → 0
View file @
11632fe1
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
Titanium.Web.Proxy.sln
View file @
00eaed63
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 1
4
VisualStudioVersion = 1
4.0.25420.1
# Visual Studio 1
5
VisualStudioVersion = 1
5.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
Titanium.Web.Proxy/Helpers/Firefox.cs
View file @
00eaed63
using
System
;
#
if
NET45
using
System
;
using
System.IO
;
namespace
Titanium.Web.Proxy.Helpers
...
...
@@ -50,3 +51,4 @@ namespace Titanium.Web.Proxy.Helpers
}
}
}
#endif
Titanium.Web.Proxy/Helpers/NativeMethods.SystemProxy.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Helpers/NativeMethods.Tcp.cs
View file @
00eaed63
#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
Titanium.Web.Proxy/Helpers/ProxyInfo.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Helpers/RunTime.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Helpers/SystemProxy.cs
View file @
00eaed63
using
System
;
#
if
NET45
using
System
;
using
System.Linq
;
using
Microsoft.Win32
;
...
...
@@ -327,3 +328,4 @@ namespace Titanium.Web.Proxy.Helpers
}
}
}
#endif
Titanium.Web.Proxy/Helpers/WinHttp/NativeMethods.WinHttp.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpHandle.cs
View file @
00eaed63
#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
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs
View file @
00eaed63
#if NET45
using
System
;
using
System.Collections.Generic
;
using
System.Net
;
...
...
@@ -330,3 +331,4 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
}
}
}
#endif
Titanium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Network/Tcp/TcpRow.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Network/Tcp/TcpTable.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Network/WinAuth/Security/LittleEndian.cs
View file @
00eaed63
#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
Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs
View file @
00eaed63
#if NET45
//
// Nancy.Authentication.Ntlm.Protocol.Type3Message - Authentication
//
...
...
@@ -128,3 +129,4 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
}
}
}
#endif
Titanium.Web.Proxy/Network/WinAuth/Security/State.cs
View file @
00eaed63
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
Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs
View file @
00eaed63
// 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
Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs
View file @
00eaed63
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
Titanium.Web.Proxy/ProxyServer.cs
View file @
00eaed63
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
);
}
}
}
Titanium.Web.Proxy/RequestHandler.cs
View file @
00eaed63
...
...
@@ -132,7 +132,6 @@ namespace Titanium.Web.Proxy
try
{
sslStream
=
new
SslStream
(
clientStream
);
string
certName
=
HttpHelper
.
GetWildCardDomainName
(
httpRemoteUri
.
Host
);
...
...
Titanium.Web.Proxy/Titanium.Web.Proxy.Standard.csproj
deleted
100644 → 0
View file @
11632fe1
<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
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
00eaed63
<
?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
Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
View file @
00eaed63
...
...
@@ -13,13 +13,13 @@
<releaseNotes></releaseNotes>
<copyright>
Copyright
©
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>
Titanium.Web.Proxy/WinAuthHandler.cs
View file @
00eaed63
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment