def request(self, flow): try: flow.response = self.create_response(flow.request) except ConnectionError: # If TCP Rst Configured if self.on_rst: self.logger.debug("Got TCP Rst, While TCP Rst Configured") self.multitor.new_identity() # Set Response try: flow.response = self.create_response(flow.request) except Exception as error: self.logger.error( "Got Unknown Error (after second TCP Rst) %s" % error) flow.response = HTTPResponse.make( 400, "Unknown Error (after second TCP Rst) %s" % error) return else: self.logger.error("Got TCP Rst, While TCP Rst Not Configured") flow.response = HTTPResponse.make(400, "Got TCP Rst") return except Exception as error: self.logger.error("Got Unknown Error %s" % error) flow.response = HTTPResponse.make(400, "Unknown Error %s" % error) return # If String Found In Response Content if self.on_string and self.on_string in flow.response.text: self.logger.debug("String Found In Response Content") self.multitor.new_identity() # Set Response flow.response = self.create_response(flow.request) # If Regex Found In Response Content if self.on_regex and re.search(self.on_regex, flow.response.text, re.IGNORECASE): self.logger.debug("Regex Found In Response Content") self.multitor.new_identity() # Set Response flow.response = self.create_response(flow.request) # If Counter Raised To The Configured Number if self.on_count and next(self.counter) >= self.on_count: self.logger.debug("Counter Raised To The Configured Number") self.counter = itertools.count(1) self.multitor.new_identity() # If A Specific Status Code Returned if self.on_error_code and self.on_error_code == flow.response.status_code: self.logger.debug("Specific Status Code Returned") self.multitor.new_identity() # Set Response flow.response = self.create_response(flow.request)
def request(flow): if LOG_LEVEL is None: start() _changeHeader(flow.request.headers, 'Proxy-Connection') _changeHeader(flow.request.headers, 'X-Requested-With') flow.remote_server = True flow.own_response = False if '127.0.0.1' in flow.request.pretty_host: urls = flow.request.url.split('/') flow.request.url = '/'.join(urls[:2] + urls[3:]) flow.remote_server = False host = flow.request.pretty_host if host.endswith('.ssl'): flow.request.scheme = 'https' flow.request.port = 443 flow.request.url = flow.request.url.replace('.ssl/', '/', 1) if flow.request.scheme != 'https' and FORCE_HTTPS: flow.request.scheme = 'https' newUrl = _sanitizeLocation(flow.request.url) flow.response = HTTPResponse.make(301, '', {'Location': newUrl}) flow.own_response = True return if flow.remote_server and PDF_PORT and flow.request.url.endswith('.pdf'): parts = _sanitizeLocation(flow.request.url).split('/') flow.request.port = int(PDF_PORT) newUrl = '/'.join(parts[:2] + ['127.0.0.1:' + PDF_PORT] + parts[2:]) flow.response = HTTPResponse.make(302, '', {'Location': newUrl}) flow.own_response = True return _changeHeader(flow.request.headers, 'Referer', '.ssl') _changeHeader(flow.request.headers, 'Origin', '.ssl') _changeHeader(flow.request.headers, 'User-Agent', TOR_UA) _changeHeader( flow.request.headers, 'Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8') _changeHeader(flow.request.headers, 'Accept-Language', 'en-US,en;q=0.5') uirh = 'Upgrade-Insecure-Requests' if not _iGet(flow.request.headers, uirh, None): flow.request.headers[uirh] = '1' newReqData = re.sub(b'http%3A%2F%2F' + dnsRegExp + b'.ssl', b'https%3A%2F%2F' + b'\\1', flow.request.content, flags=re.IGNORECASE) # Touch content only if needed: if newReqData != flow.request.content: if LOG_LEVEL > 0: print('newReqData !=;', flow.request.url) flow.request.content = newReqData if LOG_LEVEL > 0: print('requestH(' + flow.request.url + ')', flow.request.headers) if LOG_LEVEL > 1: print('requestC(' + flow.request.url + ')', flow.request.content)
def replaceImage(flow): attrs = dict((x.lower(), y) for x, y in flow.response.headers.items()) if "content-type" in attrs: if "image" in attrs['content-type'] and not "svg" in attrs['content-type']: if flow.response.status_code == 304: content = flow.response.content else: content = requests.get(flow.request.url).content if len(content) == 0: return flow try: img = Image.open(io.BytesIO(content)) size = img.size if size[0] > 40 and size[1] > 40: filename = random.choice(os.listdir("images")) img = resizeImg("images/" + filename, size[0], size[1]) #content = img.make_blob() imgByteArr = io.BytesIO() img.save(imgByteArr, format='BMP') content = imgByteArr.getvalue() responseHeaders = {'Content-Length':str(len(content))} responseHeaders['Content-Type'] = "image/bmp" #import pdb;pdb.set_trace() resp = HTTPResponse.make(status_code=200, headers=responseHeaders, content=content) flow.response = resp except: PrintException() return flow
def request(self, flow: HTTPFlow): if flow.request.host in self.ServersList and flow.request.path.startswith( "/charBuild/setDefaultSkill"): self.info("Receive default skill change change request") req = json.loads(flow.request.get_text()) self.tBuilder.chars[str( req["charInstId"] )]["defaultSkillIndex"] = req["defaultSkillIndex"] resp = { "playerDataDelta": { "deleted": {}, "modified": { "troop": { "chars": { str(req["charInstId"]): { "defaultSkillIndex": req["defaultSkillIndex"] } } } } } } self.info("make response") flow.response = HTTPResponse.make( 200, json.dumps(resp), {"Content-Type": "application/json; charset=utf-8"}) self.info("Reply Complete")
def request(self, flow: HTTPFlow): """ { "charInstId": 9, "skinId": "char_123_fang#1" } """ if self.inServersList( flow.request.host) and flow.request.path.startswith( "/charBuild/changeCharSkin"): self.info("Receive skin change request") req = json.loads(flow.request.get_text()) resp = { "playerDataDelta": { "deleted": {}, "modified": { "troop": { "chars": { str(req["charInstId"]): { "skin": req["skinId"] } } } } } } self.info("make response") self.tBuilder.chars[str(req["charInstId"])]["skin"] = req["skinId"] flow.response = HTTPResponse.make( 200, json.dumps(resp), {"Content-Type": "application/json; charset=utf-8"}) self.info("Reply Complete")
def replaceImage(flow): attrs = dict((x.lower(), y) for x, y in flow.response.headers.items()) if "content-type" in attrs: if "image" in attrs[ 'content-type'] and not "svg" in attrs['content-type']: if flow.response.status_code == 304: content = flow.response.content else: content = requests.get(flow.request.url).content if len(content) == 0: return flow try: img = Image.open(io.BytesIO(content)) size = img.size if size[0] > 40 and size[1] > 40: filename = random.choice(os.listdir("images")) img = resizeImg("images/" + filename, size[0], size[1]) #content = img.make_blob() imgByteArr = io.BytesIO() img.save(imgByteArr, format='JPEG') content = imgByteArr.getvalue() responseHeaders = {'Content-Length': str(len(content))} responseHeaders['Content-Type'] = "image/jpg" #import pdb;pdb.set_trace() resp = HTTPResponse.make(status_code=200, headers=responseHeaders, content=content) flow.response = resp except: PrintException() return flow
def request(self, flow): if self.pred(flow): try: if flow.request.method == 'GET': row = self.st.get_row_by_url(flow.request.url) if row is None: ctx.log.info('@ not found: {}'.format(flow.request.url)) flow.response = HTTPResponse.make(404, content=flow.request.url) else: ctx.log.info('@ using row: {}'.format(row)) flow.response = HTTPResponse.make( content=self.st.get_blob(row.hash), headers={ 'content-type': row.content_type }, ) except Exception as e: flow.response = HTTPResponse.make(500, content=str(e))
def homepage_refresh(self, flow, url): flow.direct_response = True environ = {} environ['webrec.template_params'] = {'url': url} resp_data = self.home_redir_view.render_to_string(environ).encode( 'utf-8') flow.response = HTTPResponse.make( 200, resp_data, {'Content-Type': 'text/html; charset=utf-8'}) return True
def request(flow): url = flow.request.pretty_url host = flow.request.pretty_host print('request():', host, url) if any(map(lambda s: host.startswith(s), ignoreHosts)): return resp = HTTPResponse.make( 303, url, { 'Content_Type': "text/html", 'Location': url.replace('http://', 'https://', 1) }) now = time.time() if insecure_urls[url] + 61 > now: resp = HTTPResponse.make(500, "mitm seen before" + url, {}) if len(insecure_urls) > 5 * 1024: print('request(): insecure_urls.clear()') insecure_urls.clear() insecure_urls[url] = now flow.response = resp
def block_telemetry(flow: HTTPFlow): if config.block_telemetry and flow.request.path.startswith('/telemetry'): flow.request.text = '{}' # Just in case flow.response = HTTPResponse.make(200, '{}') flow.response.headers.add('Content-Type', 'application/json') flow.response.headers.add('server', 'eos-gateway') flow.response.headers.add('access-control-allow-origin', '*') flow.response.headers.add('x-epic-correlation-id', '12345678-1234-1234-1234-123456789abc') log.info('Blocked telemetry request from Epic Games')
def request(self, flow): error_message = None try: flow.response = self.create_response(flow.request) except ConnectionError: # If TCP Rst Configured if self.on_rst: self.logger.debug("Got TCP Rst, While TCP Rst Configured") self.multitor.new_identity() # Set Response try: flow.response = self.create_response(flow.request) except Exception as error: error_message = f"Got Error: {error}" else: error_message = "Got TCP Rst, While TCP Rst Not Configured" except Exception as error: error_message = f"Got Error: {error}" # When There Is No Response if error_message: self.logger.error(error_message) flow.response = HTTPResponse.make( status_code=500, content=error_message, headers={"Server": f"pymultitor/{__version__}"}) return # If String Found In Response Content if self.on_string and self.on_string in flow.response.text: self.logger.debug("String Found In Response Content") self.multitor.new_identity() # Set Response flow.response = self.create_response(flow.request) # If Regex Found In Response Content if self.on_regex and re.search(self.on_regex, flow.response.text, re.IGNORECASE): self.logger.debug("Regex Found In Response Content") self.multitor.new_identity() # Set Response flow.response = self.create_response(flow.request) # If Counter Raised To The Configured Number if self.on_count and not next(self.counter) % self.on_count: self.logger.debug("Counter Raised To The Configured Number") self.multitor.new_identity() # If A Specific Status Code Returned if self.on_error_code and self.on_error_code == flow.response.status_code: self.logger.debug("Specific Status Code Returned") self.multitor.new_identity() # Set Response flow.response = self.create_response(flow.request)
def request(self, flow: HTTPFlow): """MITMProxy addon event interface for outgoing request.""" try: request = MITMRequest.from_mitmproxy(flow.request) response = self.process_request(request).to_mitmproxy() flow.response = response except DoNotIntercept as e: # Let the request pass through, by not interrupting the flow, but log it logger.warning(str(e)) except Exception as e: flow.response = HTTPResponse.make( status_code=getattr(e, 'http_status_code', 500), content=str(e), headers={'Content-Type': 'text/plain'})
def create_response(self, request): response = requests.request(method=request.method, url=request.url, data=request.content, headers=request.headers, allow_redirects=False, verify=not self.insecure, proxies=self.multitor.proxy) return HTTPResponse.make( status_code=response.status_code, content=response.content, headers=dict(response.headers), )
def request(flow): host = flow.request.headers.get('Host', '') if host.endswith('.https'): flow.request.scheme = 'https' flow.request.port = 443 origHost = host.replace('.https', '') flow.request.host = origHost elif host.endswith('.http'): flow.request.scheme = 'http' flow.request.port = 80 origHost = host.replace('.http', '') flow.request.host = origHost else: flow.response = HTTPResponse.make(418) if False: print('requestH(' + flow.request.url + ')', flow.request.headers)
def block_playtime(flow: HTTPFlow): if config.block_playtime and flow.request.path.startswith('/library/api/public/playtime/'): original_playtime = json.loads(flow.request.text) flow.request.text = '{}' # Just in case correlation_id = flow.request.headers.get('X-Epic-Correlation-ID') if m := re.match(r"UE4-(\w+)", correlation_id): device_id = m.group(1) else: device_id = '123456789abcdef01234567890abcdef' flow.response = HTTPResponse.make(204) flow.response.headers.add('x-epic-device-id', device_id) flow.response.headers.add('x-epic-correlation-id', correlation_id) flow.response.headers.add('x-envoy-upstream-service-time', '10') # ? flow.response.headers.add('server', 'istio-envoy') log.info('Blocked playtime request from Epic Games') log.debug(f'\n{json.dumps(original_playtime, indent=4)}')
def create_response(self, request): response = requests.request(method=request.method, url=request.url, data=request.content, headers=request.headers, allow_redirects=False, verify=not self.insecure, proxies=self.multitor.proxy, stream=False) # Content-Length and Transfer-Encoding set. This is expressly forbidden by RFC 7230 sec 3.3.2. if response.headers.get("Transfer-Encoding") == "chunked": response.headers.pop("Transfer-Encoding") return HTTPResponse.make( status_code=response.status_code, content=response.content, headers=dict(response.headers), )
def request(flow): global rules req = flow.request options = {'domain': req.host} db_insert(req.host) with open('hostname.txt', 'a') as f: f.write(f"{req.host} ===> url {flow.request.url}\n \n\n\n\n") if IMAGE_MATCHER.search(req.path): options["image"] = True elif SCRIPT_MATCHER.search(req.path): options["script"] = True elif STYLESHEET_MATCHER.search(req.path): options["stylesheet"] = True if rules.should_block(req.url, options): log("vvvvvvvvvvvvvvvvvvvv BLOCKED vvvvvvvvvvvvvvvvvvvvvvvvvvv") with open('block_sites.txt', 'a') as file: file.write( f'{flow.request.url} ===> header: {flow.request.headers.get("Accept")}\n' ) file.write(f'options {options}\n\n\n\n\n') log("accept: %s" % flow.request.headers.get("Accept")) log("blocked-url: %s" % flow.request.url) log("^^^^^^^^^^^^^^^^^^^^ BLOCKED ^^^^^^^^^^^^^^^^^^^^^^^^^^^") flow.response = HTTPResponse.make(404, b"OK", {"Content-Type": "text/html"}) # HTTPResponse(http_version, status_code, reason, headers, content, timestamp_start=None, timestamp_end=None) else: log("url: %s" % flow.request.url)
def request(self, flow: HTTPFlow): if flow.request.host in self.ServersList and flow.request.path.startswith( "/quest/battleStart"): req = json.loads(flow.request.get_text()) if (req["stageId"] != "main_08-16"): return self.info("Receive JT8-2 battle start request") fakeData = { "apFailReturn": 20, "battleId": "6c86c7c0-3373-11eb-9784-0d36b8275660", "isApProtect": 0, "notifyPowerScoreNotEnoughIfFailed": False, "playerDataDelta": { "deleted": {}, "modified": { # "dungeon": { # "stages": { # "main_07-01": { # "completeTimes": 1, # "hasBattleReplay": 1, # "noCostCnt": 0, # "practiceTimes": 0, # "stageId": "main_07-01", # "startTimes": 2, # "state": 3 # } # } # } } }, "result": 0 } flow.response = HTTPResponse.make( 200, json.dumps(fakeData), {"Content-Type": "application/json; charset=utf-8"}) self.info("complete")
def perform(self, flow, qs): flow.response = HTTPResponse.make( 302, b"", {"Location": self.build_destination(qs)} )
def response(flow): if LOG_LEVEL is None: start() if flow.own_response: return if LOG_LEVEL > 0: print('responseH(' + flow.request.url + ')', flow.response.headers) rHeaders = flow.response.headers ct = _iGet(rHeaders, 'content-type') if LOG_LEVEL > 1: doPrint = True for i in ('image'): if i in ct: doPrint = False if doPrint: print('responseC(' + flow.request.url + ')', flow.response.content) if _iGet(rHeaders, 'Location').startswith('http'): newUrl = _sanitizeLocation(_iGet(rHeaders, 'Location')) rHeaders[_iKeys(rHeaders, 'Location')[0]] = newUrl rCnt = flow.response.content if LOG_LEVEL > 0: print('FILTER_CONTENT;', ct) if FILTER_CONTENT: isAccepted = len(rCnt) == 0 for f in ALLOWED_CONTENT_TYPES: isAccepted = isAccepted or ct.startswith(f) if not isAccepted and flow.remote_server: flow.response = HTTPResponse.make(404) return _changeHeader(rHeaders, 'Content-Security-Policy') _changeHeader(rHeaders, 'Strict-Transport-Security') _changeHeader(rHeaders, 'Public-Key-Pins') cookies_old = rHeaders.get_all('Set-Cookie') cookies_new = [] for s in cookies_old: sn = re.sub(r';\s*[Ss]ecure\s*', '', s) cookies_new.append(sn) if 'domain=' in sn.lower(): sn = re.sub('domain\s*=\s*' + dnsRegExp.decode('utf-8'), 'domain=' + r'\1.ssl', sn, flags=re.IGNORECASE) cookies_new.append(sn) rHeaders.set_all('Set-Cookie', cookies_new) if LOG_LEVEL > 1: print('responseH(' + flow.request.url + ') cookies', cookies_new) # Replace content only in text; https is filtered out anyway. doNotTouch = True for typ in ( 'text/html', 'text/json', ): if typ in ct: doNotTouch = False if doNotTouch: return for urlPrefix in ( b'"https://', b'" https://', b'url=https://', b'\(https://', b"'https://", b'href=\\\\"https:\\\\/\\\\/', ): rCnt = re.sub(urlPrefix + dnsRegExp, urlPrefix.replace(b's:', b':') + b'\\1.ssl', rCnt, flags=re.IGNORECASE) rCnt = _rmRegexp( rCnt, b'<meta[^<>]*http-equiv=["\']Content-Security-Policy[^<>]*>') if flow.request.host not in OK_REDIRECT: rCnt = _rmRegexp(rCnt, b'<meta[^<>]*http-equiv=["\']refresh[^<>]*>') rCnt = _rmRegexp(rCnt, b'class="NoScriptForm[^"]*"') # twitter flow.response.content = rCnt
def homepage_redir(self, flow, redir_url): flow.request.host = self.fwd_host flow.response = HTTPResponse.make(303, b'', {'Location': redir_url}) return True
def block_telemetry(flow: HTTPFlow): if config.block_telemetry and flow.request.path.startswith( '/ratt/telm'): flow.response = HTTPResponse.make(500, 'No more spying') log.debug('Blocked telemetry request from Origin')
def http_connect(flow): flow.response = HTTPResponse.make(403)
def reply_from_proxy(flow: HTTPFlow): flow.response = HTTPResponse.make(418)
def test_kill_flow(tctx, when): """Test that we properly kill flows if instructed to do so""" server = Placeholder(Server) connect_flow = Placeholder(HTTPFlow) flow = Placeholder(HTTPFlow) def kill(flow: HTTPFlow): # Can't use flow.kill() here because that currently still depends on a reply object. flow.error = Error(Error.KILLED_MESSAGE) def assert_kill(err_hook: bool = True): playbook >> reply(side_effect=kill) if err_hook: playbook << http.HttpErrorHook(flow) playbook >> reply() playbook << CloseConnection(tctx.client) assert playbook playbook = Playbook(http.HttpLayer(tctx, HTTPMode.regular)) assert (playbook >> DataReceived( tctx.client, b"CONNECT example.com:80 HTTP/1.1\r\n\r\n") << http.HttpConnectHook(connect_flow)) if when == "http_connect": return assert_kill(False) assert ( playbook >> reply() << SendData( tctx.client, b'HTTP/1.1 200 Connection established\r\n\r\n') >> DataReceived( tctx.client, b"GET /foo?hello=1 HTTP/1.1\r\nHost: example.com\r\n\r\n") << layer.NextLayerHook(Placeholder()) >> reply_next_layer(lambda ctx: http.HttpLayer(ctx, HTTPMode.transparent)) << http.HttpRequestHeadersHook(flow)) if when == "requestheaders": return assert_kill() assert (playbook >> reply() << http.HttpRequestHook(flow)) if when == "request": return assert_kill() if when == "script-response-responseheaders": assert (playbook >> reply( side_effect=lambda f: setattr(f, "response", HTTPResponse.make())) << http.HttpResponseHeadersHook(flow)) return assert_kill() assert ( playbook >> reply() << OpenConnection(server) >> reply(None) << SendData( server, b"GET /foo?hello=1 HTTP/1.1\r\nHost: example.com\r\n\r\n") >> DataReceived( server, b"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World") << http.HttpResponseHeadersHook(flow)) if when == "responseheaders": return assert_kill() if when == "response": assert (playbook >> reply() >> DataReceived(server, b"!") << http.HttpResponseHook(flow)) return assert_kill(False) elif when == "error": assert (playbook >> reply() >> ConnectionClosed(server) << CloseConnection(server) << http.HttpErrorHook(flow)) return assert_kill(False) else: raise AssertionError
def request(self, flow: HTTPFlow): if self.inServersList( flow.request.host) and flow.request.path.startswith( "/gacha/tenAdvancedGacha"): respData = { "gachaResultList": [], "playerDataDelta": { "deleted": {}, "modified": {} }, "result": 0 } self.info("十连中...") charlist = self.getTen() for charId, rarity in charlist: gacha = {} gacha["isNew"] = 0 gacha["charId"] = charId cdata = self.tBuilder.getCharData(charId) if cdata == None: continue gacha["charInstId"] = cdata["instId"] if rarity == "5": gacha["itemGet"] = [{ "count": 15, "id": "4004", "type": "HGG_SHD" }, { "count": 1, "id": "p_" + charId, "type": "MATERIAL" }] if rarity == "4": gacha["itemGet"] = [{ "count": 8, "id": "4004", "type": "HGG_SHD" }, { "count": 1, "id": "p_" + charId, "type": "MATERIAL" }] if rarity == "3": gacha["itemGet"] = [{ "count": 30, "id": "4005", "type": "LGG_SHD" }, { "count": 1, "id": "p_" + charId, "type": "MATERIAL" }] if rarity == "2": gacha["itemGet"] = [{ "count": 5, "id": "4005", "type": "LGG_SHD" }, { "count": 1, "id": "p_" + charId, "type": "MATERIAL" }] respData["gachaResultList"].append(gacha) flow.response = HTTPResponse.make( 200, json.dumps(respData), {"Content-Type": "application/json; charset=utf-8"}) self.info("完成") if self.inServersList( flow.request.host) and flow.request.path.startswith( "/gacha/advancedGacha"): respData = { "charGet": {}, "playerDataDelta": { "deleted": {}, "modified": {} }, "result": 0 } self.info("单抽中...") charId, rarity = self.getOne() gacha = {} gacha["isNew"] = 0 gacha["charId"] = charId cdata = self.tBuilder.getCharData(charId) gacha["charInstId"] = cdata["instId"] if rarity == "5": gacha["itemGet"] = [{ "count": 15, "id": "4004", "type": "HGG_SHD" }, { "count": 1, "id": "p_" + charId, "type": "MATERIAL" }] if rarity == "4": gacha["itemGet"] = [{ "count": 8, "id": "4004", "type": "HGG_SHD" }, { "count": 1, "id": "p_" + charId, "type": "MATERIAL" }] if rarity == "3": gacha["itemGet"] = [{ "count": 30, "id": "4005", "type": "LGG_SHD" }, { "count": 1, "id": "p_" + charId, "type": "MATERIAL" }] if rarity == "2": gacha["itemGet"] = [{ "count": 5, "id": "4005", "type": "LGG_SHD" }, { "count": 1, "id": "p_" + charId, "type": "MATERIAL" }] respData["charGet"] = gacha flow.response = HTTPResponse.make( 200, json.dumps(respData), {"Content-Type": "application/json; charset=utf-8"}) self.info("完成")
def request(self, flow: HTTPFlow): """The full HTTP request has been read.""" client_ip = flow.client_conn.ip_address[0].split(':')[-1] url = urlparse(flow.request.url) base_url = "%s://%s" % (url.scheme, url.netloc) data = analyze_page(str(base_url)) if data: score = {text.replace('\\', ''): score for text, score in data if text} existing_json = {} with open('files/words.json', 'r') as f: try: existing_json = json.load(f) except ValueError: existing_json = {} with open('files/words.json', 'w') as f: for text, val in score.items(): if text in existing_json: existing_json[text] = (existing_json[text] + val) // 2 else: existing_json[text] = val json.dump(existing_json, f) base_url = "%s://%s" % (url.scheme, url.netloc) json_data = None with open(FILE_WEBSITE_VISITED, "r") as f: json_data = json.load(f) if json_data is not None: with open(FILE_WEBSITE_VISITED, "w") as f: if client_ip not in json_data: json_data[client_ip] = [] if base_url not in json_data[client_ip]: json_data[client_ip].append(base_url) json.dump(json_data, f) with open(FILE_WHITELIST) as f: white_list = [line.strip() for line in f.readlines()] if white_list: if base_url not in white_list: flow.response = HTTPResponse.make( 200, b"You are not permitted to view this website - %s" % bytes(flow.request.pretty_url, "utf8"), {"Content-Type": "text/html"} ) with open(FILE_BLACKLIST) as f: if not white_list: black_list = [line.strip() for line in f.readlines()] if black_list: if base_url in black_list: flow.response = HTTPResponse.make( 200, b"You are not permitted to view this website - %s" % bytes(flow.request.pretty_url, "utf8"), {"Content-Type": "text/html"} )