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
65b923fb
Commit
65b923fb
authored
Jun 04, 2016
by
justcoding121
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add mutual authentication capability
parent
c525dda7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
221 additions
and
63 deletions
+221
-63
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+16
-3
README.md
README.md
+21
-11
CertificateSelectionEventArgs.cs
...Web.Proxy/EventArguments/CertificateSelectionEventArgs.cs
+21
-0
CertificateValidationEventArgs.cs
...eb.Proxy/EventArguments/CertificateValidationEventArgs.cs
+0
-9
CertificateManager.cs
Titanium.Web.Proxy/Helpers/CertificateManager.cs
+1
-0
ConnectRequest.cs
Titanium.Web.Proxy/Models/ConnectRequest.cs
+11
-0
CustomSslStream.cs
Titanium.Web.Proxy/Network/CustomSslStream.cs
+3
-3
TcpConnectionManager.cs
Titanium.Web.Proxy/Network/TcpConnectionManager.cs
+16
-9
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+14
-1
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+116
-27
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+2
-0
No files found.
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
65b923fb
...
...
@@ -15,6 +15,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
ProxyServer
.
BeforeRequest
+=
OnRequest
;
ProxyServer
.
BeforeResponse
+=
OnResponse
;
ProxyServer
.
ServerCertificateValidationCallback
+=
OnCertificateValidation
;
ProxyServer
.
ClientCertificateSelectionCallback
+=
OnCertificateSelection
;
//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
...
...
@@ -129,13 +130,25 @@ namespace Titanium.Web.Proxy.Examples.Basic
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public
async
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
public
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
{
//set IsValid to true/false based on Certificate Errors
if
(
e
.
SslPolicyErrors
==
System
.
Net
.
Security
.
SslPolicyErrors
.
None
)
e
.
IsValid
=
true
;
else
await
e
.
Session
.
Ok
(
"Cannot validate server certificate! Not safe to proceed."
);
return
Task
.
FromResult
(
0
);
}
/// <summary>
/// Allows overriding default client certificate selection logic during mutual authentication
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public
Task
OnCertificateSelection
(
object
sender
,
CertificateSelectionEventArgs
e
)
{
//set e.clientCertificate to override
return
Task
.
FromResult
(
0
);
}
}
}
\ No newline at end of file
README.md
View file @
65b923fb
...
...
@@ -12,8 +12,11 @@ Features
========
*
Supports Http(s) and most features of HTTP 1.1
*
Supports relaying of WebSockets
*
Supports script injection
*
Support redirect/block/update requests
*
Supports updating response
*
Safely relays WebSocket requests over Http
*
Support mutual SSL authentication
*
Fully asynchronous proxy
Usage
=====
...
...
@@ -35,6 +38,8 @@ Setup HTTP proxy:
ProxyServer
.
BeforeRequest
+=
OnRequest
;
ProxyServer
.
BeforeResponse
+=
OnResponse
;
ProxyServer
.
ServerCertificateValidationCallback
+=
OnCertificateValidation
;
ProxyServer
.
ClientCertificateSelectionCallback
+=
OnCertificateSelection
;
//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
...
...
@@ -84,9 +89,7 @@ Setup HTTP proxy:
```
Sample request and response event handlers
```
csharp
//intecept & cancel, redirect or update requests
```
csharp
public
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
{
Console
.
WriteLine
(
e
.
WebSession
.
Request
.
Url
);
...
...
@@ -148,20 +151,27 @@ Sample request and response event handlers
}
}
/// Allows overriding default certificate validation logic
public
async
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
/// Allows overriding default certificate validation logic
public
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
{
//set IsValid to true/false based on Certificate Errors
if
(
e
.
SslPolicyErrors
==
System
.
Net
.
Security
.
SslPolicyErrors
.
None
)
e
.
IsValid
=
true
;
else
await
e
.
Session
.
Ok
(
"Cannot validate server certificate! Not safe to proceed."
);
return
Task
.
FromResult
(
0
);
}
/// Allows overriding default client certificate selection logic during mutual authentication
public
Task
OnCertificateSelection
(
object
sender
,
CertificateSelectionEventArgs
e
)
{
//set e.clientCertificate to override
return
Task
.
FromResult
(
0
);
}
```
Future roadmap
============
*
Support mutual authenticatio
n
*
Implement Kerberos/NTLM authentication over HTTP protocols for windows domai
n
*
Support Server Name Indication (SNI) for transparent endpoints
*
Support HTTP 2.0
Titanium.Web.Proxy/EventArguments/CertificateSelectionEventArgs.cs
0 → 100644
View file @
65b923fb
using
System
;
using
System.Security.Cryptography.X509Certificates
;
namespace
Titanium.Web.Proxy.EventArguments
{
public
class
CertificateSelectionEventArgs
:
EventArgs
,
IDisposable
{
public
object
sender
{
get
;
internal
set
;
}
public
string
targetHost
{
get
;
internal
set
;
}
public
X509CertificateCollection
localCertificates
{
get
;
internal
set
;
}
public
X509Certificate
remoteCertificate
{
get
;
internal
set
;
}
public
string
[]
acceptableIssuers
{
get
;
internal
set
;
}
public
X509Certificate
clientCertificate
{
get
;
set
;
}
public
void
Dispose
()
{
throw
new
NotImplementedException
();
}
}
}
Titanium.Web.Proxy/EventArguments/CertificateValidationEventArgs.cs
View file @
65b923fb
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Net.Security
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Text
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Http
;
namespace
Titanium.Web.Proxy.EventArguments
{
public
class
CertificateValidationEventArgs
:
EventArgs
,
IDisposable
{
public
string
HostName
=>
Session
.
WebSession
.
Request
.
Host
;
public
SessionEventArgs
Session
{
get
;
internal
set
;
}
public
X509Certificate
Certificate
{
get
;
internal
set
;
}
public
X509Chain
Chain
{
get
;
internal
set
;
}
public
SslPolicyErrors
SslPolicyErrors
{
get
;
internal
set
;
}
...
...
Titanium.Web.Proxy/Helpers/CertificateManager.cs
View file @
65b923fb
...
...
@@ -97,6 +97,7 @@ namespace Titanium.Web.Proxy.Helpers
cached
.
LastAccess
=
DateTime
.
Now
;
return
cached
.
Certificate
;
}
X509Certificate2
certificate
=
null
;
store
.
Open
(
OpenFlags
.
ReadWrite
);
string
certificateSubject
=
string
.
Format
(
"CN={0}, O={1}"
,
certificateName
,
Issuer
);
...
...
Titanium.Web.Proxy/Models/ConnectRequest.cs
0 → 100644
View file @
65b923fb
using
System
;
using
System.IO
;
namespace
Titanium.Web.Proxy.Models
{
internal
class
ConnectRequest
{
internal
Stream
Stream
{
get
;
set
;
}
internal
Uri
Uri
{
get
;
set
;
}
}
}
Titanium.Web.Proxy/Network/CustomSslStream.cs
View file @
65b923fb
...
...
@@ -17,10 +17,10 @@ namespace Titanium.Web.Proxy.Network
/// <summary>
/// Holds the current session
/// </summary>
internal
SessionEventArgs
Session
{
get
;
set
;
}
internal
object
Param
{
get
;
set
;
}
internal
CustomSslStream
(
Stream
innerStream
,
bool
leaveInnerStreamOpen
,
RemoteCertificateValidationCallback
userCertificateValidationCallback
)
:
base
(
innerStream
,
leaveInnerStreamOpen
,
userCertificateValidationCallback
)
internal
CustomSslStream
(
Stream
innerStream
,
bool
leaveInnerStreamOpen
,
RemoteCertificateValidationCallback
userCertificateValidationCallback
,
LocalCertificateSelectionCallback
clientCertificateSelectionCallback
)
:
base
(
innerStream
,
leaveInnerStreamOpen
,
userCertificateValidationCallback
,
clientCertificateSelectionCallback
)
{
}
...
...
Titanium.Web.Proxy/Network/TcpConnectionManager.cs
View file @
65b923fb
...
...
@@ -12,6 +12,7 @@ using Titanium.Web.Proxy.Extensions;
using
Titanium.Web.Proxy.Shared
;
using
System.Security.Cryptography.X509Certificates
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy.Network
{
...
...
@@ -38,7 +39,12 @@ namespace Titanium.Web.Proxy.Network
{
static
Dictionary
<
string
,
List
<
TcpConnection
>>
connectionCache
=
new
Dictionary
<
string
,
List
<
TcpConnection
>>();
static
SemaphoreSlim
connectionAccessLock
=
new
SemaphoreSlim
(
1
);
internal
static
async
Task
<
TcpConnection
>
GetClient
(
SessionEventArgs
sessionArgs
,
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
internal
static
async
Task
<
TcpConnection
>
GetClient
(
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
{
return
await
GetClient
(
null
,
hostname
,
port
,
isHttps
,
version
);
}
internal
static
async
Task
<
TcpConnection
>
GetClient
(
ConnectRequest
connectRequest
,
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
{
List
<
TcpConnection
>
cachedConnections
=
null
;
TcpConnection
cached
=
null
;
...
...
@@ -72,14 +78,14 @@ namespace Titanium.Web.Proxy.Network
}
if
(
cached
==
null
)
cached
=
await
CreateClient
(
sessionArgs
,
hostname
,
port
,
isHttps
,
version
).
ConfigureAwait
(
false
);
cached
=
await
CreateClient
(
connectRequest
,
hostname
,
port
,
isHttps
,
version
).
ConfigureAwait
(
false
);
//just create one more preemptively
if
(
cachedConnections
==
null
||
cachedConnections
.
Count
()
<
2
)
{
var
task
=
CreateClient
(
sessionArgs
,
hostname
,
port
,
isHttps
,
version
)
.
ContinueWith
(
async
(
x
)
=>
{
if
(
x
.
Status
==
TaskStatus
.
RanToCompletion
)
await
ReleaseClient
(
x
.
Result
);
});
var
task
=
CreateClient
(
connectRequest
,
hostname
,
port
,
isHttps
,
version
)
.
ContinueWith
(
async
(
x
)
=>
{
if
(
x
.
Status
==
TaskStatus
.
RanToCompletion
)
await
ReleaseClient
(
x
.
Result
);
});
}
return
cached
;
...
...
@@ -90,7 +96,7 @@ namespace Titanium.Web.Proxy.Network
return
string
.
Format
(
"{0}:{1}:{2}:{3}:{4}"
,
hostname
.
ToLower
(),
port
,
isHttps
,
version
.
Major
,
version
.
Minor
);
}
private
static
async
Task
<
TcpConnection
>
CreateClient
(
SessionEventArgs
sessionArgs
,
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
private
static
async
Task
<
TcpConnection
>
CreateClient
(
ConnectRequest
connectRequest
,
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
{
TcpClient
client
;
Stream
stream
;
...
...
@@ -106,8 +112,8 @@ namespace Titanium.Web.Proxy.Network
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
Constants
.
BUFFER_SIZE
,
true
))
{
await
writer
.
WriteLineAsync
(
string
.
Format
(
"CONNECT {0}:{1} {2}"
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Host
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Port
,
sessionArgs
.
WebSession
.
Request
.
HttpV
ersion
)).
ConfigureAwait
(
false
);
await
writer
.
WriteLineAsync
(
string
.
Format
(
"Host: {0}:{1}"
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Host
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
P
ort
)).
ConfigureAwait
(
false
);
await
writer
.
WriteLineAsync
(
string
.
Format
(
"CONNECT {0}:{1} {2}"
,
hostname
,
port
,
v
ersion
)).
ConfigureAwait
(
false
);
await
writer
.
WriteLineAsync
(
string
.
Format
(
"Host: {0}:{1}"
,
hostname
,
p
ort
)).
ConfigureAwait
(
false
);
await
writer
.
WriteLineAsync
(
"Connection: Keep-Alive"
).
ConfigureAwait
(
false
);
await
writer
.
WriteLineAsync
().
ConfigureAwait
(
false
);
await
writer
.
FlushAsync
().
ConfigureAwait
(
false
);
...
...
@@ -132,8 +138,9 @@ namespace Titanium.Web.Proxy.Network
try
{
sslStream
=
new
CustomSslStream
(
stream
,
true
,
new
RemoteCertificateValidationCallback
(
ProxyServer
.
ValidateServerCertificate
));
sslStream
.
Session
=
sessionArgs
;
sslStream
=
new
CustomSslStream
(
stream
,
true
,
new
RemoteCertificateValidationCallback
(
ProxyServer
.
ValidateServerCertificate
),
new
LocalCertificateSelectionCallback
(
ProxyServer
.
SelectClientCertificate
));
sslStream
.
Param
=
connectRequest
;
await
sslStream
.
AuthenticateAsClientAsync
(
hostname
,
null
,
Constants
.
SupportedProtocols
,
false
).
ConfigureAwait
(
false
);
stream
=
(
Stream
)
sslStream
;
}
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
65b923fb
...
...
@@ -45,7 +45,16 @@ namespace Titanium.Web.Proxy
/// </summary>
public
static
int
CertificateCacheTimeOutMinutes
{
get
;
set
;
}
/// <summary>
/// Intercept request to server
/// </summary>
public
static
event
Func
<
object
,
SessionEventArgs
,
Task
>
BeforeRequest
;
/// <summary>
/// Intercept response from server
/// </summary>
public
static
event
Func
<
object
,
SessionEventArgs
,
Task
>
BeforeResponse
;
/// <summary>
...
...
@@ -62,7 +71,11 @@ namespace Titanium.Web.Proxy
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
/// </summary>
public
static
event
Func
<
object
,
CertificateValidationEventArgs
,
Task
>
ServerCertificateValidationCallback
;
/// <summary>
/// Callback tooverride client certificate during SSL mutual authentication
/// </summary>
public
static
event
Func
<
object
,
CertificateSelectionEventArgs
,
Task
>
ClientCertificateSelectionCallback
;
public
static
List
<
ProxyEndPoint
>
ProxyEndPoints
{
get
;
set
;
}
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
65b923fb
This diff is collapsed.
Click to expand it.
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
65b923fb
...
...
@@ -60,7 +60,9 @@
<Compile
Include=
"Decompression\GZipDecompression.cs"
/>
<Compile
Include=
"Decompression\IDecompression.cs"
/>
<Compile
Include=
"Decompression\ZlibDecompression.cs"
/>
<Compile
Include=
"EventArguments\CertificateSelectionEventArgs.cs"
/>
<Compile
Include=
"EventArguments\CertificateValidationEventArgs.cs"
/>
<Compile
Include=
"Models\ConnectRequest.cs"
/>
<Compile
Include=
"Network\ProxyClient.cs"
/>
<Compile
Include=
"Exceptions\BodyNotFoundException.cs"
/>
<Compile
Include=
"Extensions\HttpWebResponseExtensions.cs"
/>
...
...
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