Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http proxy server: don't work as an actual proxy #49

Merged
merged 5 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clean-up.logs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Wed Jan 17 16:42:05 UTC 2024
Fri Jan 19 13:37:48 UTC 2024
[X] honeypots
[X] installing python3, python3-pip, autopep8 & jq
[X] installing the pip package
Expand Down
Empty file added honeypots/data/__init__.py
Empty file.
15 changes: 15 additions & 0 deletions honeypots/data/dummy_page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<title>Example Website</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div>
<h1>Example Website</h1>
<p>This website is for use in dummy HTML responses. You may use this
document without prior coordination or asking for permission.</p>
</div>
</body>
</html>
49 changes: 26 additions & 23 deletions honeypots/http_proxy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
// contributors list qeeqbox/honeypots/graphs/contributors
// -------------------------------------------------------------
'''

from pathlib import Path
from warnings import filterwarnings

filterwarnings(action='ignore', module='.*OpenSSL.*')

from dns.resolver import query as dsnquery
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, ClientFactory, Factory
from twisted.internet.protocol import Protocol, Factory
from twisted.python import log as tlog
from subprocess import Popen
from email.parser import BytesParser
Expand All @@ -25,6 +26,9 @@
from contextlib import suppress


DUMMY_TEMPLATE = (Path(__file__).parent / "data" / "dummy_page.html").read_text()


class QHTTPProxyServer():
def __init__(self, **kwargs):
self.auto_disabled = None
Expand Down Expand Up @@ -62,31 +66,20 @@ def resolve_domain(self, request_string):

def dataReceived(self, data):
_q_s.logs.info({'server': 'http_proxy_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port})
with suppress(Exception):
ip = self.resolve_domain(data)
if ip:
factory = ClientFactory()
factory.CustomProtocolParent_ = self
factory.protocol = CustomProtocolChild
reactor.connectTCP(ip, 80, factory)
else:
self.transport.loseConnection()

if self.client:
self.client.write(data)
else:
self.buffer = data
ip = self.resolve_domain(data)
if ip:
self.write(_create_dummy_response(DUMMY_TEMPLATE))
else:
self.transport.loseConnection()

if self.client:
self.client.write(data)
else:
self.buffer = data

def write(self, data):
self.transport.write(data)

class CustomProtocolChild(Protocol):
def connectionMade(self):
self.write(self.factory.CustomProtocolParent_.buffer)

def dataReceived(self, data):
self.factory.CustomProtocolParent_.write(data)

def write(self, data):
self.transport.write(data)

Expand Down Expand Up @@ -139,6 +132,16 @@ def test_server(self, ip=None, port=None, domain=None):
get(_domain, proxies={'http': 'http://{}:{}'.format(_ip, _port)}).text.encode('ascii', 'ignore')


def _create_dummy_response(content: str) -> bytes:
response = [
"HTTP/1.1 200 OK",
f"Content-Length: {len(content)}",
"",
f"{content}",
]
return "\r\n".join(response).encode()


if __name__ == '__main__':
parsed = server_arguments()
if parsed.docker or parsed.aws or parsed.custom:
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
license="AGPL-3.0",
license_files=("LICENSE"),
url="https://github.com/qeeqbox/honeypots",
packages=["honeypots"],
packages=["honeypots", "honeypots.data"],
entry_points={"console_scripts": ["honeypots=honeypots.__main__:main_logic"]},
include_package_data=True,
package_data={"honeypots.data": ["*.html"]},
install_requires=[
"twisted==21.7.0",
"psutil==5.9.0",
Expand Down
5 changes: 4 additions & 1 deletion tests/test_http_proxy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
def test_http_proxy_server(server_logs):
sleep(1) # give the server some time to start

response = requests.get("http://example.com/", proxies={"http": f"http://{IP}:{PORT}"})
response = requests.get("http://example.com/", proxies={"http": f"http://{IP}:{PORT}"}, timeout=2)

sleep(1) # give the server process some time to write logs

Expand All @@ -42,3 +42,6 @@ def test_http_proxy_server(server_logs):

assert query["data"] == "example.com"
assert query["action"] == "query"

assert response.ok
assert "Example Website" in response.text, "dummy response is missing"
2 changes: 2 additions & 0 deletions tests/test_telnet_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
indirect=True,
)
def test_telnet_server(server_logs):
sleep(1) # give the server some time to start

telnet_client = Telnet(IP, int(PORT))
telnet_client.read_until(b"login: ")
telnet_client.write(USERNAME.encode() + b"\n")
Expand Down