Created
August 20, 2021 13:23
-
-
Save tardyp/f95c67de3f54614a453a745b78e4b116 to your computer and use it in GitHub Desktop.
a simple CONNECT http proxy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SPDX-License-Identifier: MIT | |
import asyncio | |
import socket | |
async def pipe(reader, writer): | |
try: | |
while not reader.at_eof(): | |
writer.write(await reader.read(2048)) | |
except ConnectionResetError: | |
pass | |
finally: | |
writer.close() | |
def write_response(writer, resp): | |
writer.write( | |
"\r\n".join( | |
[ | |
resp, | |
"", | |
"", | |
] | |
).encode() | |
) | |
async def handle_client(local_reader, local_writer): | |
try: | |
request = await local_reader.read(2048) | |
lines = request.split(b"\r\n") | |
if not lines[0].startswith(b"CONNECT "): | |
print("bad request", request.decode()) | |
write_response(local_writer, "HTTP/1.1 407 Only CONNECT allowed") | |
return | |
host, port = lines[0].split(b" ")[1].split(b":") | |
try: | |
remote_reader, remote_writer = await asyncio.open_connection( | |
host.decode(), int(port) | |
) | |
except socket.gaierror: | |
print("failed to relay to", host, port) | |
write_response(local_writer, "HTTP/1.1 404 Not Found") | |
return | |
print("relaying to", host, port) | |
write_response(local_writer, "HTTP/1.1 200 Connection established") | |
pipe1 = pipe(local_reader, remote_writer) | |
pipe2 = pipe(remote_reader, local_writer) | |
await asyncio.gather(pipe1, pipe2) | |
finally: | |
local_writer.close() | |
loop = asyncio.get_event_loop() | |
coro = asyncio.start_server(handle_client, "127.0.0.1", 1080) | |
server = loop.run_until_complete(coro) | |
print("Serving on {}".format(server.sockets[0].getsockname())) | |
try: | |
loop.run_forever() | |
except KeyboardInterrupt: | |
pass | |
server.close() | |
loop.run_until_complete(server.wait_closed()) | |
loop.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment