Skip to content

Instantly share code, notes, and snippets.

@acheong08
Last active July 12, 2024 07:12
Show Gist options
  • Save acheong08/40032a4da5c77b7b32b94c16ba25c422 to your computer and use it in GitHub Desktop.
Save acheong08/40032a4da5c77b7b32b94c16ba25c422 to your computer and use it in GitHub Desktop.
Port forwarding utility
#!/bin/bash
# Default protocol is tcp
PROTOCOL="tcp"
# Use wireguard as default
INTERFACE="wg0"
# Config file path
CONFIG_FILE="${HOME}/.config/portfwd/config"
# Usage function to display help
usage() {
echo "Usage: $0 [--udp|--tcp] [--list|--delete|--refresh] [--interface <network-interface>] --source <source-port> --dest <destination-ip:port>"
echo "Example (TCP): $0 --source 80 --dest 172.20.10.2:80"
echo "Example (UDP): $0 --udp --source 53 --dest 172.20.10.2:53"
echo "Example (Delete): $0 --delete --source 80 --dest 172.20.10.2:80"
echo "Example (List): $0 --list"
echo "Example (Refresh): $0 --refresh"
exit 1
}
# Function to list current forwarding rules
list_rules() {
echo "Current forwarding rules:"
iptables -t nat -L PREROUTING --line-numbers -n
iptables -L FORWARD --line-numbers -n
iptables -t nat -L POSTROUTING --line-numbers -n
}
# Function to delete a forwarding rule
delete_rule() {
# Enable IP Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
# Delete PREROUTING rule
iptables -t nat -D PREROUTING "${PREROUTING_RULE}"
# Delete FORWARD rule
iptables -D FORWARD "${FORWARD_RULE}"
# Delete POSTROUTING rule
iptables -t nat -D POSTROUTING "${POSTROUTING_RULE}"
echo "Port forwarding rule deleted from *:${SOURCE_PORT} to ${DEST_IP}:${DEST_PORT} over ${PROTOCOL}"
# Remove rule from config file
sed -i "/^${PROTOCOL}:${SOURCE_PORT}:${DEST_IP}:${DEST_PORT}$/d" "${CONFIG_FILE}"
}
# Function to refresh rules from config file
refresh_rules() {
# Clear existing rules
iptables -t nat -F PREROUTING
iptables -F FORWARD
iptables -t nat -F POSTROUTING
# Enable IP Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
# Read rules from config file and apply them
while IFS=':' read -r PROTOCOL SOURCE_PORT DEST_IP DEST_PORT; do
iptables -t nat -A PREROUTING -p "${PROTOCOL}" --dport "${SOURCE_PORT}" -j DNAT --to-destination "${DEST_IP}:${DEST_PORT}"
iptables -A FORWARD -p "${PROTOCOL}" -d "${DEST_IP}" --dport "${DEST_PORT}" -j ACCEPT
iptables -t nat -A POSTROUTING -o "${INTERFACE}" -p "${PROTOCOL}" --dport "${DEST_PORT}" -d "${DEST_IP}" -j MASQUERADE
echo "Port forwarding rule reloaded from *:${SOURCE_PORT} to ${DEST_IP}:${DEST_PORT} over ${PROTOCOL}"
done < "${CONFIG_FILE}"
}
# Parse arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
--udp) PROTOCOL="udp" ;;
--tcp) PROTOCOL="tcp" ;;
--list) list_rules; exit 0 ;;
--delete) DELETE=true ;;
--refresh) refresh_rules; exit 0 ;;
--source) SOURCE_PORT="$2"; shift ;;
--interface) INTERFACE="$2"; shift ;;
--dest) IFS=":" read -r DEST_IP DEST_PORT <<< "$2"; shift ;;
*) usage ;;
esac
shift
done
# Check if both ports are specified
if [ -z "${SOURCE_PORT}" ] || [ -z "${DEST_IP}" ] || [ -z "${DEST_PORT}" ]; then
usage
fi
# Check if delete option is specified
if [ "${DELETE}" = true ]; then
# Fetch existing rule line numbers
PREROUTING_RULE=$(iptables -t nat -L PREROUTING --line-numbers -n | awk "\$4==\"${PROTOCOL}\" && \$5==\"dpt:${SOURCE_PORT}\" && \$9==\"dnat\" && \$10==\"to:${DEST_IP}:${DEST_PORT}\" {print \$1}")
FORWARD_RULE=$(iptables -L FORWARD --line-numbers -n | awk "\$4==\"${PROTOCOL}\" && \$5==\"dpt:${DEST_PORT}\" && \$6==\"dst=${DEST_IP}\" {print \$1}")
POSTROUTING_RULE=$(iptables -t nat -L POSTROUTING --line-numbers -n | awk "\$4==\"${PROTOCOL}\" && \$5==\"dpt:${DEST_PORT}\" && \$7==\"dst=${DEST_IP}\" {print \$1}")
# Check if rules exist
if [ -z "${PREROUTING_RULE}" ] || [ -z "${FORWARD_RULE}" ] || [ -z "${POSTROUTING_RULE}" ]; then
echo "No forwarding rule found for *:${SOURCE_PORT} to ${DEST_IP}:${DEST_PORT} over ${PROTOCOL}"
exit 1
fi
delete_rule
exit 0
fi
# Enable IP Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
# Set up NAT PREROUTING
iptables -t nat -A PREROUTING -p "${PROTOCOL}" --dport "${SOURCE_PORT}" -j DNAT --to-destination "${DEST_IP}:${DEST_PORT}"
# Set up forwarding rule
iptables -A FORWARD -p "${PROTOCOL}" -d "${DEST_IP}" --dport "${DEST_PORT}" -j ACCEPT
# Set up NAT POSTROUTING
iptables -t nat -A POSTROUTING -o "${INTERFACE}" -p "${PROTOCOL}" --dport "${DEST_PORT}" -d "${DEST_IP}" -j MASQUERADE
echo "Port forwarding set up from *:${SOURCE_PORT} to ${DEST_IP}:${DEST_PORT} over ${PROTOCOL}"
# Save rule to config file
mkdir -p "$(dirname "${CONFIG_FILE}")"
echo "${PROTOCOL}:${SOURCE_PORT}:${DEST_IP}:${DEST_PORT}" >> "${CONFIG_FILE}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment