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

commit 98624cf9da2804b27566a38c51dbf840c76faad5
parent 1357791f0307bb465ff8bdb4e7562c6eecbc870f
Author: Ben Connors <benconnors@outlook.com>
Date:   Fri, 11 Sep 2026 00:07:59 -0400

Add timestamp to signature

Diffstat:
Mudp_holepunch.py | 17+++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/udp_holepunch.py b/udp_holepunch.py @@ -3,6 +3,7 @@ import argparse as ap import base64 as b64 import os +import datetime as dt import socket as s import subprocess as subp import sys @@ -12,6 +13,9 @@ import threading import requests as r +def utcnow(): + return dt.datetime.now(dt.timezone.utc).timestamp() + def ssh_sign(message, key_path, namespace="udp-holepunch"): """Sign a message using ssh-keygen.""" return subp.check_output(["ssh-keygen", "-f", key_path, "-Y", "sign", "-n", namespace], input=message, text=True, stderr=subp.DEVNULL) @@ -109,7 +113,7 @@ def udp_holepunch_loop(sock, other_addr, no_ack=False, timeout=60): return True -def udp_holepunch_server(local_port, server_port, server_path, no_ack=False, allowed_keys=None, timeout=60): +def udp_holepunch_server(local_port, server_port, server_path, no_ack=False, allowed_keys=None, timeout=60, sig_valid=60*10): """Serve as the UDP holepunching "server". Poll the given `server_path`; if a message is found from `udp_holepunch_client`, begin the @@ -138,6 +142,15 @@ def udp_holepunch_server(local_port, server_port, server_path, no_ack=False, all ## Invalid signature raise Exception("Invalid signature on the webserver") + if ',' not in info: + raise Exception("Missing time on the webserver") + + info, other_time = info.split(',') + other_time = float(other_time) + + if abs(utcnow() - other_time) > sig_valid: + raise Exception("Signature expired on webserver") + other_ip, other_port = info.split(':') break @@ -266,7 +279,7 @@ rm {server_path} proc.stdout.readline() ## 4. Write our information to the poll file - info_string = "%s:%s" % (external_ip, external_port) + info_string = "%s:%s,%d" % (external_ip, external_port, utcnow()) if key_path is not None: ## Add a signature sig = ssh_sign(info_string, key_path)