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
|
black --check tcp_nat_proxy.py
|
||||||
isort -c 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
|
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
|
import asyncio
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
import uvloop
|
import uvloop
|
||||||
|
|
||||||
|
Route = namedtuple("Route", ["listen_port", "destination_host", "destination_port"])
|
||||||
|
|
||||||
uvloop.install()
|
uvloop.install()
|
||||||
|
|
||||||
BUFFER_SIZE = 4096
|
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):
|
async def pipe(reader, writer):
|
||||||
try:
|
try:
|
||||||
while not reader.at_eof():
|
while not reader.at_eof():
|
||||||
|
@ -15,26 +27,42 @@ async def pipe(reader, writer):
|
||||||
writer.close()
|
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):
|
async def handle_client(local_reader, local_writer):
|
||||||
try:
|
try:
|
||||||
remote_reader, remote_writer = await asyncio.open_connection(
|
remote_reader, remote_writer = await asyncio.open_connection(
|
||||||
destination_host, destination_port
|
route.destination_host, route.destination_port
|
||||||
)
|
)
|
||||||
pipe1 = pipe(local_reader, remote_writer)
|
await asyncio.gather(
|
||||||
pipe2 = pipe(remote_reader, local_writer)
|
pipe(local_reader, remote_writer), pipe(remote_reader, local_writer)
|
||||||
await asyncio.gather(pipe1, pipe2)
|
)
|
||||||
|
except ConnectionRefusedError:
|
||||||
|
print("Connection to {} refused".format(destination_host_display(route)))
|
||||||
|
pass
|
||||||
finally:
|
finally:
|
||||||
local_writer.close()
|
local_writer.close()
|
||||||
|
|
||||||
server = await asyncio.start_server(handle_client, "0.0.0.0", listen_port)
|
server = await asyncio.start_server(handle_client, "0.0.0.0", route.listen_port)
|
||||||
print("Serving on {}".format(server.sockets[0].getsockname()))
|
print(
|
||||||
|
"Routing from {} to {}".format(
|
||||||
|
route.listen_port, destination_host_display(route)
|
||||||
|
)
|
||||||
|
)
|
||||||
await server.wait_closed()
|
await server.wait_closed()
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
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__":
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("Process terminated")
|
||||||
|
|
Reference in a new issue