-
Notifications
You must be signed in to change notification settings - Fork 0
/
MiddleMan.cs
142 lines (130 loc) · 4.37 KB
/
MiddleMan.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//
// Copyright (C) 2021 William Stackenäs <[email protected]>
//
// This file is part of Tiriryarai.
//
// Tiriryarai is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Tiriryarai is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
using System.Text;
using System.Text.RegularExpressions;
using Tiriryarai.Http;
using Tiriryarai.Server;
using Tiriryarai.Util;
namespace TiriryaraiMitm
{
public class MiddleMan : IManInTheMiddle
{
private bool intercept;
private Logger logger;
private HttpsMitmProxyConfig conf;
public MiddleMan()
{
intercept = false;
logger = Logger.GetSingleton();
conf = HttpsMitmProxyConfig.GetSingleton();
// An example of what could be done here is to create an ini
// file in the directory specified by conf.ConfigDirectory
// if it doesn't exist, or read configuration from it if it
// does exist. The configuration file could be encrypted using
// conf.PassKey.
}
public bool Block(string hostname)
{
// Block all private IP addresses to prevent bypassing
// a firewall
return new Regex(
"(^127\\.)|(^10\\.)|(^172\\.1[6-9]\\.)|(^172\\.2[0-9]\\.)|(^172\\.3[0-1]\\.)|(^192\\.168\\.)"
).IsMatch(hostname);
}
public HttpMessage HandleRequest(HttpRequest req)
{
if (intercept)
{
// Intercept the request and return a response instead
HttpResponse resp = new HttpResponse(200);
resp.SetHeader("Content-Type", "text/html");
resp.SetDecodedBodyAndLength(Encoding.Default.GetBytes(
"<p>Your request was intercepted and not sent to the host!</p>"
));
return resp;
}
// Replace the connection header and remove all headers in its header
// fields in accordance to rfc7230 section 6.1. Tiriryarai does not
// follow rfc proxy conventions fully to allow plugins the freedom to
// choose whether or not to follow them.
string[] connection = req.GetHeader("Connection");
if (connection != null)
{
foreach (string field in connection)
{
req.RemoveHeader(field);
}
req.SetHeader("Connection", "keep-alive");
logger.Log(3, req.Host, "REPLACED CONNECTION HEADER", req);
}
// Add header if the request was destined to example.org
if ("example.org".Equals(req.Host))
{
req.SetHeader("X-To-Example", "true");
logger.Log(3, req.Host, "ADDED A HEADER", req);
}
return req;
}
public HttpResponse HandleResponse(HttpResponse resp, HttpRequest req)
{
// Add header if the request was destined to example.org
if ("example.org".Equals(req.Host))
{
resp.SetHeader("X-From-Example", "true");
logger.Log(3, req.Host, "ADDED A HEADER", resp);
}
return resp;
}
public HttpResponse HomePage(HttpRequest req)
{
// Display a simple web page for downloading the root CA certificate
// and set a boolean to intercept requests
string msg = "";
string path = req.Path;
string contentType = req.ContentTypeWithoutCharset;
HttpResponse resp = new HttpResponse(200);
resp.SetHeader("Content-Type", "text/html");
if ("/save".Equals(path) && req.Method == Method.POST &&
"application/x-www-form-urlencoded".Equals(contentType))
{
intercept = "on".Equals(req.GetBodyParam("intercept"));
msg = "<p style=\"color:#00FF00\";>Saved!</p>";
}
resp.SetDecodedBodyAndLength(Encoding.Default.GetBytes(string.Format(
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"<title>Tiriryarai</title>" +
"<meta charset=\"utf-8\"/>" +
"</head>" +
"<body>" +
"<h1>Custom MitM configuration page</h1>" +
"<form method=\"post\" action=\"/save\">" +
"<input type=\"checkbox\" name=\"intercept\" id=\"intercept\" {0}/>" +
"<label for=\"intercept\">Intercept</label><br><br>" +
"<input type=\"submit\" name=\"submit\" value=\"Save\"/>" +
"</form>" +
"{1}" +
"</body>" +
"</html>", intercept ? "checked" : "", msg)
));
return resp;
}
}
}