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
6cb2ed4f
Commit
6cb2ed4f
authored
Jul 12, 2015
by
titanium007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add inline comments
parent
0381ef56
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
52 additions
and
57 deletions
+52
-57
NetFramework.cs
Titanium.Web.Proxy/Helpers/NetFramework.cs
+1
-0
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+6
-7
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+36
-33
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+9
-17
No files found.
Titanium.Web.Proxy/Helpers/NetFramework.cs
View file @
6cb2ed4f
...
...
@@ -8,6 +8,7 @@ namespace Titanium.Web.Proxy.Helpers
{
public
class
NetFrameworkHelper
{
//http://stackoverflow.com/questions/856885/httpwebrequest-to-url-with-dot-at-the-end
public
static
void
URLPeriodFix
()
{
MethodInfo
getSyntax
=
typeof
(
UriParser
).
GetMethod
(
"GetSyntax"
,
System
.
Reflection
.
BindingFlags
.
Static
|
System
.
Reflection
.
BindingFlags
.
NonPublic
);
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
6cb2ed4f
...
...
@@ -74,6 +74,7 @@ namespace Titanium.Web.Proxy
ServicePointManager
.
DnsRefreshTimeout
=
3
*
60
*
1000
;
//3 minutes
ServicePointManager
.
MaxServicePointIdleTime
=
3
*
60
*
1000
;
//HttpWebRequest certificate validation callback
ServicePointManager
.
ServerCertificateValidationCallback
=
delegate
(
object
s
,
X509Certificate
certificate
,
X509Chain
chain
,
SslPolicyErrors
sslPolicyErrors
)
{
if
(
sslPolicyErrors
==
SslPolicyErrors
.
None
)
return
true
;
...
...
@@ -81,6 +82,7 @@ namespace Titanium.Web.Proxy
return
false
;
};
//Fix a bug in .NET 4.0
NetFrameworkHelper
.
URLPeriodFix
();
}
...
...
@@ -107,6 +109,7 @@ namespace Titanium.Web.Proxy
RootCertificateName
=
RootCertificateName
==
null
?
"Titanium_Proxy_Test_Root"
:
RootCertificateName
;
bool
certTrusted
=
CertManager
.
CreateTrustedRootCertificate
();
//If certificate was trusted by the machine
if
(
certTrusted
)
{
SystemProxyHelper
.
EnableProxyHTTPS
(
"localhost"
,
ListeningPort
);
...
...
@@ -150,11 +153,7 @@ namespace Titanium.Web.Proxy
}
}
catch
(
ThreadInterruptedException
)
{
}
catch
(
SocketException
)
{
}
catch
(
SocketException
)
{
}
}
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
6cb2ed4f
...
...
@@ -26,16 +26,16 @@ namespace Titanium.Web.Proxy
{
string
connectionGroup
=
null
;
Stream
clientStream
=
null
;
CustomBinaryReader
clientStreamReader
=
null
;
StreamWriter
connectStreamWriter
=
null
;
string
tunnelHostName
=
null
;
int
tunnelPort
=
0
;
try
{
connectionGroup
=
Dns
.
GetHostEntry
(((
IPEndPoint
)
Client
.
Client
.
RemoteEndPoint
).
Address
).
HostName
;
//Separate HttpWebRequest connection group for each client
connectionGroup
=
((
IPEndPoint
)
Client
.
Client
.
RemoteEndPoint
).
Address
.
ToString
();
clientStream
=
Client
.
GetStream
();
...
...
@@ -55,7 +55,7 @@ namespace Titanium.Web.Proxy
{
throw
new
EndOfStreamException
();
}
//break up the line into three components
//break up the line into three components
(method, remote URL & Http Version)
String
[]
splitBuffer
=
httpCmd
.
Split
(
spaceSplit
,
3
);
String
method
=
splitBuffer
[
0
];
...
...
@@ -73,12 +73,13 @@ namespace Titanium.Web.Proxy
RequestVersion
=
"HTTP/1.0"
;
}
//Client wants to create a secure tcp tunnel (its a HTTPS request)
if
(
splitBuffer
[
0
].
ToUpper
()
==
"CONNECT"
)
{
//Browser wants to create a secure tunnel
//instead = we are going to perform a man in the middle "attack"
//the user's browser should warn them of the certification errors,
//
so
we need to install our root certficate in users machine as Certificate Authority.
//
to avoid that
we need to install our root certficate in users machine as Certificate Authority.
remoteUri
=
"https://"
+
splitBuffer
[
1
];
tunnelHostName
=
splitBuffer
[
1
].
Split
(
':'
)[
0
];
int
.
TryParse
(
splitBuffer
[
1
].
Split
(
':'
)[
1
],
out
tunnelPort
);
...
...
@@ -109,11 +110,9 @@ namespace Titanium.Web.Proxy
connectStreamWriter
.
Flush
();
//If port is not 443 its not a HTTP request, so just relay
if
(
tunnelPort
!=
443
)
{
TcpHelper
.
SendRaw
(
tunnelHostName
,
tunnelPort
,
clientStreamReader
.
BaseStream
);
if
(
clientStream
!=
null
)
...
...
@@ -121,22 +120,29 @@ namespace Titanium.Web.Proxy
return
;
}
//Create the fake certificate signed using our fake certificate authority
Monitor
.
Enter
(
certificateAccessLock
);
var
_certificate
=
ProxyServer
.
CertManager
.
CreateCertificate
(
tunnelHostName
);
Monitor
.
Exit
(
certificateAccessLock
);
SslStream
sslStream
=
null
;
//Pinned certificate clients cannot be proxied
//Example dropbox.com uses certificate pinning
//So just relay the request after identifying it by first failure
if
(!
pinnedCertificateClients
.
Contains
(
tunnelHostName
)
&&
isSecure
)
{
sslStream
=
new
SslStream
(
clientStream
,
true
);
try
{
//Successfully managed to authenticate the client using the fake certificate
sslStream
.
AuthenticateAsServer
(
_certificate
,
false
,
SslProtocols
.
Tls
|
SslProtocols
.
Ssl3
|
SslProtocols
.
Ssl2
,
false
);
}
catch
(
AuthenticationException
ex
)
{
//if authentication failed it could be because client uses pinned certificates
//So add the hostname to this list so that next time we can relay without touching it (tunnel the request)
if
(
pinnedCertificateClients
.
Contains
(
tunnelHostName
)
==
false
)
{
pinnedCertificateClients
.
Add
(
tunnelHostName
);
...
...
@@ -147,8 +153,7 @@ namespace Titanium.Web.Proxy
}
else
{
//Hostname was a previously failed request due to certificate pinning, just relay (tunnel the request)
TcpHelper
.
SendRaw
(
tunnelHostName
,
tunnelPort
,
clientStreamReader
.
BaseStream
);
if
(
clientStream
!=
null
)
...
...
@@ -175,6 +180,7 @@ namespace Titanium.Web.Proxy
securehost
=
remoteUri
;
}
//Now create the request
HandleHttpSessionRequest
(
Client
,
httpCmd
,
connectionGroup
,
clientStream
,
tunnelHostName
,
requestLines
,
clientStreamReader
,
securehost
);
...
...
@@ -203,10 +209,8 @@ namespace Titanium.Web.Proxy
finally
{
}
}
private
static
void
HandleHttpSessionRequest
(
TcpClient
Client
,
string
httpCmd
,
string
connectionGroup
,
Stream
clientStream
,
string
tunnelHostName
,
List
<
string
>
requestLines
,
CustomBinaryReader
clientStreamReader
,
string
securehost
)
{
...
...
@@ -221,6 +225,7 @@ namespace Titanium.Web.Proxy
args
.
securehost
=
securehost
;
try
{
//break up the line into three components (method, remote URL & Http Version)
var
splitBuffer
=
httpCmd
.
Split
(
spaceSplit
,
3
);
if
(
splitBuffer
.
Length
!=
3
)
...
...
@@ -264,10 +269,10 @@ namespace Titanium.Web.Proxy
var
rawHeader
=
requestLines
[
i
];
String
[]
header
=
rawHeader
.
ToLower
().
Trim
().
Split
(
colonSpaceSplit
,
2
,
StringSplitOptions
.
None
);
//if request was upgrade to web-socket protocol then relay the request without proxying
if
((
header
[
0
]
==
"upgrade"
)
&&
(
header
[
1
]
==
"websocket"
))
{
TcpHelper
.
SendRaw
(
httpCmd
,
tunnelHostName
,
ref
requestLines
,
args
.
IsSSLRequest
,
clientStreamReader
.
BaseStream
);
if
(
clientStream
!=
null
)
...
...
@@ -285,6 +290,7 @@ namespace Titanium.Web.Proxy
args
.
ProxyRequest
.
AllowAutoRedirect
=
false
;
args
.
ProxyRequest
.
AutomaticDecompression
=
DecompressionMethods
.
None
;
//If requested interception
if
(
BeforeRequest
!=
null
)
{
args
.
RequestHostname
=
args
.
ProxyRequest
.
RequestUri
.
Host
;
...
...
@@ -299,6 +305,7 @@ namespace Titanium.Web.Proxy
BeforeRequest
(
null
,
args
);
}
string
tmpLine
;
if
(
args
.
CancelRequest
)
{
...
...
@@ -320,7 +327,7 @@ namespace Titanium.Web.Proxy
args
.
ProxyRequest
.
ConnectionGroupName
=
connectionGroup
;
args
.
ProxyRequest
.
AllowWriteStreamBuffering
=
true
;
//If request was modified by user
if
(
args
.
RequestWasModified
)
{
ASCIIEncoding
encoding
=
new
ASCIIEncoding
();
...
...
@@ -333,14 +340,18 @@ namespace Titanium.Web.Proxy
}
else
{
//If its a post/put request, then read the client html body and send it to server
if
(
method
.
ToUpper
()
==
"POST"
||
method
.
ToUpper
()
==
"PUT"
)
{
args
.
ProxyRequest
.
BeginGetRequestStream
(
new
AsyncCallback
(
GetRequestStreamCallback
),
args
);
}
else
{
//otherwise wait for response asynchronously
args
.
ProxyRequest
.
BeginGetResponse
(
new
AsyncCallback
(
HandleHttpSessionResponse
),
args
);
//Now read the next request (if keep-Alive is enabled, otherwise exit thus thread)
//If client is pipeling the request, this will be immediately hit before response for previous request was made
if
(
args
.
ProxyRequest
.
KeepAlive
)
{
requestLines
=
new
List
<
string
>();
...
...
@@ -357,11 +368,6 @@ namespace Titanium.Web.Proxy
}
}
catch
(
IOException
)
{
...
...
@@ -378,10 +384,6 @@ namespace Titanium.Web.Proxy
finally
{
}
...
...
@@ -453,6 +455,8 @@ namespace Titanium.Web.Proxy
case
"user-agent"
:
WebRequest
.
UserAgent
=
header
[
1
];
break
;
//revisit this, transfer-encoding is not a request header according to spec
//But how to identify if client is sending chunked body for PUT/POST?
case
"transfer-encoding"
:
if
(
header
[
1
].
ToLower
()
==
"chunked"
)
WebRequest
.
SendChunked
=
true
;
...
...
@@ -468,7 +472,6 @@ namespace Titanium.Web.Proxy
if
(
header
.
Length
>=
2
)
WebRequest
.
Headers
.
Add
(
header
[
0
],
header
[
1
]);
break
;
}
...
...
@@ -519,20 +522,16 @@ namespace Titanium.Web.Proxy
postStream
.
Close
();
}
catch
(
IOException
ex
)
catch
(
IOException
)
{
args
.
ProxyRequest
.
KeepAlive
=
false
;
Debug
.
WriteLine
(
ex
.
Message
);
return
;
}
catch
(
WebException
ex
)
catch
(
WebException
)
{
args
.
ProxyRequest
.
KeepAlive
=
false
;
Debug
.
WriteLine
(
ex
.
Message
);
return
;
}
...
...
@@ -616,9 +615,11 @@ namespace Titanium.Web.Proxy
}
}
//Http request body sent, now wait asynchronously for response
args
.
ProxyRequest
.
BeginGetResponse
(
new
AsyncCallback
(
HandleHttpSessionResponse
),
args
);
//Now read the next request (if keep-Alive is enabled, otherwise exit thus thread)
//If client is pipeling the request, this will be immediately hit before response for previous request was made
if
(
args
.
ProxyRequest
.
KeepAlive
)
{
string
httpCmd
,
tmpLine
;
...
...
@@ -630,6 +631,8 @@ namespace Titanium.Web.Proxy
}
httpCmd
=
requestLines
.
Count
()
>
0
?
requestLines
[
0
]
:
null
;
TcpClient
Client
=
args
.
Client
;
//Http request body sent, now wait for next request
HandleHttpSessionRequest
(
Client
,
httpCmd
,
args
.
ProxyRequest
.
ConnectionGroupName
,
args
.
ClientStream
,
args
.
tunnelHostName
,
requestLines
,
args
.
ClientStreamReader
,
args
.
securehost
);
}
}
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
6cb2ed4f
...
...
@@ -17,6 +17,7 @@ namespace Titanium.Web.Proxy
{
partial
class
ProxyServer
{
//Called asynchronously when a request was successfully and we received the response
private
static
void
HandleHttpSessionResponse
(
IAsyncResult
AsynchronousResult
)
{
...
...
@@ -27,7 +28,8 @@ namespace Titanium.Web.Proxy
}
catch
(
WebException
webEx
)
{
args
.
ProxyRequest
.
KeepAlive
=
false
;
//Things line 404, 500 etc
//args.ProxyRequest.KeepAlive = false;
args
.
ServerResponse
=
webEx
.
Response
as
HttpWebResponse
;
}
...
...
@@ -109,35 +111,25 @@ namespace Titanium.Web.Proxy
}
catch
(
IOException
ex
)
catch
(
IOException
)
{
args
.
ProxyRequest
.
KeepAlive
=
false
;
Debug
.
WriteLine
(
ex
.
Message
);
}
catch
(
SocketException
ex
)
{
args
.
ProxyRequest
.
KeepAlive
=
false
;
Debug
.
WriteLine
(
ex
.
Message
);
}
catch
(
ArgumentException
ex
)
catch
(
ArgumentException
)
{
args
.
ProxyRequest
.
KeepAlive
=
false
;
Debug
.
WriteLine
(
ex
.
Message
);
}
catch
(
WebException
ex
)
catch
(
WebException
)
{
args
.
ProxyRequest
.
KeepAlive
=
false
;
Debug
.
WriteLine
(
ex
.
Message
);
}
finally
{
//Close this HttpWebRequest session
if
(
args
.
ProxyRequest
!=
null
)
args
.
ProxyRequest
.
Abort
();
if
(
args
.
ServerResponseStream
!=
null
)
args
.
ServerResponseStream
.
Close
();
...
...
@@ -146,6 +138,7 @@ namespace Titanium.Web.Proxy
}
//If this is false then terminate the tcp client
if
(
args
.
ProxyRequest
.
KeepAlive
==
false
)
{
if
(
responseWriter
!=
null
)
...
...
@@ -245,6 +238,7 @@ namespace Titanium.Web.Proxy
}
}
//Send chunked response
public
static
void
SendChunked
(
Stream
InStream
,
Stream
OutStream
)
{
...
...
@@ -274,8 +268,6 @@ namespace Titanium.Web.Proxy
var
ChunkTrail
=
Encoding
.
ASCII
.
GetBytes
(
Environment
.
NewLine
);
var
ChunkHead
=
Encoding
.
ASCII
.
GetBytes
(
Data
.
Length
.
ToString
(
"x2"
));
OutStream
.
Write
(
ChunkHead
,
0
,
ChunkHead
.
Length
);
OutStream
.
Write
(
ChunkTrail
,
0
,
ChunkTrail
.
Length
);
...
...
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