Skip to content

Commit 29d64d1

Browse files
author
Ravi Sankar Penta
committed
Add validations to Egress router script
- In case of multiple destinations, ensure unique local port is redirected to each destination - Early port validation instead of implicitly depending on iptables
1 parent d5b13f7 commit 29d64d1

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

images/egress/router/egress-router.sh

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,21 @@ set -o errexit
66
set -o nounset
77
set -o pipefail
88

9+
function die() {
10+
echo "$*" 1>&2
11+
exit 1
12+
}
13+
914
BLANK_LINE_OR_COMMENT_REGEX="([[:space:]]*$|#.*)"
1015
PORT_REGEX="[[:digit:]]+"
1116
PROTO_REGEX="(tcp|udp)"
1217
IP_REGEX="[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+"
1318

1419
if [[ ! "${EGRESS_SOURCE:-}" =~ ^${IP_REGEX}$ ]]; then
15-
echo "EGRESS_SOURCE unspecified or invalid"
16-
exit 1
20+
die "EGRESS_SOURCE unspecified or invalid"
1721
fi
1822
if [[ ! "${EGRESS_GATEWAY:-}" =~ ^${IP_REGEX}$ ]]; then
19-
echo "EGRESS_GATEWAY unspecified or invalid"
20-
exit 1
23+
die "EGRESS_GATEWAY unspecified or invalid"
2124
fi
2225

2326
if [[ -n "${EGRESS_ROUTER_DEBUG:-}" ]]; then
@@ -43,23 +46,30 @@ function setup_network() {
4346
arping -q -U -c 1 -I macvlan0 "${EGRESS_SOURCE}" || true ) > /dev/null 2>&1 < /dev/null &
4447
}
4548

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+
4656
function gen_iptables_rules() {
4757
if [[ -z "${EGRESS_DESTINATION:-}" ]]; then
48-
echo "EGRESS_DESTINATION unspecified"
49-
exit 1
58+
die "EGRESS_DESTINATION unspecified"
5059
fi
5160

5261
did_fallback=
62+
declare -A used_ports=()
5363
while read dest; do
5464
if [[ "${dest}" =~ ^${BLANK_LINE_OR_COMMENT_REGEX}$ ]]; then
5565
# comment or blank line
5666
continue
5767
fi
5868
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
6170
fi
6271

72+
localport=""
6373
if [[ "${dest}" =~ ^${IP_REGEX}$ ]]; then
6474
# single IP address: do fallback "all ports to same IP"
6575
echo -A PREROUTING -i eth0 -j DNAT --to-destination "${dest}"
@@ -71,14 +81,24 @@ function gen_iptables_rules() {
7181

7282
elif [[ "${dest}" =~ ^${PORT_REGEX}\ +${PROTO_REGEX}\ +${IP_REGEX}\ +${PORT_REGEX}$ ]]; then
7383
read localport proto destip destport <<< "${dest}"
84+
validate_port ${destport}
7485
echo -A PREROUTING -i eth0 -p "${proto}" --dport "${localport}" -j DNAT --to-destination "${destip}:${destport}"
7586

7687
else
77-
echo "EGRESS_DESTINATION value '${dest}' is invalid" 1>&2
78-
exit 1
88+
die "EGRESS_DESTINATION value '${dest}' is invalid" 1>&2
7989

8090
fi
8191

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+
82102
done <<< "${EGRESS_DESTINATION}"
83103
echo -A POSTROUTING -j SNAT --to-source "${EGRESS_SOURCE}"
84104
}
@@ -132,8 +152,7 @@ case "${EGRESS_ROUTER_MODE:=legacy}" in
132152
;;
133153

134154
*)
135-
echo "Unrecognized EGRESS_ROUTER_MODE '${EGRESS_ROUTER_MODE}'"
136-
exit 1
155+
die "Unrecognized EGRESS_ROUTER_MODE '${EGRESS_ROUTER_MODE}'"
137156
;;
138157
esac
139158

images/egress/router/egress_router_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,18 @@ func TestEgressRouterBad(t *testing.T) {
197197
dest: "80 sctp 10.4.5.6",
198198
err: "EGRESS_DESTINATION value '80 sctp 10.4.5.6' is invalid",
199199
},
200+
{
201+
source: "1.2.3.4",
202+
gateway: "1.1.1.1",
203+
dest: "800000 tcp 10.4.5.6",
204+
err: "Invalid port: 800000, must be in the range 1 to 65535",
205+
},
206+
{
207+
source: "1.2.3.4",
208+
gateway: "1.1.1.1",
209+
dest: "80 tcp 10.4.5.6\n8080 tcp 10.7.8.9 80\n80 tcp 10.7.8.9 900",
210+
err: "EGRESS_DESTINATION localport 80 is already used, must be unique for each destination",
211+
},
200212
}
201213

202214
for n, test := range tests {

0 commit comments

Comments
 (0)