Last active
November 2, 2022 11:21
-
-
Save rany2/07562f62c97350fb08ccd6c0f8771724 to your computer and use it in GitHub Desktop.
Start mosh-server, but first create a port redirection in the NAT router (with UPnP) and delete that redirection again just before mosh-server exits.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# Start mosh-server, but first create a port redirection in the NAT | |
# router (with UPnP) and delete that redirection again just before | |
# mosh-server exits. | |
# die -- print error on stderr and exit | |
function die { | |
echo "$@" >&2 | |
exit 1 | |
} | |
declare -i port=0 n | |
# Check if we have been given a port via the -p option. | |
# | |
for ((n = 1; n <= "$#"; n++)); do | |
if [[ "${!n}" = "-p" ]]; then | |
n=$((n + 1)) | |
port="${!n}" | |
fi | |
done | |
# If we don't have a valid port yet, find one that is not in | |
# use. Check that there is no server on this machine listening on the | |
# port and that it is not already redirected on the NAT box. | |
# | |
if [[ "${port}" -ne 0 ]]; then | |
fixed_port=true | |
else | |
for ((port = 61000; port > 0; port--)); do | |
ss_output=$(ss -4 -l -n -u) || die "Error: Calling ss failed." | |
if ! printf '%s\n' "${ss_output}" | grep -E -q '^[^ ]* * [^ ]* * [^ ]* * (([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5]):'"${port} "; then | |
upnpc_output=$(upnpc -l) || die "Error: Calling upnpc failed." | |
if ! printf '%s\n' "${upnpc_output}" | grep -E -q "^ *[0-9]+ UDP ${port}->"; then | |
break # Found one! | |
fi | |
fi | |
done | |
fi | |
# If we still don't have a port, we're in trouble | |
# | |
[[ "${port}" -ne 0 ]] || die "Error: Could not find a free port!?" | |
# Redirect the port in the NAT router | |
# | |
upnpc -e "mosh-server" -r "${port}" udp >/dev/null || | |
echo "Failed to redirect port ${port}. Continuing anyway..." >&2 | |
# Make a program that executes a shell, removes the port direction | |
# when the shell exits, and finally removes itself. | |
# | |
UPNP_SHELL=$(mktemp) || die "Error: Cannot create temporary file." | |
cat >"${UPNP_SHELL}" <<-EOF | |
#!/usr/bin/env bash | |
trap 'rm -f -- "${UPNP_SHELL}"' EXIT | |
ret=1 | |
if command -v getent &> /dev/null; then | |
"\$(getent passwd "${USER}" | awk -F: '{print \$NF}')" | |
ret=\$? | |
elif command -v perl &> /dev/null; then | |
"\$(perl -e '@x=getpwuid(\$<); print \$x[8]')" | |
ret=\$? | |
elif command -v python3 &> /dev/null; then | |
"\$(python3 -c 'import pwd, os; print(pwd.getpwuid(os.getuid())[6])')" | |
ret=\$? | |
elif command -v python2 &> /dev/null; then | |
"\$(python2 -c 'import pwd, os; print(pwd.getpwuid(os.getuid())[6])')" | |
ret=\$? | |
elif command -v python &> /dev/null; then | |
"\$(python -c 'import pwd, os; print(pwd.getpwuid(os.getuid())[6])')" | |
ret=\$? | |
else | |
"\$(grep -E "^${USER}:" /etc/passwd | cut -d: -f7)" | |
ret=\$? | |
fi | |
upnpc -d "${port}" udp >/dev/null | |
exit "\${ret}" | |
EOF | |
chmod +x "${UPNP_SHELL}" | |
# Start mosh-server | |
# | |
if [[ -n "${fixed_port}" ]]; then | |
exec mosh-server "$@" -- "${UPNP_SHELL}" | |
else | |
exec mosh-server "$@" -p "${port}" -- "${UPNP_SHELL}" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment