Last active
August 22, 2024 21:43
-
-
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 hidden or 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) | |
| # | |
| # 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 | |
| local_port="0" # set to 0 to obtain from natpmpc | |
| protocols="tcp" # "tcp" "udp" "tcp udp" | |
| refresh_timeout="40" # seconds | |
| port_file="/tmp/nat-pmp_local_port.txt" # set to "" 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