Skip to content

Instantly share code, notes, and snippets.

@tedpearson
Last active May 16, 2024 23:09
Show Gist options
  • Save tedpearson/e1b3319b93e3cb2f96d76d9c87f3aa65 to your computer and use it in GitHub Desktop.
Save tedpearson/e1b3319b93e3cb2f96d76d9c87f3aa65 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# Super simple script that listens to a local UDP port and relays all packets to an arbitrary remote host.
# Packets that the host sends back will also be relayed to the local UDP client.
# Works with Python 2 and 3
import ipaddress
import socket
import sys
# Whether or not to print the IP address and port of each packet received
debug = False
def fail(reason):
sys.stderr.write(reason + '\n')
sys.exit(1)
def addressMatches(a, b: (str, str, str, str)) -> bool:
# convert embedded ipv4 to ipv4
ip_a = ipaddress.ip_address(a[0])
ip_b = ipaddress.ip_address(b[0])
if ip_a.version == 6 and ip_a.ipv4_mapped is not None:
ip_a = ip_a.ipv4_mapped
if ip_b.version == 6 and ip_b.ipv4_mapped is not None:
ip_b = ip_b.ipv4_mapped
return ip_a == ip_b
if len(sys.argv) != 4:
fail('Usage: udp-relay.py localPort remoteHost remotePort')
localPort, remoteHost, remotePort = sys.argv[1], sys.argv[2], sys.argv[3]
try:
localPort = int(localPort)
except:
fail('Invalid port number: ' + str(localPort))
try:
remotePort = int(remotePort)
except:
fail('Invalid port number: ' + str(remotePort))
try:
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.bind(('::', localPort))
except:
fail('Failed to bind on port ' + str(localPort))
knownClient = None
knownServer = (remoteHost, remotePort, 0, 0)
print("known server: " + str(knownServer))
sys.stdout.write('All set, listening on ' + str(localPort) + '.\n')
while True:
data, addr = s.recvfrom(32768)
if knownClient is None or not addressMatches(addr, knownServer):
if debug:
print("")
knownClient = addr
if debug:
print("Packet received from " + str(addr))
if addr == knownClient:
if debug:
print("\tforwarding to " + str(knownServer))
s.sendto(data, knownServer)
else:
if debug:
print("\tforwarding to " + str(knownClient))
s.sendto(data, knownClient)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment