Persistent and reliable TCP tunneling based on asyncio.
To illustrate the two differenc modes Client can operate in, we give a detailed example of two conceptually different setups.
Let's suppose you have an application server listening on host
srv:6789, you have two servers host1 and host2 and a client
workstation cli. Let's suppose we have the following setup:
cli ---> host1 ---> host2 ---> srv
The arrow a ---> b indicates that a can connect to b, but
b can not connect to a.
In this case you start a tunnel server on host2 that listens on port 9000.
Server('0.0.0.0', 9000)You also strart a tunnel client
on host1 in CONNECT mode with the following parameters
Client(
aiowstunnel.CONNECT, # you need connect mode here
'host2', 9000, # the tunnel server is listening on port 9000
'0.0.0.0', 5678, # the listening host/port
'srv', 6789, # the connectiong host/port
)In this case, the parameters mean the following:
server_mode- This was set to
aiowstunnel.CONNECT, which means the client wants the server to use theconnect_host,connect_portsettings when a new connection is received by the client and connect to the given host-port. tunnel_host,tunnel_port- It tells the Client where the tunnel server is listening. The client will connect to this server and tries to keep the connection open.
listen_host,listen_port- The
server_modeparameter isCONNECT, so the server is going to use theconnect_hostandconnect_portparameters and the client will listen on this host/port. In this example the client is running onhost1and it will start a new server on0.0.0.0:5678. The program running onclican connect to this server as if it was the application server connect_host,connect_port- As described earlier in
CONNECTmode the server will use these to connect when a connection comes to the client. The client tells the server to connect tosrv:6789-- the application server.
What if the firewall is configured in this way:
cli ---> host1 <--- host2 ---> srv
In this case the tunnel server will be started on host1, the
client on host2. The server needs to listen 0.0.0.0:5678 while
the client connects to the application server.
Server('0.0.0.0', 9000)Client(
aiowstunnel.LISTEN, # you need the server to listen
'host1', 9000, # the tunnel server is listening on port 9000
'0.0.0.0', 5678, # the server listens here
'srv', 6789, # the client connects here
)Here is the code to properly start the server in the above example
import asyncio
import signal
import logging
from aiowstunnel.server import Server
logging.basicConfig(level=logging.INFO)
async def serve(stop):
srv = Server('0.0.0.0', 9000)
srv.start()
await stop
await srv.close()
loop = asyncio.get_event_loop()
# install signal handler
stop = asyncio.Future()
loop.add_signal_handler(signal.SIGINT, stop.set_result, None)
loop.run_until_complete(serve(stop))Starting the client is very similar
import asyncio
import logging
import signal
from aiowstunnel.client import Client
import aiowstunnel
logging.basicConfig(level=logging.INFO)
async def provide_tunnel(stop):
cli = Client(
aiowstunnel.LISTEN, # you need the server to listen
'host1', 9000, # the tunnel server is listening on port 9000
'0.0.0.0', 5678, # the server listens here
'srv', 6789, # the client connects here
)
cli.start()
await stop
await cli.close()
loop = asyncio.get_event_loop()
# install signal handler
stop = asyncio.Future()
loop.add_signal_handler(signal.SIGINT, stop.set_result, None)
loop.run_until_complete(provide_tunnel(stop))TODO