udp-holepunch - Python script for UDP holepunching using a webserver. With an example of SSH using this and sctp-echo.

git clone https://benconnors.ca/git-repos/udp-holepunch

About | Log | Files | Refs

ssh_holepunch_client.py (2657B) - raw


      1 #!/usr/bin/env python3
      2 
      3 import argparse as ap
      4 import subprocess as subp
      5 import sys
      6 
      7 from udp_holepunch import udp_holepunch_client
      8 
      9 if __name__ == "__main__":
     10     parser = ap.ArgumentParser(
     11         description="Run SSH through UDP with holepunching (client)"
     12     )
     13 
     14     parser.add_argument(
     15         "-l", "--local-port", 
     16         type=int, 
     17         default=0, 
     18         help="Fixed internal UDP port for us to use (defaults to 0 = auto-assigned by system)"
     19     )
     20     parser.add_argument(
     21         "-p", "--server-port", 
     22         type=int, 
     23         default=0,
     24         help="Fixed UDP port to use to start holepunching (defaults to 0 to use our external UDP port number)"
     25     )
     26     parser.add_argument(
     27         "-s", "--skip-ack",
     28         action="store_true",
     29         default=False,
     30         help="Skip hello packet acknowledgement to finalize holepunching (a couple of the first packets down the line may get lost)",
     31     )
     32     parser.add_argument(
     33         "-e", "--sctp-echo",
     34         default="sctp_echo",
     35         help="Path to invoke sctp_echo"
     36     )
     37     parser.add_argument(
     38         "-k", "--signing-key",
     39         type=str,
     40         default=None,
     41         help="Path to the SSH key used to sign postings on the webserver (can be different from the login key"
     42     )
     43     parser.add_argument(
     44         "--ack-timeout",
     45         type=int,
     46         default=60,
     47         help="Timeout when waiting for holepunching to be established",
     48     )
     49 
     50     parser.add_argument(
     51         "server_name", 
     52         help="Name of the intermediate server (for SSH)"
     53     )
     54     parser.add_argument(
     55         "server_path", 
     56         help="Path of file to write on the intermediate server (e.g. /var/www/inter)"
     57     )
     58     parser.add_argument(
     59         "ssh_name",
     60         help="Name of SSH server to connect to (%%h if in ProxyCommand)",
     61     )
     62 
     63     args = parser.parse_args()
     64 
     65     ## 1. Holepunch
     66     local_port, remote_ip, remote_port = udp_holepunch_client(
     67         args.local_port,
     68         args.server_name, 
     69         args.server_port,
     70         args.server_path,
     71         no_ack=args.skip_ack,
     72         key_path=args.signing_key,
     73         timeout=args.ack_timeout,
     74     )
     75 
     76     ## 2. Run the client
     77     client = subp.Popen(
     78         [
     79             args.sctp_echo, 
     80             "-c",
     81             "0.0.0.0", ## Local IP
     82             str(local_port), ## Local UDP
     83             str(local_port), ## Local SCTP = UDP
     84             remote_ip, ## Remote IP
     85             str(remote_port), ## Remote UDP port
     86             str(remote_port), ## Remote SCTP port = UDP
     87         ],
     88         stdout=sys.stdout.buffer.raw, ## Must use raw or e.g. vi will crash it
     89         stdin=sys.stdin.buffer.raw,
     90     )
     91     client.wait()