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
915e5ca7
Commit
915e5ca7
authored
Apr 13, 2018
by
justcoding121
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor => separate handle clients
parent
518aac9f
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
360 additions
and
319 deletions
+360
-319
ExplicitClientHandler.cs
Titanium.Web.Proxy/ExplicitClientHandler.cs
+228
-0
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+0
-319
TransparentClientHandler.cs
Titanium.Web.Proxy/TransparentClientHandler.cs
+132
-0
No files found.
Titanium.Web.Proxy/ExplicitClientHandler.cs
0 → 100644
View file @
915e5ca7
using
System
;
using
System.IO
;
using
System.Net
;
using
System.Net.Security
;
using
System.Net.Sockets
;
using
System.Threading.Tasks
;
using
StreamExtended
;
using
StreamExtended.Helpers
;
using
StreamExtended.Network
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Exceptions
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy
{
partial
class
ProxyServer
{
/// <summary>
/// This is called when client is aware of proxy
/// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
/// </summary>
/// <param name="endPoint"></param>
/// <param name="tcpClient"></param>
/// <returns></returns>
private
async
Task
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
var
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
var
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
try
{
string
connectHostname
=
null
;
ConnectRequest
connectRequest
=
null
;
//Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
if
(
await
HttpHelper
.
IsConnectMethod
(
clientStream
)
==
1
)
{
//read the first line HTTP command
string
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
if
(
string
.
IsNullOrEmpty
(
httpCmd
))
{
return
;
}
Request
.
ParseRequestLine
(
httpCmd
,
out
string
_
,
out
string
httpUrl
,
out
var
version
);
var
httpRemoteUri
=
new
Uri
(
"http://"
+
httpUrl
);
connectHostname
=
httpRemoteUri
.
Host
;
connectRequest
=
new
ConnectRequest
{
RequestUri
=
httpRemoteUri
,
OriginalUrl
=
httpUrl
,
HttpVersion
=
version
,
};
await
HeaderParser
.
ReadHeaders
(
clientStreamReader
,
connectRequest
.
Headers
);
var
connectArgs
=
new
TunnelConnectSessionEventArgs
(
BufferSize
,
endPoint
,
connectRequest
,
ExceptionFunc
);
connectArgs
.
ProxyClient
.
TcpClient
=
tcpClient
;
connectArgs
.
ProxyClient
.
ClientStream
=
clientStream
;
await
endPoint
.
InvokeBeforeTunnelConnectRequest
(
this
,
connectArgs
,
ExceptionFunc
);
//filter out excluded host names
bool
decryptSsl
=
endPoint
.
DecryptSsl
&&
connectArgs
.
DecryptSsl
;
if
(
connectArgs
.
DenyConnect
)
{
if
(
connectArgs
.
WebSession
.
Response
.
StatusCode
==
0
)
{
connectArgs
.
WebSession
.
Response
=
new
Response
{
HttpVersion
=
HttpHeader
.
Version11
,
StatusCode
=
(
int
)
HttpStatusCode
.
Forbidden
,
StatusDescription
=
"Forbidden"
,
};
}
//send the response
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
);
return
;
}
if
(
await
CheckAuthorization
(
connectArgs
)
==
false
)
{
await
endPoint
.
InvokeBeforeTunnectConnectResponse
(
this
,
connectArgs
,
ExceptionFunc
);
//send the response
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
);
return
;
}
//write back successfull CONNECT response
var
response
=
ConnectResponse
.
CreateSuccessfullConnectResponse
(
version
);
// Set ContentLength explicitly to properly handle HTTP 1.0
response
.
ContentLength
=
0
;
response
.
Headers
.
FixProxyHeaders
();
connectArgs
.
WebSession
.
Response
=
response
;
await
clientStreamWriter
.
WriteResponseAsync
(
response
);
var
clientHelloInfo
=
await
SslTools
.
PeekClientHello
(
clientStream
);
bool
isClientHello
=
clientHelloInfo
!=
null
;
if
(
isClientHello
)
{
connectRequest
.
ClientHelloInfo
=
clientHelloInfo
;
}
await
endPoint
.
InvokeBeforeTunnectConnectResponse
(
this
,
connectArgs
,
ExceptionFunc
,
isClientHello
);
if
(
decryptSsl
&&
isClientHello
)
{
connectRequest
.
RequestUri
=
new
Uri
(
"https://"
+
httpUrl
);
SslStream
sslStream
=
null
;
try
{
sslStream
=
new
SslStream
(
clientStream
);
string
certName
=
HttpHelper
.
GetWildCardDomainName
(
connectHostname
);
var
certificate
=
endPoint
.
GenericCertificate
??
await
CertificateManager
.
CreateCertificateAsync
(
certName
);
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SupportedSslProtocols
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
.
Dispose
();
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
}
catch
(
Exception
e
)
{
ExceptionFunc
(
new
Exception
(
$"Could'nt authenticate client '
{
connectHostname
}
' with fake certificate."
,
e
));
sslStream
?.
Dispose
();
return
;
}
if
(
await
HttpHelper
.
IsConnectMethod
(
clientStream
)
==
-
1
)
{
// It can be for example some Google (Cloude Messaging for Chrome) magic
decryptSsl
=
false
;
}
}
if
(
connectArgs
.
TerminateSession
)
{
throw
new
Exception
(
"Session was terminated by user."
);
}
//Hostname is excluded or it is not an HTTPS connect
if
(!
decryptSsl
||
!
isClientHello
)
{
//create new connection
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
))
{
if
(
isClientHello
)
{
int
available
=
clientStream
.
Available
;
if
(
available
>
0
)
{
//send the buffered data
var
data
=
BufferPool
.
GetBuffer
(
BufferSize
);
try
{
// clientStream.Available sbould be at most BufferSize because it is using the same buffer size
await
clientStream
.
ReadAsync
(
data
,
0
,
available
);
await
connection
.
StreamWriter
.
WriteAsync
(
data
,
0
,
available
,
true
);
}
finally
{
BufferPool
.
ReturnBuffer
(
data
);
}
}
var
serverHelloInfo
=
await
SslTools
.
PeekServerHello
(
connection
.
Stream
);
((
ConnectResponse
)
connectArgs
.
WebSession
.
Response
).
ServerHelloInfo
=
serverHelloInfo
;
}
await
TcpHelper
.
SendRaw
(
clientStream
,
connection
.
Stream
,
BufferSize
,
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataSent
(
buffer
,
offset
,
count
);
},
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataReceived
(
buffer
,
offset
,
count
);
},
ExceptionFunc
);
}
return
;
}
}
//Now create the request
await
HandleHttpSessionRequest
(
tcpClient
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connectHostname
,
endPoint
,
connectRequest
);
}
catch
(
ProxyHttpException
e
)
{
ExceptionFunc
(
e
);
}
catch
(
IOException
e
)
{
ExceptionFunc
(
new
Exception
(
"Connection was aborted"
,
e
));
}
catch
(
SocketException
e
)
{
ExceptionFunc
(
new
Exception
(
"Could not connect"
,
e
));
}
catch
(
Exception
e
)
{
ExceptionFunc
(
new
Exception
(
"Error occured in whilst handling the client"
,
e
));
}
finally
{
clientStreamReader
.
Dispose
();
clientStream
.
Dispose
();
}
}
}
}
Titanium.Web.Proxy/RequestHandler.cs
View file @
915e5ca7
...
@@ -28,325 +28,6 @@ namespace Titanium.Web.Proxy
...
@@ -28,325 +28,6 @@ namespace Titanium.Web.Proxy
private
bool
isWindowsAuthenticationEnabledAndSupported
=>
EnableWinAuth
&&
RunTime
.
IsWindows
&&
!
RunTime
.
IsRunningOnMono
;
private
bool
isWindowsAuthenticationEnabledAndSupported
=>
EnableWinAuth
&&
RunTime
.
IsWindows
&&
!
RunTime
.
IsRunningOnMono
;
/// <summary>
/// This is called when client is aware of proxy
/// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
/// </summary>
/// <param name="endPoint"></param>
/// <param name="tcpClient"></param>
/// <returns></returns>
private
async
Task
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
var
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
var
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
try
{
string
connectHostname
=
null
;
ConnectRequest
connectRequest
=
null
;
//Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
if
(
await
HttpHelper
.
IsConnectMethod
(
clientStream
)
==
1
)
{
//read the first line HTTP command
string
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
if
(
string
.
IsNullOrEmpty
(
httpCmd
))
{
return
;
}
Request
.
ParseRequestLine
(
httpCmd
,
out
string
_
,
out
string
httpUrl
,
out
var
version
);
var
httpRemoteUri
=
new
Uri
(
"http://"
+
httpUrl
);
connectHostname
=
httpRemoteUri
.
Host
;
connectRequest
=
new
ConnectRequest
{
RequestUri
=
httpRemoteUri
,
OriginalUrl
=
httpUrl
,
HttpVersion
=
version
,
};
await
HeaderParser
.
ReadHeaders
(
clientStreamReader
,
connectRequest
.
Headers
);
var
connectArgs
=
new
TunnelConnectSessionEventArgs
(
BufferSize
,
endPoint
,
connectRequest
,
ExceptionFunc
);
connectArgs
.
ProxyClient
.
TcpClient
=
tcpClient
;
connectArgs
.
ProxyClient
.
ClientStream
=
clientStream
;
await
endPoint
.
InvokeBeforeTunnelConnectRequest
(
this
,
connectArgs
,
ExceptionFunc
);
//filter out excluded host names
bool
decryptSsl
=
endPoint
.
DecryptSsl
&&
connectArgs
.
DecryptSsl
;
if
(
connectArgs
.
DenyConnect
)
{
if
(
connectArgs
.
WebSession
.
Response
.
StatusCode
==
0
)
{
connectArgs
.
WebSession
.
Response
=
new
Response
{
HttpVersion
=
HttpHeader
.
Version11
,
StatusCode
=
(
int
)
HttpStatusCode
.
Forbidden
,
StatusDescription
=
"Forbidden"
,
};
}
//send the response
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
);
return
;
}
if
(
await
CheckAuthorization
(
connectArgs
)
==
false
)
{
await
endPoint
.
InvokeBeforeTunnectConnectResponse
(
this
,
connectArgs
,
ExceptionFunc
);
//send the response
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
);
return
;
}
//write back successfull CONNECT response
var
response
=
ConnectResponse
.
CreateSuccessfullConnectResponse
(
version
);
// Set ContentLength explicitly to properly handle HTTP 1.0
response
.
ContentLength
=
0
;
response
.
Headers
.
FixProxyHeaders
();
connectArgs
.
WebSession
.
Response
=
response
;
await
clientStreamWriter
.
WriteResponseAsync
(
response
);
var
clientHelloInfo
=
await
SslTools
.
PeekClientHello
(
clientStream
);
bool
isClientHello
=
clientHelloInfo
!=
null
;
if
(
isClientHello
)
{
connectRequest
.
ClientHelloInfo
=
clientHelloInfo
;
}
await
endPoint
.
InvokeBeforeTunnectConnectResponse
(
this
,
connectArgs
,
ExceptionFunc
,
isClientHello
);
if
(
decryptSsl
&&
isClientHello
)
{
connectRequest
.
RequestUri
=
new
Uri
(
"https://"
+
httpUrl
);
SslStream
sslStream
=
null
;
try
{
sslStream
=
new
SslStream
(
clientStream
);
string
certName
=
HttpHelper
.
GetWildCardDomainName
(
connectHostname
);
var
certificate
=
endPoint
.
GenericCertificate
??
await
CertificateManager
.
CreateCertificateAsync
(
certName
);
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SupportedSslProtocols
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
.
Dispose
();
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
}
catch
(
Exception
e
)
{
ExceptionFunc
(
new
Exception
(
$"Could'nt authenticate client '
{
connectHostname
}
' with fake certificate."
,
e
));
sslStream
?.
Dispose
();
return
;
}
if
(
await
HttpHelper
.
IsConnectMethod
(
clientStream
)
==
-
1
)
{
// It can be for example some Google (Cloude Messaging for Chrome) magic
decryptSsl
=
false
;
}
}
if
(
connectArgs
.
TerminateSession
)
{
throw
new
Exception
(
"Session was terminated by user."
);
}
//Hostname is excluded or it is not an HTTPS connect
if
(!
decryptSsl
||
!
isClientHello
)
{
//create new connection
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
))
{
if
(
isClientHello
)
{
int
available
=
clientStream
.
Available
;
if
(
available
>
0
)
{
//send the buffered data
var
data
=
BufferPool
.
GetBuffer
(
BufferSize
);
try
{
// clientStream.Available sbould be at most BufferSize because it is using the same buffer size
await
clientStream
.
ReadAsync
(
data
,
0
,
available
);
await
connection
.
StreamWriter
.
WriteAsync
(
data
,
0
,
available
,
true
);
}
finally
{
BufferPool
.
ReturnBuffer
(
data
);
}
}
var
serverHelloInfo
=
await
SslTools
.
PeekServerHello
(
connection
.
Stream
);
((
ConnectResponse
)
connectArgs
.
WebSession
.
Response
).
ServerHelloInfo
=
serverHelloInfo
;
}
await
TcpHelper
.
SendRaw
(
clientStream
,
connection
.
Stream
,
BufferSize
,
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataSent
(
buffer
,
offset
,
count
);
},
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataReceived
(
buffer
,
offset
,
count
);
},
ExceptionFunc
);
}
return
;
}
}
//Now create the request
await
HandleHttpSessionRequest
(
tcpClient
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connectHostname
,
endPoint
,
connectRequest
);
}
catch
(
ProxyHttpException
e
)
{
ExceptionFunc
(
e
);
}
catch
(
IOException
e
)
{
ExceptionFunc
(
new
Exception
(
"Connection was aborted"
,
e
));
}
catch
(
SocketException
e
)
{
ExceptionFunc
(
new
Exception
(
"Could not connect"
,
e
));
}
catch
(
Exception
e
)
{
ExceptionFunc
(
new
Exception
(
"Error occured in whilst handling the client"
,
e
));
}
finally
{
clientStreamReader
.
Dispose
();
clientStream
.
Dispose
();
}
}
/// <summary>
/// This is called when this proxy acts as a reverse proxy (like a real http server)
/// So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
/// </summary>
/// <param name="endPoint"></param>
/// <param name="tcpClient"></param>
/// <returns></returns>
private
async
Task
HandleClient
(
TransparentProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
var
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
var
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
try
{
var
clientHelloInfo
=
await
SslTools
.
PeekClientHello
(
clientStream
);
var
isHttps
=
clientHelloInfo
!=
null
;
string
httpsHostName
=
null
;
if
(
isHttps
)
{
httpsHostName
=
clientHelloInfo
.
GetServerName
()
??
endPoint
.
GenericCertificateName
;
var
args
=
new
BeforeSslAuthenticateEventArgs
();
args
.
SniHostName
=
httpsHostName
;
await
endPoint
.
InvokeBeforeSslAuthenticate
(
this
,
args
,
ExceptionFunc
);
if
(
args
.
TerminateSession
)
{
throw
new
Exception
(
"Session was terminated by user."
);
}
if
(
endPoint
.
DecryptSsl
&&
args
.
DecryptSsl
)
{
SslStream
sslStream
=
null
;
try
{
sslStream
=
new
SslStream
(
clientStream
);
string
certName
=
HttpHelper
.
GetWildCardDomainName
(
httpsHostName
);
var
certificate
=
await
CertificateManager
.
CreateCertificateAsync
(
certName
);
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SslProtocols
.
Tls
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
.
Dispose
();
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
}
catch
(
Exception
e
)
{
ExceptionFunc
(
new
Exception
(
$"Could'nt authenticate client '
{
httpsHostName
}
' with fake certificate."
,
e
));
sslStream
?.
Dispose
();
return
;
}
}
else
{
//create new connection
var
connection
=
new
TcpClient
(
UpStreamEndPoint
);
await
connection
.
ConnectAsync
(
httpsHostName
,
endPoint
.
Port
);
connection
.
ReceiveTimeout
=
ConnectionTimeOutSeconds
*
1000
;
connection
.
SendTimeout
=
ConnectionTimeOutSeconds
*
1000
;
using
(
connection
)
{
var
serverStream
=
connection
.
GetStream
();
int
available
=
clientStream
.
Available
;
if
(
available
>
0
)
{
//send the buffered data
var
data
=
BufferPool
.
GetBuffer
(
BufferSize
);
try
{
// clientStream.Available sbould be at most BufferSize because it is using the same buffer size
await
clientStream
.
ReadAsync
(
data
,
0
,
available
);
await
serverStream
.
WriteAsync
(
data
,
0
,
available
);
await
serverStream
.
FlushAsync
();
}
finally
{
BufferPool
.
ReturnBuffer
(
data
);
}
}
//var serverHelloInfo = await SslTools.PeekServerHello(serverStream);
await
TcpHelper
.
SendRaw
(
clientStream
,
serverStream
,
BufferSize
,
null
,
null
,
ExceptionFunc
);
}
}
}
//HTTPS server created - we can now decrypt the client's traffic
//Now create the request
await
HandleHttpSessionRequest
(
tcpClient
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
isHttps
?
httpsHostName
:
null
,
endPoint
,
null
,
true
);
}
finally
{
clientStreamReader
.
Dispose
();
clientStream
.
Dispose
();
}
}
/// <summary>
/// <summary>
/// This is the core request handler method for a particular connection from client
/// This is the core request handler method for a particular connection from client
...
...
Titanium.Web.Proxy/TransparentClientHandler.cs
0 → 100644
View file @
915e5ca7
using
System
;
using
System.Net.Security
;
using
System.Net.Sockets
;
using
System.Security.Authentication
;
using
System.Threading.Tasks
;
using
StreamExtended
;
using
StreamExtended.Helpers
;
using
StreamExtended.Network
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy
{
partial
class
ProxyServer
{
/// <summary>
/// This is called when this proxy acts as a reverse proxy (like a real http server)
/// So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
/// </summary>
/// <param name="endPoint"></param>
/// <param name="tcpClient"></param>
/// <returns></returns>
private
async
Task
HandleClient
(
TransparentProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
var
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
var
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
try
{
var
clientHelloInfo
=
await
SslTools
.
PeekClientHello
(
clientStream
);
var
isHttps
=
clientHelloInfo
!=
null
;
string
httpsHostName
=
null
;
if
(
isHttps
)
{
httpsHostName
=
clientHelloInfo
.
GetServerName
()
??
endPoint
.
GenericCertificateName
;
var
args
=
new
BeforeSslAuthenticateEventArgs
();
args
.
SniHostName
=
httpsHostName
;
await
endPoint
.
InvokeBeforeSslAuthenticate
(
this
,
args
,
ExceptionFunc
);
if
(
args
.
TerminateSession
)
{
throw
new
Exception
(
"Session was terminated by user."
);
}
if
(
endPoint
.
DecryptSsl
&&
args
.
DecryptSsl
)
{
SslStream
sslStream
=
null
;
try
{
sslStream
=
new
SslStream
(
clientStream
);
string
certName
=
HttpHelper
.
GetWildCardDomainName
(
httpsHostName
);
var
certificate
=
await
CertificateManager
.
CreateCertificateAsync
(
certName
);
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SslProtocols
.
Tls
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
.
Dispose
();
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
}
catch
(
Exception
e
)
{
ExceptionFunc
(
new
Exception
(
$"Could'nt authenticate client '
{
httpsHostName
}
' with fake certificate."
,
e
));
sslStream
?.
Dispose
();
return
;
}
}
else
{
//create new connection
var
connection
=
new
TcpClient
(
UpStreamEndPoint
);
await
connection
.
ConnectAsync
(
httpsHostName
,
endPoint
.
Port
);
connection
.
ReceiveTimeout
=
ConnectionTimeOutSeconds
*
1000
;
connection
.
SendTimeout
=
ConnectionTimeOutSeconds
*
1000
;
using
(
connection
)
{
var
serverStream
=
connection
.
GetStream
();
int
available
=
clientStream
.
Available
;
if
(
available
>
0
)
{
//send the buffered data
var
data
=
BufferPool
.
GetBuffer
(
BufferSize
);
try
{
// clientStream.Available sbould be at most BufferSize because it is using the same buffer size
await
clientStream
.
ReadAsync
(
data
,
0
,
available
);
await
serverStream
.
WriteAsync
(
data
,
0
,
available
);
await
serverStream
.
FlushAsync
();
}
finally
{
BufferPool
.
ReturnBuffer
(
data
);
}
}
//var serverHelloInfo = await SslTools.PeekServerHello(serverStream);
await
TcpHelper
.
SendRaw
(
clientStream
,
serverStream
,
BufferSize
,
null
,
null
,
ExceptionFunc
);
}
}
}
//HTTPS server created - we can now decrypt the client's traffic
//Now create the request
await
HandleHttpSessionRequest
(
tcpClient
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
isHttps
?
httpsHostName
:
null
,
endPoint
,
null
,
true
);
}
finally
{
clientStreamReader
.
Dispose
();
clientStream
.
Dispose
();
}
}
}
}
\ No newline at end of file
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