@@ -6,18 +6,21 @@ set -o errexit
6
6
set -o nounset
7
7
set -o pipefail
8
8
9
+ function die() {
10
+ echo " $* " 1>&2
11
+ exit 1
12
+ }
13
+
9
14
BLANK_LINE_OR_COMMENT_REGEX=" ([[:space:]]*$|#.*)"
10
15
PORT_REGEX=" [[:digit:]]+"
11
16
PROTO_REGEX=" (tcp|udp)"
12
17
IP_REGEX=" [[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+"
13
18
14
19
if [[ ! " ${EGRESS_SOURCE:- } " =~ ^${IP_REGEX} $ ]]; then
15
- echo " EGRESS_SOURCE unspecified or invalid"
16
- exit 1
20
+ die " EGRESS_SOURCE unspecified or invalid"
17
21
fi
18
22
if [[ ! " ${EGRESS_GATEWAY:- } " =~ ^${IP_REGEX} $ ]]; then
19
- echo " EGRESS_GATEWAY unspecified or invalid"
20
- exit 1
23
+ die " EGRESS_GATEWAY unspecified or invalid"
21
24
fi
22
25
23
26
if [[ -n " ${EGRESS_ROUTER_DEBUG:- } " ]]; then
@@ -43,23 +46,30 @@ function setup_network() {
43
46
arping -q -U -c 1 -I macvlan0 " ${EGRESS_SOURCE} " || true ) > /dev/null 2>&1 < /dev/null &
44
47
}
45
48
49
+ function validate_port() {
50
+ local port=$1
51
+ if [[ " ${port} " -lt " 1" || " ${port} " -gt " 65535" ]]; then
52
+ die " Invalid port: ${port} , must be in the range 1 to 65535"
53
+ fi
54
+ }
55
+
46
56
function gen_iptables_rules() {
47
57
if [[ -z " ${EGRESS_DESTINATION:- } " ]]; then
48
- echo " EGRESS_DESTINATION unspecified"
49
- exit 1
58
+ die " EGRESS_DESTINATION unspecified"
50
59
fi
51
60
52
61
did_fallback=
62
+ declare -A used_ports=()
53
63
while read dest; do
54
64
if [[ " ${dest} " =~ ^${BLANK_LINE_OR_COMMENT_REGEX} $ ]]; then
55
65
# comment or blank line
56
66
continue
57
67
fi
58
68
if [[ -n " ${did_fallback} " ]]; then
59
- echo " EGRESS_DESTINATION fallback IP must be the last line" 1>&2
60
- exit 1
69
+ die " EGRESS_DESTINATION fallback IP must be the last line" 1>&2
61
70
fi
62
71
72
+ localport=" "
63
73
if [[ " ${dest} " =~ ^${IP_REGEX} $ ]]; then
64
74
# single IP address: do fallback "all ports to same IP"
65
75
echo -A PREROUTING -i eth0 -j DNAT --to-destination " ${dest} "
@@ -71,14 +81,24 @@ function gen_iptables_rules() {
71
81
72
82
elif [[ " ${dest} " =~ ^${PORT_REGEX} \ +${PROTO_REGEX} \ +${IP_REGEX} \ +${PORT_REGEX} $ ]]; then
73
83
read localport proto destip destport <<< " ${dest}"
84
+ validate_port ${destport}
74
85
echo -A PREROUTING -i eth0 -p " ${proto} " --dport " ${localport} " -j DNAT --to-destination " ${destip} :${destport} "
75
86
76
87
else
77
- echo " EGRESS_DESTINATION value '${dest} ' is invalid" 1>&2
78
- exit 1
88
+ die " EGRESS_DESTINATION value '${dest} ' is invalid" 1>&2
79
89
80
90
fi
81
91
92
+ if [[ -n " ${localport} " ]]; then
93
+ validate_port ${localport}
94
+
95
+ if [[ " ${used_ports[${localport}]:- x} " == " x" ]]; then
96
+ used_ports[${localport} ]=1
97
+ else
98
+ die " EGRESS_DESTINATION localport $localport is already used, must be unique for each destination"
99
+ fi
100
+ fi
101
+
82
102
done <<< " ${EGRESS_DESTINATION}"
83
103
echo -A POSTROUTING -j SNAT --to-source " ${EGRESS_SOURCE} "
84
104
}
@@ -132,8 +152,7 @@ case "${EGRESS_ROUTER_MODE:=legacy}" in
132
152
;;
133
153
134
154
* )
135
- echo " Unrecognized EGRESS_ROUTER_MODE '${EGRESS_ROUTER_MODE} '"
136
- exit 1
155
+ die " Unrecognized EGRESS_ROUTER_MODE '${EGRESS_ROUTER_MODE} '"
137
156
;;
138
157
esac
139
158
0 commit comments