Last active
August 21, 2023 15:36
-
-
Save vdbsh/cc129c90e978a1ddb222446f68e67080 to your computer and use it in GitHub Desktop.
Maps network ports thru NAT-PMP and refreshes that mapping automatically
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 | |
# natpmprfr.sh: Maps network ports thru NAT-PMP and refreshes that mapping automatically | |
# (https://en.wikipedia.org/wiki/NAT_Port_Mapping_Protocol) | |
# | |
# Useful for applications with poor or without NAT-PMP implementation | |
# (http://miniupnp.free.fr/libnatpmp.html) | |
# | |
# Script can set UFW rules according to mapped/unmapped local ports | |
# (https://help.ubuntu.com/community/UFW) | |
# | |
# Requirements: sudo, natpmpc, ufw (optional) | |
# Tested on Ubuntu 22.04 LTS | |
gateway="192.168.1.1" # mat-pmp gateway | |
private_port="0" # set 0 to obtain from natpmpc | |
protocols="tcp" # "tcp" "udp" "tcp udp" | |
refresh_timeout="40" # seconds | |
port_file="/tmp/nat-pmp_local_port.txt" # leave "" to disable | |
set_ufw_rules=true # requires root permissions | |
map_port() { | |
if [[ "$protocols" == *"tcp"* ]]; then | |
natpmc_out=$(sudo -u nobody natpmpc -g "$gateway" -a 0 "$local_port" tcp 60) | |
local_port=$(echo "$natpmc_out" | grep -Po 'local\sport\s\K\d{0,65535}') | |
public_port=$(echo "$natpmc_out" | grep -Po 'public\sport\s\K\d{0,65535}') | |
echo "π» Local TCP port: $local_port" >/dev/tty | |
echo "π Public TCP port: $public_port" >/dev/tty | |
fi | |
if [[ "$protocols" == *"udp"* ]]; then | |
natpmc_out=$(sudo -u nobody natpmpc -g "$gateway" -a 0 "$local_port" udp 60) | |
local_port=$(echo "$natpmc_out" | grep -Po 'local\sport\s\K\d{0,65535}') | |
public_port=$(echo "$natpmc_out" | grep -Po 'public\sport\s\K\d{0,65535}') | |
echo "π» Local UDP port: $local_port" >/dev/tty | |
echo "π Public UDP port: $public_port" >/dev/tty | |
fi | |
if [ -n "$local_port" ]; then | |
echo "$local_port" | |
fi | |
} | |
ufw_open_port() { | |
if [ "$set_ufw_rules" = true ]; then | |
echo "" | |
echo "𧱠UFW says:" | |
if [ "$local_port" = "0" ]; then | |
ufw allow "$1" | |
else | |
ufw allow "$local_port" | |
fi | |
fi | |
} | |
ufw_close_port() { | |
if [ "$set_ufw_rules" = true ]; then | |
echo "" | |
echo "𧱠UFW says:" | |
if [ "$local_port" = "0" ]; then | |
ufw delete allow "$1" | |
else | |
ufw delete allow "$local_port" | |
fi | |
fi | |
} | |
write_port_to_file() { | |
if [ -n "$port_file" ]; then | |
echo "$1" | sudo -u nobody tee "$port_file" 1>/dev/null | |
fi | |
} | |
unmap_ports() { | |
echo "" | |
echo "π Unmapping port(s)..." | |
if [ -n "$cached_local_port" ]; then | |
if [[ "$protocols" == *"tcp"* ]]; then | |
sudo -u nobody natpmpc -g "$gateway" -a "$cached_local_port" "$local_port" tcp 0 1>/dev/null | |
fi | |
if [[ "$protocols" == *"udp"* ]]; then | |
sudo -u nobody natpmpc -g "$gateway" -a "$cached_local_port" "$local_port" udp 0 1>/dev/null | |
fi | |
ufw_close_port "$cached_local_port" | |
fi | |
} | |
terminate() { | |
unmap_ports | |
rm -f "$port_file" | |
exit | |
} | |
if [ "$set_ufw_rules" = true ]; then | |
if [ "$EUID" -ne 0 ]; then | |
echo "Please run as root" | |
exit | |
fi | |
fi | |
trap terminate SIGINT SIGTERM SIGQUIT SIGABRT | |
echo "π Getting info..." | |
if sudo -u nobody natpmpc -g "$gateway"; then | |
while true; do | |
echo "" | |
echo "π Mapping ${protocols^^} port(s)..." | |
local_port=$(map_port) | |
if [ -n "$local_port" ]; then | |
ufw_open_port "$local_port" | |
write_port_to_file "$local_port" | |
cached_local_port="$local_port" | |
else | |
echo "" | |
echo "π’ Something went wrong..." | |
if [ -n "$cached_local_port" ]; then | |
unmap_ports | |
cached_local_port="" | |
rm -f "$port_file" | |
fi | |
fi | |
echo "" | |
echo "π Refreshing ($(date))..." | |
sleep "$refresh_timeout" | |
done | |
else | |
exit | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment