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
e82ad51e
Commit
e82ad51e
authored
May 14, 2017
by
Jehonathan Thomas
Committed by
GitHub
May 14, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #219 from justcoding121/develop
Merge with develop
parents
e928c25a
8e02c62c
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
642 additions
and
132 deletions
+642
-132
Titanium.Web.Proxy.sln.DotSettings
Titanium.Web.Proxy.sln.DotSettings
+5
-0
HttpWebRequestExtensions.cs
Titanium.Web.Proxy/Extensions/HttpWebRequestExtensions.cs
+3
-2
HttpWebResponseExtensions.cs
Titanium.Web.Proxy/Extensions/HttpWebResponseExtensions.cs
+3
-2
StringExtensions.cs
Titanium.Web.Proxy/Extensions/StringExtensions.cs
+17
-0
CustomBinaryReader.cs
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
+94
-41
CustomBufferedStream.cs
Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs
+437
-0
SystemProxy.cs
Titanium.Web.Proxy/Helpers/SystemProxy.cs
+1
-1
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+10
-9
Request.cs
Titanium.Web.Proxy/Http/Request.cs
+2
-2
Response.cs
Titanium.Web.Proxy/Http/Response.cs
+2
-2
EndPoint.cs
Titanium.Web.Proxy/Models/EndPoint.cs
+10
-8
HttpHeader.cs
Titanium.Web.Proxy/Models/HttpHeader.cs
+10
-0
TcpConnection.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs
+3
-6
TcpConnectionFactory.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+12
-12
ProxyAuthorizationHandler.cs
Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
+2
-2
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+0
-7
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+17
-21
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+11
-17
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+3
-0
No files found.
Titanium.Web.Proxy.sln.DotSettings
0 → 100644
View file @
e82ad51e
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String></wpf:ResourceDictionary>
\ No newline at end of file
Titanium.Web.Proxy/Extensions/HttpWebRequestExtensions.cs
View file @
e82ad51e
using
System.Text
;
using
System
;
using
System.Text
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Shared
;
...
...
@@ -29,7 +30,7 @@ namespace Titanium.Web.Proxy.Extensions
foreach
(
var
contentType
in
contentTypes
)
{
var
encodingSplit
=
contentType
.
Split
(
'='
);
if
(
encodingSplit
.
Length
==
2
&&
encodingSplit
[
0
].
T
oLower
().
Trim
()
==
"charset"
)
if
(
encodingSplit
.
Length
==
2
&&
encodingSplit
[
0
].
T
rim
().
Equals
(
"charset"
,
StringComparison
.
CurrentCultureIgnoreCase
)
)
{
return
Encoding
.
GetEncoding
(
encodingSplit
[
1
]);
}
...
...
Titanium.Web.Proxy/Extensions/HttpWebResponseExtensions.cs
View file @
e82ad51e
using
System.Text
;
using
System
;
using
System.Text
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Shared
;
...
...
@@ -26,7 +27,7 @@ namespace Titanium.Web.Proxy.Extensions
foreach
(
var
contentType
in
contentTypes
)
{
var
encodingSplit
=
contentType
.
Split
(
'='
);
if
(
encodingSplit
.
Length
==
2
&&
encodingSplit
[
0
].
T
oLower
().
Trim
()
==
"charset"
)
if
(
encodingSplit
.
Length
==
2
&&
encodingSplit
[
0
].
T
rim
().
Equals
(
"charset"
,
StringComparison
.
CurrentCultureIgnoreCase
)
)
{
return
Encoding
.
GetEncoding
(
encodingSplit
[
1
]);
}
...
...
Titanium.Web.Proxy/Extensions/StringExtensions.cs
0 → 100644
View file @
e82ad51e
using
System
;
using
System.Collections.Generic
;
using
System.Globalization
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Extensions
{
internal
static
class
StringExtensions
{
internal
static
bool
ContainsIgnoreCase
(
this
string
str
,
string
value
)
{
return
CultureInfo
.
CurrentCulture
.
CompareInfo
.
IndexOf
(
str
,
value
,
CompareOptions
.
IgnoreCase
)
>=
0
;
}
}
}
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
View file @
e82ad51e
...
...
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using
System.IO
;
using
System.Text
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Extensions
;
namespace
Titanium.Web.Proxy.Helpers
{
...
...
@@ -15,12 +14,30 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
internal
class
CustomBinaryReader
:
IDisposable
{
private
readonly
Stream
stream
;
private
readonly
CustomBufferedStream
stream
;
private
readonly
int
bufferSize
;
private
readonly
Encoding
encoding
;
internal
CustomBinaryReader
(
Stream
stream
)
[
ThreadStatic
]
private
static
byte
[]
staticBuffer
;
private
byte
[]
buffer
{
get
{
if
(
staticBuffer
==
null
||
staticBuffer
.
Length
!=
bufferSize
)
{
staticBuffer
=
new
byte
[
bufferSize
];
}
return
staticBuffer
;
}
}
internal
CustomBinaryReader
(
CustomBufferedStream
stream
,
int
bufferSize
)
{
this
.
stream
=
stream
;
this
.
bufferSize
=
bufferSize
;
//default to UTF-8
encoding
=
Encoding
.
UTF8
;
...
...
@@ -34,35 +51,43 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns></returns>
internal
async
Task
<
string
>
ReadLineAsync
()
{
using
(
var
readBuffer
=
new
MemoryStream
())
{
var
lastChar
=
default
(
char
);
var
buffer
=
new
byte
[
1
];
var
lastChar
=
default
(
byte
);
int
bufferDataLength
=
0
;
while
((
await
stream
.
ReadAsync
(
buffer
,
0
,
1
))
>
0
)
// try to use the thread static buffer, usually it is enough
var
buffer
=
this
.
buffer
;
while
(
stream
.
DataAvailable
||
await
stream
.
FillBufferAsync
())
{
var
newChar
=
stream
.
ReadByteFromBuffer
();
buffer
[
bufferDataLength
]
=
newChar
;
//if new line
if
(
lastChar
==
'\r'
&&
buffer
[
0
]
==
'\n'
)
if
(
lastChar
==
'\r'
&&
newChar
==
'\n'
)
{
var
result
=
readBuffer
.
ToArray
();
return
encoding
.
GetString
(
result
.
SubArray
(
0
,
result
.
Length
-
1
));
return
encoding
.
GetString
(
buffer
,
0
,
bufferDataLength
-
1
);
}
//end of stream
if
(
buffer
[
0
]
==
'\0'
)
if
(
newChar
==
'\0'
)
{
return
encoding
.
GetString
(
readBuffer
.
ToArray
()
);
return
encoding
.
GetString
(
buffer
,
0
,
bufferDataLength
);
}
await
readBuffer
.
WriteAsync
(
buffer
,
0
,
1
)
;
bufferDataLength
++
;
//store last char for new line comparison
lastChar
=
(
char
)
buffer
[
0
];
}
lastChar
=
newChar
;
return
encoding
.
GetString
(
readBuffer
.
ToArray
());
if
(
bufferDataLength
==
buffer
.
Length
)
{
ResizeBuffer
(
ref
buffer
,
bufferDataLength
*
2
);
}
}
return
encoding
.
GetString
(
buffer
,
0
,
bufferDataLength
);
}
/// <summary>
/// Read until the last new line
/// </summary>
...
...
@@ -78,6 +103,17 @@ namespace Titanium.Web.Proxy.Helpers
return
requestLines
;
}
/// <summary>
/// Read until the last new line, ignores the result
/// </summary>
/// <returns></returns>
internal
async
Task
ReadAndIgnoreAllLinesAsync
()
{
while
(!
string
.
IsNullOrEmpty
(
await
ReadLineAsync
()))
{
}
}
/// <summary>
/// Read the specified number of raw bytes from the base stream
/// </summary>
...
...
@@ -91,34 +127,51 @@ namespace Titanium.Web.Proxy.Helpers
if
(
totalBytesToRead
<
bufferSize
)
bytesToRead
=
(
int
)
totalBytesToRead
;
var
buffer
=
new
byte
[
bufferSize
];
var
buffer
=
this
.
buffer
;
if
(
bytesToRead
>
buffer
.
Length
)
{
buffer
=
new
byte
[
bytesToRead
];
}
var
bytesRead
=
0
;
int
bytesRead
;
var
totalBytesRead
=
0
;
using
(
var
outStream
=
new
MemoryStream
())
{
while
((
bytesRead
+=
await
stream
.
ReadAsync
(
buffer
,
0
,
bytesToRead
))
>
0
)
while
((
bytesRead
=
await
stream
.
ReadAsync
(
buffer
,
totalBytesRead
,
bytesToRead
))
>
0
)
{
await
outStream
.
WriteAsync
(
buffer
,
0
,
bytesRead
);
totalBytesRead
+=
bytesRead
;
if
(
totalBytesRead
==
totalBytesToRead
)
break
;
bytesRead
=
0
;
var
remainingBytes
=
(
totalBytesToRead
-
totalBytesRead
);
bytesToRead
=
remainingBytes
>
(
long
)
bufferSize
?
bufferSize
:
(
int
)
remainingBytes
;
var
remainingBytes
=
totalBytesToRead
-
totalBytesRead
;
bytesToRead
=
Math
.
Min
(
bufferSize
,
(
int
)
remainingBytes
);
if
(
totalBytesRead
+
bytesToRead
>
buffer
.
Length
)
{
ResizeBuffer
(
ref
buffer
,
Math
.
Min
(
totalBytesToRead
,
buffer
.
Length
*
2
));
}
}
return
outStream
.
ToArray
();
if
(
totalBytesRead
!=
buffer
.
Length
)
{
//Normally this should not happen. Resize the buffer anyway
var
newBuffer
=
new
byte
[
totalBytesRead
];
Buffer
.
BlockCopy
(
buffer
,
0
,
newBuffer
,
0
,
totalBytesRead
);
buffer
=
newBuffer
;
}
return
buffer
;
}
public
void
Dispose
()
{
}
private
void
ResizeBuffer
(
ref
byte
[]
buffer
,
long
size
)
{
var
newBuffer
=
new
byte
[
size
];
Buffer
.
BlockCopy
(
buffer
,
0
,
newBuffer
,
0
,
buffer
.
Length
);
buffer
=
newBuffer
;
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs
0 → 100644
View file @
e82ad51e
This diff is collapsed.
Click to expand it.
Titanium.Web.Proxy/Helpers/SystemProxy.cs
View file @
e82ad51e
...
...
@@ -181,7 +181,7 @@ namespace Titanium.Web.Proxy.Helpers
if
(
tmp
.
StartsWith
(
"http="
)
||
tmp
.
StartsWith
(
"https="
))
{
var
endPoint
=
tmp
.
Substring
(
5
);
return
new
HttpSystemProxyValue
()
return
new
HttpSystemProxyValue
{
HostName
=
endPoint
.
Split
(
':'
)[
0
],
Port
=
int
.
Parse
(
endPoint
.
Split
(
':'
)[
1
]),
...
...
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
e82ad51e
...
...
@@ -78,18 +78,19 @@ namespace Titanium.Web.Proxy.Http
//prepare the request & headers
if
((
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
)
||
(
ServerConnection
.
UpStreamHttpsProxy
!=
null
&&
ServerConnection
.
IsHttps
))
{
requestLines
.
AppendLine
(
string
.
Join
(
" "
,
Request
.
Method
,
Request
.
RequestUri
.
AbsoluteUri
,
$"HTTP/
{
Request
.
HttpVersion
.
Major
}
.
{
Request
.
HttpVersion
.
Minor
}
"
)
);
requestLines
.
AppendLine
(
$"
{
Request
.
Method
}
{
Request
.
RequestUri
.
AbsoluteUri
}
HTTP/
{
Request
.
HttpVersion
.
Major
}
.
{
Request
.
HttpVersion
.
Minor
}
"
);
}
else
{
requestLines
.
AppendLine
(
string
.
Join
(
" "
,
Request
.
Method
,
Request
.
RequestUri
.
PathAndQuery
,
$"HTTP/
{
Request
.
HttpVersion
.
Major
}
.
{
Request
.
HttpVersion
.
Minor
}
"
)
);
requestLines
.
AppendLine
(
$"
{
Request
.
Method
}
{
Request
.
RequestUri
.
PathAndQuery
}
HTTP/
{
Request
.
HttpVersion
.
Major
}
.
{
Request
.
HttpVersion
.
Minor
}
"
);
}
//Send Authentication to Upstream proxy if needed
if
(
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
&&
!
string
.
IsNullOrEmpty
(
ServerConnection
.
UpStreamHttpProxy
.
UserName
)
&&
ServerConnection
.
UpStreamHttpProxy
.
Password
!=
null
)
{
requestLines
.
AppendLine
(
"Proxy-Connection: keep-alive"
);
requestLines
.
AppendLine
(
"Proxy-Authorization"
+
": Basic "
+
Convert
.
ToBase64String
(
Encoding
.
UTF8
.
GetBytes
(
ServerConnection
.
UpStreamHttpProxy
.
UserName
+
":"
+
ServerConnection
.
UpStreamHttpProxy
.
Password
)));
requestLines
.
AppendLine
(
"Proxy-Authorization"
+
": Basic "
+
Convert
.
ToBase64String
(
Encoding
.
UTF8
.
GetBytes
(
$"
{
ServerConnection
.
UpStreamHttpProxy
.
UserName
}
:
{
ServerConnection
.
UpStreamHttpProxy
.
Password
}
"
)));
}
//write request headers
foreach
(
var
headerItem
in
Request
.
RequestHeaders
)
...
...
@@ -97,7 +98,7 @@ namespace Titanium.Web.Proxy.Http
var
header
=
headerItem
.
Value
;
if
(
headerItem
.
Key
!=
"Proxy-Authorization"
)
{
requestLines
.
AppendLine
(
header
.
Name
+
": "
+
header
.
Value
);
requestLines
.
AppendLine
(
$"
{
header
.
Name
}
:
{
header
.
Value
}
"
);
}
}
...
...
@@ -109,7 +110,7 @@ namespace Titanium.Web.Proxy.Http
{
if
(
headerItem
.
Key
!=
"Proxy-Authorization"
)
{
requestLines
.
AppendLine
(
header
.
Name
+
": "
+
header
.
Value
);
requestLines
.
AppendLine
(
$"
{
header
.
Name
}
:
{
header
.
Value
}
"
);
}
}
}
...
...
@@ -132,13 +133,13 @@ namespace Titanium.Web.Proxy.Http
//find if server is willing for expect continue
if
(
responseStatusCode
.
Equals
(
"100"
)
&&
responseStatusDescription
.
ToLower
().
Equals
(
"continue"
))
&&
responseStatusDescription
.
Equals
(
"continue"
,
StringComparison
.
CurrentCultureIgnoreCase
))
{
Request
.
Is100Continue
=
true
;
await
ServerConnection
.
StreamReader
.
ReadLineAsync
();
}
else
if
(
responseStatusCode
.
Equals
(
"417"
)
&&
responseStatusDescription
.
ToLower
().
Equals
(
"expectation failed"
))
&&
responseStatusDescription
.
Equals
(
"expectation failed"
,
StringComparison
.
CurrentCultureIgnoreCase
))
{
Request
.
ExpectationFailed
=
true
;
await
ServerConnection
.
StreamReader
.
ReadLineAsync
();
...
...
@@ -178,7 +179,7 @@ namespace Titanium.Web.Proxy.Http
//For HTTP 1.1 comptibility server may send expect-continue even if not asked for it in request
if
(
Response
.
ResponseStatusCode
.
Equals
(
"100"
)
&&
Response
.
ResponseStatusDescription
.
ToLower
().
Equals
(
"continue"
))
&&
Response
.
ResponseStatusDescription
.
Equals
(
"continue"
,
StringComparison
.
CurrentCultureIgnoreCase
))
{
//Read the next line after 100-continue
Response
.
Is100Continue
=
true
;
...
...
@@ -189,7 +190,7 @@ namespace Titanium.Web.Proxy.Http
return
;
}
else
if
(
Response
.
ResponseStatusCode
.
Equals
(
"417"
)
&&
Response
.
ResponseStatusDescription
.
ToLower
().
Equals
(
"expectation failed"
))
&&
Response
.
ResponseStatusDescription
.
Equals
(
"expectation failed"
,
StringComparison
.
CurrentCultureIgnoreCase
))
{
//read next line after expectation failed response
Response
.
ExpectationFailed
=
true
;
...
...
Titanium.Web.Proxy/Http/Request.cs
View file @
e82ad51e
...
...
@@ -172,7 +172,7 @@ namespace Titanium.Web.Proxy.Http
{
var
header
=
RequestHeaders
[
"transfer-encoding"
];
return
header
.
Value
.
ToLower
().
Contains
(
"chunked"
);
return
header
.
Value
.
ContainsIgnoreCase
(
"chunked"
);
}
return
false
;
...
...
@@ -266,7 +266,7 @@ namespace Titanium.Web.Proxy.Http
var
header
=
RequestHeaders
[
"upgrade"
];
return
header
.
Value
.
ToLower
()
==
"websocket"
;
return
header
.
Value
.
Equals
(
"websocket"
,
StringComparison
.
CurrentCultureIgnoreCase
)
;
}
}
...
...
Titanium.Web.Proxy/Http/Response.cs
View file @
e82ad51e
...
...
@@ -54,7 +54,7 @@ namespace Titanium.Web.Proxy.Http
{
var
header
=
ResponseHeaders
[
"connection"
];
if
(
header
.
Value
.
ToLower
().
Contains
(
"close"
))
if
(
header
.
Value
.
ContainsIgnoreCase
(
"close"
))
{
return
false
;
}
...
...
@@ -153,7 +153,7 @@ namespace Titanium.Web.Proxy.Http
{
var
header
=
ResponseHeaders
[
"transfer-encoding"
];
if
(
header
.
Value
.
ToLower
().
Contains
(
"chunked"
))
if
(
header
.
Value
.
ContainsIgnoreCase
(
"chunked"
))
{
return
true
;
}
...
...
Titanium.Web.Proxy/Models/EndPoint.cs
View file @
e82ad51e
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Net
;
using
System.Net.Sockets
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Text.RegularExpressions
;
namespace
Titanium.Web.Proxy.Models
{
...
...
@@ -53,8 +55,8 @@ namespace Titanium.Web.Proxy.Models
/// </summary>
public
class
ExplicitProxyEndPoint
:
ProxyEndPoint
{
private
List
<
string
>
excludedHttpsHostNameRegex
;
private
List
<
string
>
includedHttpsHostNameRegex
;
internal
List
<
Regex
>
excludedHttpsHostNameRegex
;
internal
List
<
Regex
>
includedHttpsHostNameRegex
;
internal
bool
IsSystemHttpProxy
{
get
;
set
;
}
...
...
@@ -63,9 +65,9 @@ namespace Titanium.Web.Proxy.Models
/// <summary>
/// List of host names to exclude using Regular Expressions.
/// </summary>
public
List
<
string
>
ExcludedHttpsHostNameRegex
public
IEnumerable
<
string
>
ExcludedHttpsHostNameRegex
{
get
{
return
excludedHttpsHostNameRegex
;
}
get
{
return
excludedHttpsHostNameRegex
?.
Select
(
x
=>
x
.
ToString
()).
ToList
()
;
}
set
{
if
(
IncludedHttpsHostNameRegex
!=
null
)
...
...
@@ -73,16 +75,16 @@ namespace Titanium.Web.Proxy.Models
throw
new
ArgumentException
(
"Cannot set excluded when included is set"
);
}
excludedHttpsHostNameRegex
=
value
;
excludedHttpsHostNameRegex
=
value
?.
Select
(
x
=>
new
Regex
(
x
,
RegexOptions
.
Compiled
)).
ToList
()
;
}
}
/// <summary>
/// List of host names to exclude using Regular Expressions.
/// </summary>
public
List
<
string
>
IncludedHttpsHostNameRegex
public
IEnumerable
<
string
>
IncludedHttpsHostNameRegex
{
get
{
return
includedHttpsHostNameRegex
;
}
get
{
return
includedHttpsHostNameRegex
?.
Select
(
x
=>
x
.
ToString
()).
ToList
()
;
}
set
{
if
(
ExcludedHttpsHostNameRegex
!=
null
)
...
...
@@ -90,7 +92,7 @@ namespace Titanium.Web.Proxy.Models
throw
new
ArgumentException
(
"Cannot set included when excluded is set"
);
}
includedHttpsHostNameRegex
=
value
;
includedHttpsHostNameRegex
=
value
?.
Select
(
x
=>
new
Regex
(
x
,
RegexOptions
.
Compiled
)).
ToList
()
;
}
}
...
...
Titanium.Web.Proxy/Models/HttpHeader.cs
View file @
e82ad51e
using
System
;
using
System.IO
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Models
{
...
...
@@ -28,6 +30,7 @@ namespace Titanium.Web.Proxy.Models
/// Header Name.
/// </summary>
public
string
Name
{
get
;
set
;
}
/// <summary>
/// Header Value.
/// </summary>
...
...
@@ -41,5 +44,12 @@ namespace Titanium.Web.Proxy.Models
{
return
$"
{
Name
}
:
{
Value
}
"
;
}
internal
async
Task
WriteToStream
(
StreamWriter
writer
)
{
await
writer
.
WriteAsync
(
Name
);
await
writer
.
WriteAsync
(
": "
);
await
writer
.
WriteLineAsync
(
Value
);
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs
View file @
e82ad51e
...
...
@@ -52,14 +52,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary>
public
void
Dispose
()
{
Stream
.
Close
();
Stream
.
Dispose
();
Stream
?.
Close
();
Stream
?.
Dispose
();
StreamReader
?.
Dispose
();
TcpClient
.
LingerState
=
new
LingerOption
(
true
,
0
);
TcpClient
.
Client
.
Shutdown
(
SocketShutdown
.
Both
);
TcpClient
.
Client
.
Close
();
TcpClient
.
Client
.
Dispose
();
TcpClient
.
Close
();
}
...
...
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
e82ad51e
...
...
@@ -8,6 +8,7 @@ using Titanium.Web.Proxy.Helpers;
using
Titanium.Web.Proxy.Models
;
using
System.Security.Authentication
;
using
System.Linq
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Shared
;
namespace
Titanium.Web.Proxy.Network.Tcp
...
...
@@ -44,7 +45,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
Stream
clientStream
,
IPEndPoint
upStreamEndPoint
)
{
TcpClient
client
;
Stream
stream
;
CustomBuffered
Stream
stream
;
bool
isLocalhost
=
(
externalHttpsProxy
==
null
&&
externalHttpProxy
==
null
)
?
false
:
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
);
...
...
@@ -60,7 +61,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
client
=
new
TcpClient
(
upStreamEndPoint
);
await
client
.
ConnectAsync
(
externalHttpsProxy
.
HostName
,
externalHttpsProxy
.
Port
);
stream
=
client
.
GetStream
(
);
stream
=
new
CustomBufferedStream
(
client
.
GetStream
(),
bufferSize
);
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
bufferSize
,
true
)
{
NewLine
=
ProxyConstants
.
NewLine
})
{
...
...
@@ -78,24 +79,23 @@ namespace Titanium.Web.Proxy.Network.Tcp
writer
.
Close
();
}
using
(
var
reader
=
new
CustomBinaryReader
(
stream
))
using
(
var
reader
=
new
CustomBinaryReader
(
stream
,
bufferSize
))
{
var
result
=
await
reader
.
ReadLineAsync
();
if
(!
new
[]
{
"200 OK"
,
"connection established"
}.
Any
(
s
=>
result
.
ToLower
().
Contains
(
s
.
ToLower
())))
if
(!
new
[]
{
"200 OK"
,
"connection established"
}.
Any
(
s
=>
result
.
ContainsIgnoreCase
(
s
)))
{
throw
new
Exception
(
"Upstream proxy failed to create a secure tunnel"
);
}
await
reader
.
ReadAllLinesAsync
();
await
reader
.
ReadA
ndIgnoreA
llLinesAsync
();
}
}
else
{
client
=
new
TcpClient
(
upStreamEndPoint
);
await
client
.
ConnectAsync
(
remoteHostName
,
remotePort
);
stream
=
client
.
GetStream
(
);
stream
=
new
CustomBufferedStream
(
client
.
GetStream
(),
bufferSize
);
}
try
...
...
@@ -105,7 +105,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
await
sslStream
.
AuthenticateAsClientAsync
(
remoteHostName
,
null
,
supportedSslProtocols
,
false
);
stream
=
sslStream
;
stream
=
new
CustomBufferedStream
(
sslStream
,
bufferSize
)
;
}
catch
{
...
...
@@ -120,13 +120,13 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
client
=
new
TcpClient
(
upStreamEndPoint
);
await
client
.
ConnectAsync
(
externalHttpProxy
.
HostName
,
externalHttpProxy
.
Port
);
stream
=
client
.
GetStream
(
);
stream
=
new
CustomBufferedStream
(
client
.
GetStream
(),
bufferSize
);
}
else
{
client
=
new
TcpClient
(
upStreamEndPoint
);
await
client
.
ConnectAsync
(
remoteHostName
,
remotePort
);
stream
=
client
.
GetStream
(
);
stream
=
new
CustomBufferedStream
(
client
.
GetStream
(),
bufferSize
);
}
}
...
...
@@ -137,7 +137,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
stream
.
WriteTimeout
=
connectionTimeOutSeconds
*
1000
;
return
new
TcpConnection
()
return
new
TcpConnection
{
UpStreamHttpProxy
=
externalHttpProxy
,
UpStreamHttpsProxy
=
externalHttpsProxy
,
...
...
@@ -145,7 +145,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
Port
=
remotePort
,
IsHttps
=
isHttps
,
TcpClient
=
client
,
StreamReader
=
new
CustomBinaryReader
(
stream
),
StreamReader
=
new
CustomBinaryReader
(
stream
,
bufferSize
),
Stream
=
stream
,
Version
=
httpVersion
};
...
...
Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
View file @
e82ad51e
...
...
@@ -48,7 +48,7 @@ namespace Titanium.Web.Proxy
var
header
=
httpHeaders
.
FirstOrDefault
(
t
=>
t
.
Name
==
"Proxy-Authorization"
);
if
(
null
==
header
)
throw
new
NullReferenceException
();
var
headerValue
=
header
.
Value
.
Trim
();
if
(!
headerValue
.
ToLower
().
StartsWith
(
"basic"
))
if
(!
headerValue
.
StartsWith
(
"basic"
,
StringComparison
.
CurrentCultureIgnoreCase
))
{
//Return not authorized
await
WriteResponseStatus
(
new
Version
(
1
,
1
),
"407"
,
...
...
@@ -95,7 +95,7 @@ namespace Titanium.Web.Proxy
}
var
username
=
decoded
.
Substring
(
0
,
decoded
.
IndexOf
(
':'
));
var
password
=
decoded
.
Substring
(
decoded
.
IndexOf
(
':'
)
+
1
);
return
await
AuthenticateUserFunc
(
username
,
password
)
.
ConfigureAwait
(
false
)
;
return
await
AuthenticateUserFunc
(
username
,
password
);
}
catch
(
Exception
e
)
{
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
e82ad51e
...
...
@@ -616,8 +616,6 @@ namespace Titanium.Web.Proxy
}
else
{
await
HandleClient
(
endPoint
as
ExplicitProxyEndPoint
,
tcpClient
);
}
...
...
@@ -631,12 +629,7 @@ namespace Titanium.Web.Proxy
//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
.
Client
.
Shutdown
(
SocketShutdown
.
Both
);
tcpClient
.
Client
.
Close
();
tcpClient
.
Client
.
Dispose
();
tcpClient
.
Close
();
}
}
});
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
e82ad51e
...
...
@@ -6,7 +6,6 @@ using System.Net;
using
System.Net.Security
;
using
System.Net.Sockets
;
using
System.Security.Authentication
;
using
System.Text.RegularExpressions
;
using
Titanium.Web.Proxy.Exceptions
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Helpers
;
...
...
@@ -30,12 +29,12 @@ namespace Titanium.Web.Proxy
private
async
Task
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
Stream
clientStream
=
tcpClient
.
GetStream
(
);
CustomBufferedStream
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
clientStream
.
ReadTimeout
=
ConnectionTimeOutSeconds
*
1000
;
clientStream
.
WriteTimeout
=
ConnectionTimeOutSeconds
*
1000
;
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
);
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
var
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
Uri
httpRemoteUri
;
...
...
@@ -76,12 +75,12 @@ namespace Titanium.Web.Proxy
if
(
endPoint
.
ExcludedHttpsHostNameRegex
!=
null
)
{
excluded
=
endPoint
.
ExcludedHttpsHostNameRegex
.
Any
(
x
=>
Regex
.
IsMatch
(
httpRemoteUri
.
Host
,
x
));
excluded
=
endPoint
.
excludedHttpsHostNameRegex
.
Any
(
x
=>
x
.
IsMatch
(
httpRemoteUri
.
Host
));
}
if
(
endPoint
.
IncludedHttpsHostNameRegex
!=
null
)
{
excluded
=
!
endPoint
.
IncludedHttpsHostNameRegex
.
Any
(
x
=>
Regex
.
IsMatch
(
httpRemoteUri
.
Host
,
x
));
excluded
=
!
endPoint
.
includedHttpsHostNameRegex
.
Any
(
x
=>
x
.
IsMatch
(
httpRemoteUri
.
Host
));
}
List
<
HttpHeader
>
connectRequestHeaders
=
null
;
...
...
@@ -112,7 +111,6 @@ namespace Titanium.Web.Proxy
try
{
sslStream
=
new
SslStream
(
clientStream
,
true
);
var
certificate
=
endPoint
.
GenericCertificate
??
certificateManager
.
CreateCertificate
(
httpRemoteUri
.
Host
,
false
);
...
...
@@ -121,11 +119,10 @@ namespace Titanium.Web.Proxy
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SupportedSslProtocols
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
clientStream
=
sslStream
;
clientStreamReader
=
new
CustomBinaryReader
(
sslStream
);
clientStreamWriter
=
new
StreamWriter
(
sslStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
}
catch
{
...
...
@@ -142,8 +139,8 @@ namespace Titanium.Web.Proxy
//Sorry cannot do a HTTPS request decrypt to port 80 at this time
else
if
(
httpVerb
==
"CONNECT"
)
{
//
Cyphe
n out CONNECT request headers
await
clientStreamReader
.
ReadAllLinesAsync
();
//
Sipho
n out CONNECT request headers
await
clientStreamReader
.
ReadA
ndIgnoreA
llLinesAsync
();
//write back successfull CONNECT response
await
WriteConnectResponse
(
clientStreamWriter
,
version
);
...
...
@@ -171,8 +168,7 @@ namespace Titanium.Web.Proxy
//So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
private
async
Task
HandleClient
(
TransparentProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
Stream
clientStream
=
tcpClient
.
GetStream
();
CustomBufferedStream
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
clientStream
.
ReadTimeout
=
ConnectionTimeOutSeconds
*
1000
;
clientStream
.
WriteTimeout
=
ConnectionTimeOutSeconds
*
1000
;
...
...
@@ -193,8 +189,9 @@ namespace Titanium.Web.Proxy
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SslProtocols
.
Tls
,
false
);
clientStreamReader
=
new
CustomBinaryReader
(
sslStream
);
clientStreamWriter
=
new
StreamWriter
(
sslStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
//HTTPS server created - we can now decrypt the client's traffic
}
...
...
@@ -205,11 +202,10 @@ namespace Titanium.Web.Proxy
Dispose
(
sslStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
}
clientStream
=
sslStream
;
}
else
{
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
);
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
}
...
...
@@ -231,14 +227,14 @@ namespace Titanium.Web.Proxy
{
if
(
GetCustomUpStreamHttpProxyFunc
!=
null
)
{
customUpStreamHttpProxy
=
await
GetCustomUpStreamHttpProxyFunc
(
args
)
.
ConfigureAwait
(
false
)
;
customUpStreamHttpProxy
=
await
GetCustomUpStreamHttpProxyFunc
(
args
);
}
}
else
{
if
(
GetCustomUpStreamHttpsProxyFunc
!=
null
)
{
customUpStreamHttpsProxy
=
await
GetCustomUpStreamHttpsProxyFunc
(
args
)
.
ConfigureAwait
(
false
)
;
customUpStreamHttpsProxy
=
await
GetCustomUpStreamHttpsProxyFunc
(
args
);
}
}
...
...
@@ -498,7 +494,7 @@ namespace Titanium.Web.Proxy
}
//construct the web request that we are going to issue on behalf of the client.
await
HandleHttpSessionRequestInternal
(
null
,
args
,
customUpStreamHttpProxy
,
customUpStreamHttpsProxy
,
false
)
.
ConfigureAwait
(
false
)
;
await
HandleHttpSessionRequestInternal
(
null
,
args
,
customUpStreamHttpProxy
,
customUpStreamHttpsProxy
,
false
);
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
e82ad51e
...
...
@@ -50,9 +50,9 @@ namespace Titanium.Web.Proxy
await
Task
.
WhenAll
(
handlerTasks
);
}
if
(
args
.
ReRequest
)
if
(
args
.
ReRequest
)
{
await
HandleHttpSessionRequestInternal
(
null
,
args
,
null
,
null
,
true
)
.
ConfigureAwait
(
false
)
;
await
HandleHttpSessionRequestInternal
(
null
,
args
,
null
,
null
,
true
);
return
;
}
...
...
@@ -124,7 +124,7 @@ namespace Titanium.Web.Proxy
await
args
.
ProxyClient
.
ClientStream
.
FlushAsync
();
}
catch
(
Exception
e
)
catch
(
Exception
e
)
{
ExceptionFunc
(
new
ProxyHttpException
(
"Error occured wilst handling session response"
,
e
,
args
));
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
...
...
@@ -175,7 +175,7 @@ namespace Titanium.Web.Proxy
foreach
(
var
header
in
response
.
ResponseHeaders
)
{
await
responseWriter
.
WriteLineAsync
(
header
.
Value
.
ToString
()
);
await
header
.
Value
.
WriteToStream
(
responseWriter
);
}
//write non unique request headers
...
...
@@ -184,11 +184,10 @@ namespace Titanium.Web.Proxy
var
headers
=
headerItem
.
Value
;
foreach
(
var
header
in
headers
)
{
await
responseWriter
.
WriteLineAsync
(
header
.
ToString
()
);
await
header
.
WriteToStream
(
responseWriter
);
}
}
await
responseWriter
.
WriteLineAsync
();
await
responseWriter
.
FlushAsync
();
}
...
...
@@ -231,20 +230,15 @@ namespace Titanium.Web.Proxy
private
void
Dispose
(
Stream
clientStream
,
CustomBinaryReader
clientStreamReader
,
StreamWriter
clientStreamWriter
,
IDisposable
args
)
{
if
(
clientStream
!=
null
)
{
clientStream
.
Close
();
clientStream
.
Dispose
();
}
args
?.
Dispose
();
clientStream
?.
Close
();
clientStream
?.
Dispose
();
clientStreamReader
?.
Dispose
();
if
(
clientStreamWriter
==
null
)
return
;
clientStreamWriter
.
Close
();
clientStreamWriter
.
Dispose
();
clientStreamWriter
?.
Close
();
clientStreamWriter
?.
Dispose
();
args
?.
Dispose
();
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
e82ad51e
...
...
@@ -26,6 +26,7 @@
<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>
...
...
@@ -72,6 +73,8 @@
<Compile
Include=
"EventArguments\CertificateSelectionEventArgs.cs"
/>
<Compile
Include=
"EventArguments\CertificateValidationEventArgs.cs"
/>
<Compile
Include=
"Extensions\ByteArrayExtensions.cs"
/>
<Compile
Include=
"Extensions\StringExtensions.cs"
/>
<Compile
Include=
"Helpers\CustomBufferedStream.cs"
/>
<Compile
Include=
"Helpers\Network.cs"
/>
<Compile
Include=
"Helpers\RunTime.cs"
/>
<Compile
Include=
"Http\Responses\GenericResponse.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