Wrap it in a CLI
This commit is contained in:
parent
907d9d1a78
commit
53bab3aafd
3 changed files with 44 additions and 10 deletions
|
@ -4,5 +4,5 @@ set -e
|
|||
|
||||
black --check tcp_nat_proxy.py
|
||||
isort -c tcp_nat_proxy.py
|
||||
flake8 tcp_nat_proxy.py
|
||||
flake8 tcp_nat_proxy.py --ignore=E128,E501
|
||||
mypy --strict-optional --ignore-missing-imports tcp_nat_proxy.py
|
||||
|
|
6
setup.cfg
Normal file
6
setup.cfg
Normal file
|
@ -0,0 +1,6 @@
|
|||
[isort]
|
||||
multi_line_output=3
|
||||
include_trailing_comma=True
|
||||
force_grid_wrap=0
|
||||
use_parentheses=True
|
||||
line_length=88
|
|
@ -1,12 +1,24 @@
|
|||
import argparse
|
||||
import asyncio
|
||||
from collections import namedtuple
|
||||
|
||||
import uvloop
|
||||
|
||||
Route = namedtuple("Route", ["listen_port", "destination_host", "destination_port"])
|
||||
|
||||
uvloop.install()
|
||||
|
||||
BUFFER_SIZE = 4096
|
||||
|
||||
|
||||
def destination_host_display(route: Route):
|
||||
return "{}:{}".format(route.destination_host, route.destination_port)
|
||||
|
||||
|
||||
def parse_argument(value):
|
||||
return Route(*value.split(":"))
|
||||
|
||||
|
||||
async def pipe(reader, writer):
|
||||
try:
|
||||
while not reader.at_eof():
|
||||
|
@ -15,26 +27,42 @@ async def pipe(reader, writer):
|
|||
writer.close()
|
||||
|
||||
|
||||
async def create_proxy_pipe(listen_port, destination_host, destination_port):
|
||||
async def create_proxy_pipe(route: Route):
|
||||
async def handle_client(local_reader, local_writer):
|
||||
try:
|
||||
remote_reader, remote_writer = await asyncio.open_connection(
|
||||
destination_host, destination_port
|
||||
route.destination_host, route.destination_port
|
||||
)
|
||||
pipe1 = pipe(local_reader, remote_writer)
|
||||
pipe2 = pipe(remote_reader, local_writer)
|
||||
await asyncio.gather(pipe1, pipe2)
|
||||
await asyncio.gather(
|
||||
pipe(local_reader, remote_writer), pipe(remote_reader, local_writer)
|
||||
)
|
||||
except ConnectionRefusedError:
|
||||
print("Connection to {} refused".format(destination_host_display(route)))
|
||||
pass
|
||||
finally:
|
||||
local_writer.close()
|
||||
|
||||
server = await asyncio.start_server(handle_client, "0.0.0.0", listen_port)
|
||||
print("Serving on {}".format(server.sockets[0].getsockname()))
|
||||
server = await asyncio.start_server(handle_client, "0.0.0.0", route.listen_port)
|
||||
print(
|
||||
"Routing from {} to {}".format(
|
||||
route.listen_port, destination_host_display(route)
|
||||
)
|
||||
)
|
||||
await server.wait_closed()
|
||||
|
||||
|
||||
async def main():
|
||||
await asyncio.gather(create_proxy_pipe(8888, "127.0.0.1", 8889))
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"-R", "--route", action="append", required=True, type=parse_argument
|
||||
)
|
||||
args = parser.parse_args()
|
||||
servers = [create_proxy_pipe(route) for route in args.route]
|
||||
await asyncio.gather(*servers)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
try:
|
||||
asyncio.run(main())
|
||||
except KeyboardInterrupt:
|
||||
print("Process terminated")
|
||||
|
|
Reference in a new issue