Skip to content

Commit 64bd91d

Browse files
committed
Add forward-ports script.
1 parent a482c13 commit 64bd91d

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

bin/forward-ports.sh

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/bin/sh
2+
3+
#
4+
# Adds TCP/UDP port forwarding rules to the pf firewall (MacOS/BSD).
5+
#
6+
# Adds rules for both TCP and UDP in addition to those from /etc/pf.conf.
7+
# Requires an existing rdr-anchor entry in /etc/pf.conf.
8+
# Only adds rules temporarily, without changing any files.
9+
#
10+
# Usage: ./forward-ports.sh [[nic:]port=[ip:]port [...]]
11+
#
12+
# If no network interface is given, forwards from all interfaces.
13+
# If no IP is given, forwards to 127.0.0.1.
14+
# If no port forwarding rule is given, resets to the rules from /etc/pf.conf.
15+
#
16+
# e.g. forwarding ports 80 and 443 on network interface en0 to ports 8080 and
17+
# 8443 on localhost respectively:
18+
# ./forward-ports.sh en0:80=8080 en0:443=8443
19+
#
20+
# Copyright 2019, Sebastian Tschan
21+
# https://blueimp.net
22+
#
23+
# Licensed under the MIT license:
24+
# https://opensource.org/licenses/MIT
25+
#
26+
27+
set -e
28+
29+
RULES=
30+
NEWLINE='
31+
'
32+
33+
print_usage_exit() {
34+
if [ -n "$RULES" ]; then
35+
printf '\nError in custom rules:\n%s\n' "$RULES" >&2
36+
fi
37+
echo "Usage: $0 [[nic:]port=[ip:]port [...]]" >&2
38+
exit 1
39+
}
40+
41+
print_nat_rules() {
42+
echo
43+
echo 'Loaded NAT rules:'
44+
sudo pfctl -s nat 2>/dev/null
45+
echo
46+
}
47+
48+
# Print usage and exit if option arguments like "-h" are used:
49+
if [ "${1#-}" != "$1" ]; then print_usage_exit; fi
50+
51+
while test $# -gt 0; do
52+
# Separate the from=to parts:
53+
from=${1%=*}
54+
to=${1#*=}
55+
# If from part has a nic defined, extract it, else forward from all:
56+
case "$from" in
57+
*:*) nic="on ${from%:*}";;
58+
*) nic=;;
59+
esac
60+
# Extract the port to forward from:
61+
from_port=${from##*:}
62+
# If to part has an IP defined, extract it, else forward to 127.0.0.1:
63+
case "$to" in
64+
*:*) to_ip=${to%:*};;
65+
*) to_ip=127.0.0.1;;
66+
esac
67+
# Extract the port to forward to:
68+
to_port=${to##*:}
69+
# Create the packet filter (pf) forwarding rule for both TCP and UDP:
70+
rule=$(
71+
printf \
72+
'rdr pass %s inet proto %s from any to any port %s -> %s port %s' \
73+
"$nic" '{tcp udp}' "$from_port" "$to_ip" "$to_port"
74+
)
75+
# Add it to the list of rules:
76+
RULES="$RULES$rule$NEWLINE"
77+
shift
78+
done
79+
80+
# Add the rules after the line matching "rdr-anchor" in /etc/pf.conf, print the
81+
# combined rules to STDOUT and load the rules into pf from STDIN.
82+
# Finally, display the loaded NAT rules or print the script usage on failure:
83+
# shellcheck disable=SC2015
84+
printf %s "$RULES" | sed -e '/rdr-anchor/r /dev/stdin' /etc/pf.conf |
85+
sudo pfctl -Ef - 2>/dev/null && print_nat_rules || print_usage_exit

0 commit comments

Comments
 (0)