This repository has been archived by the owner on Jan 23, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 86
/
istio-iptables.sh
executable file
·656 lines (601 loc) · 24.3 KB
/
istio-iptables.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
#!/bin/bash
#
# Copyright 2017, 2018 Istio Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
#
# Initialization script responsible for setting up port forwarding for Istio sidecar.
function usage() {
echo "${0} -p PORT -u UID -g GID [-m mode] [-b ports] [-d ports] [-i CIDR] [-x CIDR] [-k interfaces] [-t] [-h]"
echo ''
# shellcheck disable=SC2016
echo ' -p: Specify the envoy port to which redirect all TCP traffic (default $ENVOY_PORT = 15001)'
# shellcheck disable=SC2016
echo ' -z: Port to which all inbound TCP traffic to the pod/VM should be redirected to. For REDIRECT only (default $INBOUND_CAPTURE_PORT = 15006)'
echo ' -u: Specify the UID of the user for which the redirection is not'
echo ' applied. Typically, this is the UID of the proxy container'
# shellcheck disable=SC2016
echo ' (default to uid of $ENVOY_USER, uid of istio_proxy, or 1337)'
echo ' -g: Specify the GID of the user for which the redirection is not'
echo ' applied. (same default value as -u param)'
echo ' -m: The mode used to redirect inbound connections to Envoy, either "REDIRECT" or "TPROXY"'
# shellcheck disable=SC2016
echo ' (default to $ISTIO_INBOUND_INTERCEPTION_MODE)'
echo ' -b: Comma separated list of inbound ports for which traffic is to be redirected to Envoy (optional). The'
echo ' wildcard character "*" can be used to configure redirection for all ports. An empty list will disable'
# shellcheck disable=SC2016
echo ' all inbound redirection (default to $ISTIO_INBOUND_PORTS)'
echo ' -d: Comma separated list of inbound ports to be excluded from redirection to Envoy (optional). Only applies'
# shellcheck disable=SC2016
echo ' when all inbound traffic (i.e. "*") is being redirected (default to $ISTIO_LOCAL_EXCLUDE_PORTS)'
echo ' -i: Comma separated list of IP ranges in CIDR form to redirect to envoy (optional). The wildcard'
echo ' character "*" can be used to redirect all outbound traffic. An empty list will disable all outbound'
# shellcheck disable=SC2016
echo ' redirection (default to $ISTIO_SERVICE_CIDR)'
echo ' -x: Comma separated list of IP ranges in CIDR form to be excluded from redirection. Only applies when all '
# shellcheck disable=SC2016
echo ' outbound traffic (i.e. "*") is being redirected (default to $ISTIO_SERVICE_EXCLUDE_CIDR).'
echo ' -o: Comma separated list of outbound ports to be excluded from redirection to Envoy (optional).'
echo ' -k: Comma separated list of virtual interfaces whose inbound traffic (from VM)'
echo ' will be treated as outbound (optional)'
echo ' -t: Unit testing, only functions are loaded and no other instructions are executed.'
echo ' -h: Displays usage information and exits.'
# shellcheck disable=SC2016
echo ''
}
function dump {
iptables-save
ip6tables-save
}
function isValidIP() {
if isIPv4 "${1}"; then
true
elif isIPv6 "${1}"; then
true
else
false
fi
}
#
# Function return true if argument is a valid ipv4 address
#
function isIPv4() {
local ipv4regexp="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
if [[ ${1} =~ ${ipv4regexp} ]]; then
true
else
false
fi
}
#
# Function return true if argument is a valid ipv6 address
#
function isIPv6() {
local ipv6section="^[0-9a-fA-F]{1,4}$"
addr="$1"
number_of_parts=0
number_of_skip=0
IFS=':' read -r -a addr <<< "$1"
if [ ${#addr[@]} -eq 0 ]; then
return 1
fi
for part in "${addr[@]}"; do
# check to not exceed number of parts in ipv6 address
if [[ ${number_of_parts} -ge 8 ]]; then
return 1
fi
if [[ ${number_of_parts} -eq 0 ]] && ! [[ ${part} =~ ${ipv6section} ]]; then
return 1
fi
if ! [[ ${part} =~ ${ipv6section} ]]; then
if ! [[ "$part" == "" ]]; then
return 1
else
# Found empty part, no more than 2 sections '::' are allowed in ipv6 address
if [[ "$number_of_skip" -ge 1 ]]; then
return 1
fi
((number_of_skip++))
fi
fi
((number_of_parts++))
done
return 0
}
#
# Maximum time to wait for an iptables call to succeed when populating the redirection rules.
# During that time, iptables call will be attempted for every one second.
#
IPTABLES_WAIT=30
#
# The path to the iptables command.
#
# shellcheck disable=SC2230
IPTABLES_CMD=$(which iptables)
#
# The path to the ip6tables command.
#
# shellcheck disable=SC2230
IP6TABLES_CMD=$(which ip6tables)
#
# If true, retries iptables & ip6tables commands in case they fails.
#
IPTABLES_RETRY=false
#
# Function wrapping a command to retry in case of failure if IPTABLES_RETRY is "true".
#
function iptables_retry {
if [ "${IPTABLES_RETRY}" != "true" ]; then
"$@"
return $?
fi
local iptables_wait=$IPTABLES_WAIT
set +o errexit
while true; do
"$@"
local err_code=$?
if [[ $err_code == 0 ]]; then
break
fi
iptables_wait=$(( iptables_wait - 1 ))
if (( iptables_wait > 0 )); then
sleep 1
else
exit $err_code
fi
done
set -o errexit
}
#
# Function wrapping iptables to retry in case of failure if IPTABLES_RETRY is "true".
#
function iptables {
iptables_retry "$IPTABLES_CMD" "$@"
return $?
}
#
# Function wrapping ip6tables to retry in case of failure if IPTABLES_RETRY is "true".
#
function ip6tables {
iptables_retry "$IP6TABLES_CMD" "$@"
return $?
}
# Use a comma as the separator for multi-value arguments.
IFS=,
# TODO: load all files from a directory, similar with ufw, to make it easier for automated install scripts
# Ideally we should generate ufw (and similar) configs as well, in case user already has an iptables solution.
PROXY_PORT=${ENVOY_PORT:-15001}
PROXY_INBOUND_CAPTURE_PORT=${INBOUND_CAPTURE_PORT:-15006}
PROXY_UID=
PROXY_GID=
INBOUND_INTERCEPTION_MODE=${ISTIO_INBOUND_INTERCEPTION_MODE}
INBOUND_TPROXY_MARK=${ISTIO_INBOUND_TPROXY_MARK:-1337}
INBOUND_TPROXY_ROUTE_TABLE=${ISTIO_INBOUND_TPROXY_ROUTE_TABLE:-133}
INBOUND_PORTS_INCLUDE=${ISTIO_INBOUND_PORTS-}
INBOUND_PORTS_EXCLUDE=${ISTIO_LOCAL_EXCLUDE_PORTS-}
OUTBOUND_IP_RANGES_INCLUDE=${ISTIO_SERVICE_CIDR-}
OUTBOUND_IP_RANGES_EXCLUDE=${ISTIO_SERVICE_EXCLUDE_CIDR-}
OUTBOUND_PORTS_EXCLUDE=${ISTIO_LOCAL_OUTBOUND_PORTS_EXCLUDE-}
KUBEVIRT_INTERFACES=
ENABLE_INBOUND_IPV6=
while getopts ":p:z:u:g:m:b:d:o:i:x:k:ht" opt; do
case ${opt} in
p)
PROXY_PORT=${OPTARG}
;;
z)
PROXY_INBOUND_CAPTURE_PORT=${OPTARG}
;;
u)
PROXY_UID=${OPTARG}
;;
g)
PROXY_GID=${OPTARG}
;;
m)
INBOUND_INTERCEPTION_MODE=${OPTARG}
;;
b)
INBOUND_PORTS_INCLUDE=${OPTARG}
;;
d)
INBOUND_PORTS_EXCLUDE=${OPTARG}
;;
i)
OUTBOUND_IP_RANGES_INCLUDE=${OPTARG}
;;
x)
OUTBOUND_IP_RANGES_EXCLUDE=${OPTARG}
;;
o)
OUTBOUND_PORTS_EXCLUDE=${OPTARG}
;;
k)
KUBEVIRT_INTERFACES=${OPTARG}
;;
t)
echo "Unit testing is specified..."
return
;;
h)
usage
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage
exit 1
;;
esac
done
trap dump EXIT
# TODO: more flexibility - maybe a whitelist of users to be captured for output instead of a blacklist.
if [ -z "${PROXY_UID}" ]; then
# Default to the UID of ENVOY_USER and root
if ! PROXY_UID=$(id -u "${ENVOY_USER:-istio-proxy}"); then
PROXY_UID="1337"
fi
# If ENVOY_UID is not explicitly defined (as it would be in k8s env), we add root to the list,
# for ca agent.
PROXY_UID=${PROXY_UID},0
fi
# for TPROXY as its uid and gid are same
if [ -z "${PROXY_GID}" ]; then
PROXY_GID=${PROXY_UID}
fi
# Check if any of the pod's ip addresses are ipv6. If so, set variable
# to program ip6tables.
#
# The odd structure of this loop is to prevent the while loop from
# executing in a subshell, which prevents ENABLE_INBOUND_IPV6 from
# being set in the main script.
while read -r POD_IP; do
if isIPv6 "$POD_IP"; then
echo "Found ipv6 pod IP: ${POD_IP}"
ENABLE_INBOUND_IPV6="${POD_IP}"
else
echo "Found ipv4 pod IP: ${POD_IP}"
fi
done <<< "$(ip -brief -oneline addr | awk '{print $3}' | sed 's|/.*||g')"
#
# Since OUTBOUND_IP_RANGES_EXCLUDE could carry ipv4 and ipv6 ranges
# need to split them in different arrays one for ipv4 and one for ipv6
# in order to not to fail
pl='/*'
#
# Next two lines, read comma separated inclusion and exclusion lists into
# arrays, so each element could be validated individually.
#
IFS=',' read -ra EXCLUDE <<< "$OUTBOUND_IP_RANGES_EXCLUDE"
IFS=',' read -ra INCLUDE <<< "$OUTBOUND_IP_RANGES_INCLUDE"
ipv6_ranges_exclude=()
ipv4_ranges_exclude=()
for range in "${EXCLUDE[@]}"; do
r=${range%$pl}
if isValidIP "$r"; then
if isIPv4 "$r"; then
ipv4_ranges_exclude+=("$range")
elif isIPv6 "$r"; then
ipv6_ranges_exclude+=("$range")
fi
fi
done
ipv6_ranges_include=()
ipv4_ranges_include=()
if [ "${OUTBOUND_IP_RANGES_INCLUDE}" == "*" ]; then
ipv6_ranges_include=("*")
ipv4_ranges_include=("*")
else
for range in "${INCLUDE[@]}"; do
r=${range%$pl}
if isValidIP "$r"; then
if isIPv4 "$r"; then
ipv4_ranges_include+=("$range")
elif isIPv6 "$r"; then
ipv6_ranges_include+=("$range")
fi
fi
done
fi
# Dump out our environment for debugging purposes.
echo "Environment:"
echo "------------"
echo "ENVOY_PORT=${ENVOY_PORT-}"
echo "INBOUND_CAPTURE_PORT=${INBOUND_CAPTURE_PORT-}"
echo "ISTIO_INBOUND_INTERCEPTION_MODE=${ISTIO_INBOUND_INTERCEPTION_MODE-}"
echo "ISTIO_INBOUND_TPROXY_MARK=${ISTIO_INBOUND_TPROXY_MARK-}"
echo "ISTIO_INBOUND_TPROXY_ROUTE_TABLE=${ISTIO_INBOUND_TPROXY_ROUTE_TABLE-}"
echo "ISTIO_INBOUND_PORTS=${ISTIO_INBOUND_PORTS-}"
echo "ISTIO_LOCAL_EXCLUDE_PORTS=${ISTIO_LOCAL_EXCLUDE_PORTS-}"
echo "ISTIO_SERVICE_CIDR=${ISTIO_SERVICE_CIDR-}"
echo "ISTIO_SERVICE_EXCLUDE_CIDR=${ISTIO_SERVICE_EXCLUDE_CIDR-}"
echo
echo "Variables:"
echo "----------"
echo "PROXY_PORT=${PROXY_PORT}"
echo "PROXY_INBOUND_CAPTURE_PORT=${PROXY_INBOUND_CAPTURE_PORT}"
echo "PROXY_UID=${PROXY_UID}"
echo "INBOUND_INTERCEPTION_MODE=${INBOUND_INTERCEPTION_MODE}"
echo "INBOUND_TPROXY_MARK=${INBOUND_TPROXY_MARK}"
echo "INBOUND_TPROXY_ROUTE_TABLE=${INBOUND_TPROXY_ROUTE_TABLE}"
echo "INBOUND_PORTS_INCLUDE=${INBOUND_PORTS_INCLUDE}"
echo "INBOUND_PORTS_EXCLUDE=${INBOUND_PORTS_EXCLUDE}"
echo "OUTBOUND_IP_RANGES_INCLUDE=${OUTBOUND_IP_RANGES_INCLUDE}"
echo "OUTBOUND_IP_RANGES_EXCLUDE=${OUTBOUND_IP_RANGES_EXCLUDE}"
echo "OUTBOUND_PORTS_EXCLUDE=${OUTBOUND_PORTS_EXCLUDE}"
echo "KUBEVIRT_INTERFACES=${KUBEVIRT_INTERFACES}"
echo "ENABLE_INBOUND_IPV6=${ENABLE_INBOUND_IPV6}"
echo
set +o nounset
# Blindly add a ipv6 address. If it fails it's fine.
# Add local ipv6 address to lo. Used in redirecting unknown ipv6 traffic to original dst.
# This address does not show up in neigh table so each Pod/Vm will only see its own. Think about 127.0.0.6.
if [ -n "${ENABLE_INBOUND_IPV6}" ]; then
ip -6 addr add ::6/128 dev lo
fi
set -o errexit
set -o nounset
set -o pipefail
set -x # echo on
IPTABLES_RETRY=true
# Create a new chain for redirecting outbound traffic to the common Envoy port.
# In both chains, '-j RETURN' bypasses Envoy and '-j ISTIO_REDIRECT'
# redirects to Envoy.
iptables -t nat -N ISTIO_REDIRECT
iptables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-port "${PROXY_PORT}"
# Use this chain also for redirecting inbound traffic to the common Envoy port
# when not using TPROXY.
iptables -t nat -N ISTIO_IN_REDIRECT
iptables -t nat -A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-port "${PROXY_INBOUND_CAPTURE_PORT}"
# Handling of inbound ports. Traffic will be redirected to Envoy, which will process and forward
# to the local service. If not set, no inbound port will be intercepted by istio iptables.
if [ -n "${INBOUND_PORTS_INCLUDE}" ]; then
if [ "${INBOUND_INTERCEPTION_MODE}" = "TPROXY" ] ; then
# When using TPROXY, create a new chain for routing all inbound traffic to
# Envoy. Any packet entering this chain gets marked with the ${INBOUND_TPROXY_MARK} mark,
# so that they get routed to the loopback interface in order to get redirected to Envoy.
# In the ISTIO_INBOUND chain, '-j ISTIO_DIVERT' reroutes to the loopback
# interface.
# Mark all inbound packets.
iptables -t mangle -N ISTIO_DIVERT
iptables -t mangle -A ISTIO_DIVERT -j MARK --set-mark "${INBOUND_TPROXY_MARK}"
iptables -t mangle -A ISTIO_DIVERT -j ACCEPT
# Route all packets marked in chain ISTIO_DIVERT using routing table ${INBOUND_TPROXY_ROUTE_TABLE}.
ip -f inet rule add fwmark "${INBOUND_TPROXY_MARK}" lookup "${INBOUND_TPROXY_ROUTE_TABLE}"
# In routing table ${INBOUND_TPROXY_ROUTE_TABLE}, create a single default rule to route all traffic to
# the loopback interface.
ip -f inet route add local default dev lo table "${INBOUND_TPROXY_ROUTE_TABLE}" || ip route show table all
# Create a new chain for redirecting inbound traffic to the common Envoy
# port.
# In the ISTIO_INBOUND chain, '-j RETURN' bypasses Envoy and
# '-j ISTIO_TPROXY' redirects to Envoy.
iptables -t mangle -N ISTIO_TPROXY
iptables -t mangle -A ISTIO_TPROXY ! -d 127.0.0.1/32 -p tcp -j TPROXY --tproxy-mark "${INBOUND_TPROXY_MARK}/0xffffffff" --on-port "${PROXY_PORT}"
table=mangle
else
table=nat
fi
iptables -t ${table} -N ISTIO_INBOUND
iptables -t ${table} -A PREROUTING -p tcp -j ISTIO_INBOUND
if [ "${INBOUND_PORTS_INCLUDE}" == "*" ]; then
# Makes sure SSH is not redirected
iptables -t ${table} -A ISTIO_INBOUND -p tcp --dport 22 -j RETURN
# Apply any user-specified port exclusions.
if [ -n "${INBOUND_PORTS_EXCLUDE}" ]; then
for port in ${INBOUND_PORTS_EXCLUDE}; do
iptables -t ${table} -A ISTIO_INBOUND -p tcp --dport "${port}" -j RETURN
done
fi
# Redirect remaining inbound traffic to Envoy.
if [ "${INBOUND_INTERCEPTION_MODE}" = "TPROXY" ]; then
# If an inbound packet belongs to an established socket, route it to the
# loopback interface.
iptables -t mangle -A ISTIO_INBOUND -p tcp -m conntrack --ctstate RELATED,ESTABLISHED -j ISTIO_DIVERT || echo "No conntrack match support"
# Otherwise, it's a new connection. Redirect it using TPROXY.
iptables -t mangle -A ISTIO_INBOUND -p tcp -j ISTIO_TPROXY
else
iptables -t nat -A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
fi
else
# User has specified a non-empty list of ports to be redirected to Envoy.
for port in ${INBOUND_PORTS_INCLUDE}; do
if [ "${INBOUND_INTERCEPTION_MODE}" = "TPROXY" ]; then
iptables -t mangle -A ISTIO_INBOUND -p tcp --dport "${port}" -m conntrack --ctstate RELATED,ESTABLISHED -j ISTIO_DIVERT || echo "No conntrack match support"
iptables -t mangle -A ISTIO_INBOUND -p tcp --dport "${port}" -j ISTIO_TPROXY
else
iptables -t nat -A ISTIO_INBOUND -p tcp --dport "${port}" -j ISTIO_IN_REDIRECT
fi
done
fi
fi
# TODO: change the default behavior to not intercept any output - user may use http_proxy or another
# iptables wrapper (like ufw). Current default is similar with 0.1
# Create a new chain for selectively redirecting outbound packets to Envoy.
iptables -t nat -N ISTIO_OUTPUT
# Jump to the ISTIO_OUTPUT chain from OUTPUT chain for all tcp traffic.
iptables -t nat -A OUTPUT -p tcp -j ISTIO_OUTPUT
# Apply port based exclusions. Must be applied before connections back to self
# are redirected.
if [ -n "${OUTBOUND_PORTS_EXCLUDE}" ]; then
for port in ${OUTBOUND_PORTS_EXCLUDE}; do
iptables -t nat -A ISTIO_OUTPUT -p tcp --dport "${port}" -j RETURN
done
fi
# 127.0.0.6 is bind connect from inbound passthrough cluster
iptables -t nat -A ISTIO_OUTPUT -o lo -s 127.0.0.6/32 -j RETURN
for uid in ${PROXY_UID}; do
# Redirect app calls back to itself via Envoy when using the service VIP
# e.g. appN => Envoy (client) => Envoy (server) => appN.
iptables -t nat -A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -m owner --uid-owner "${uid}" -j ISTIO_IN_REDIRECT
# Do not redirect app calls to back itself via Envoy when using the endpoint address
# e.g. appN => appN by lo
iptables -t nat -A ISTIO_OUTPUT -o lo -m owner ! --uid-owner "${uid}" -j RETURN
# Avoid infinite loops. Don't redirect Envoy traffic directly back to
# Envoy for non-loopback traffic.
iptables -t nat -A ISTIO_OUTPUT -m owner --uid-owner "${uid}" -j RETURN
done
for gid in ${PROXY_GID}; do
# Redirect app calls back to itself via Envoy when using the service VIP
# e.g. appN => Envoy (client) => Envoy (server) => appN.
iptables -t nat -A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -m owner --gid-owner "${gid}" -j ISTIO_IN_REDIRECT
# Do not redirect app calls to back itself via Envoy when using the endpoint address
# e.g. appN => appN by lo
iptables -t nat -A ISTIO_OUTPUT -o lo -m owner ! --gid-owner "${gid}" -j RETURN
# Avoid infinite loops. Don't redirect Envoy traffic directly back to
# Envoy for non-loopback traffic.
iptables -t nat -A ISTIO_OUTPUT -m owner --gid-owner "${gid}" -j RETURN
done
# Skip redirection for Envoy-aware applications and
# container-to-container traffic both of which explicitly use
# localhost.
iptables -t nat -A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
# Apply outbound IPv4 exclusions. Must be applied before inclusions.
if [ ${#ipv4_ranges_exclude[@]} -gt 0 ]; then
for cidr in "${ipv4_ranges_exclude[@]}"; do
iptables -t nat -A ISTIO_OUTPUT -d "${cidr}" -j RETURN
done
fi
for internalInterface in ${KUBEVIRT_INTERFACES}; do
iptables -t nat -I PREROUTING 1 -i "${internalInterface}" -j RETURN
done
# Apply outbound IP inclusions.
if [ ${#ipv4_ranges_include[@]} -gt 0 ]; then
if [ "${ipv4_ranges_include[0]}" == "*" ]; then
# Wildcard specified. Redirect all remaining outbound traffic to Envoy.
iptables -t nat -A ISTIO_OUTPUT -j ISTIO_REDIRECT
for internalInterface in ${KUBEVIRT_INTERFACES}; do
iptables -t nat -I PREROUTING 1 -i "${internalInterface}" -j ISTIO_REDIRECT
done
else
# User has specified a non-empty list of cidrs to be redirected to Envoy.
for cidr in "${ipv4_ranges_include[@]}"; do
for internalInterface in ${KUBEVIRT_INTERFACES}; do
iptables -t nat -I PREROUTING 1 -i "${internalInterface}" -d "${cidr}" -j ISTIO_REDIRECT
done
iptables -t nat -A ISTIO_OUTPUT -d "${cidr}" -j ISTIO_REDIRECT
done
# All other traffic is not redirected.
iptables -t nat -A ISTIO_OUTPUT -j RETURN
fi
fi
# If ENABLE_INBOUND_IPV6 is unset (default unset), restrict IPv6 traffic.
set +o nounset
if [ -n "${ENABLE_INBOUND_IPV6}" ]; then
# Create a new chain for redirecting outbound traffic to the common Envoy port.
# In both chains, '-j RETURN' bypasses Envoy and '-j ISTIO_REDIRECT'
# redirects to Envoy.
ip6tables -t nat -N ISTIO_REDIRECT
ip6tables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-port "${PROXY_PORT}"
# Use this chain also for redirecting inbound traffic to the common Envoy port
# when not using TPROXY.
ip6tables -t nat -N ISTIO_IN_REDIRECT
ip6tables -t nat -A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-port "${PROXY_INBOUND_CAPTURE_PORT}"
# Handling of inbound ports. Traffic will be redirected to Envoy, which will process and forward
# to the local service. If not set, no inbound port will be intercepted by istio iptables.
if [ -n "${INBOUND_PORTS_INCLUDE}" ]; then
table=nat
ip6tables -t ${table} -N ISTIO_INBOUND
ip6tables -t ${table} -A PREROUTING -p tcp -j ISTIO_INBOUND
if [ "${INBOUND_PORTS_INCLUDE}" == "*" ]; then
# Makes sure SSH is not redirected
ip6tables -t ${table} -A ISTIO_INBOUND -p tcp --dport 22 -j RETURN
# Apply any user-specified port exclusions.
if [ -n "${INBOUND_PORTS_EXCLUDE}" ]; then
for port in ${INBOUND_PORTS_EXCLUDE}; do
ip6tables -t ${table} -A ISTIO_INBOUND -p tcp --dport "${port}" -j RETURN
done
fi
# Redirect other inbound traffic
ip6tables -t ${table} -A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
else
# User has specified a non-empty list of ports to be redirected to Envoy.
for port in ${INBOUND_PORTS_INCLUDE}; do
ip6tables -t nat -A ISTIO_INBOUND -p tcp --dport "${port}" -j ISTIO_IN_REDIRECT
done
fi
fi
# Create a new chain for selectively redirecting outbound packets to Envoy.
ip6tables -t nat -N ISTIO_OUTPUT
# Jump to the ISTIO_OUTPUT chain from OUTPUT chain for all tcp traffic.
ip6tables -t nat -A OUTPUT -p tcp -j ISTIO_OUTPUT
# Apply port based exclusions. Must be applied before connections back to self
# are redirected.
if [ -n "${OUTBOUND_PORTS_EXCLUDE}" ]; then
for port in ${OUTBOUND_PORTS_EXCLUDE}; do
ip6tables -t nat -A ISTIO_OUTPUT -p tcp --dport "${port}" -j RETURN
done
fi
# ::6 is bind when connect from inbound passthrough cluster
ip6tables -t nat -A ISTIO_OUTPUT -o lo -s ::6/128 -j RETURN
for uid in ${PROXY_UID}; do
# Redirect app calls back to itself via Envoy when using the service VIP
# e.g. appN => Envoy (client) => Envoy (server) => appN.
ip6tables -t nat -A ISTIO_OUTPUT -o lo ! -d ::1/128 -m owner --uid-owner "${uid}" -j ISTIO_IN_REDIRECT
# Do not redirect app calls to back itself via Envoy when using the endpoint address
# e.g. appN => appN by lo
ip6tables -t nat -A ISTIO_OUTPUT -o lo -m owner ! --uid-owner "${uid}" -j RETURN
# Avoid infinite loops. Don't redirect Envoy traffic directly back to
# Envoy for non-loopback traffic.
ip6tables -t nat -A ISTIO_OUTPUT -m owner --uid-owner "${uid}" -j RETURN
done
for gid in ${PROXY_GID}; do
# Redirect app calls back to itself via Envoy when using the service VIP
# e.g. appN => Envoy (client) => Envoy (server) => appN.
ip6tables -t nat -A ISTIO_OUTPUT -o lo ! -d ::1/128 -m owner --gid-owner "${gid}" -j ISTIO_IN_REDIRECT
# Do not redirect app calls to back itself via Envoy when using the endpoint address
# e.g. appN => appN by lo
ip6tables -t nat -A ISTIO_OUTPUT -o lo -m owner ! --gid-owner "${gid}" -j RETURN
# Avoid infinite loops. Don't redirect Envoy traffic directly back to
# Envoy for non-loopback traffic.
ip6tables -t nat -A ISTIO_OUTPUT -m owner --gid-owner "${gid}" -j RETURN
done
# Skip redirection for Envoy-aware applications and
# container-to-container traffic both of which explicitly use
# localhost.
ip6tables -t nat -A ISTIO_OUTPUT -d ::1/128 -j RETURN
# Apply outbound IPv6 exclusions. Must be applied before inclusions.
if [ ${#ipv6_ranges_exclude[@]} -gt 0 ]; then
for cidr in "${ipv6_ranges_exclude[@]}"; do
ip6tables -t nat -A ISTIO_OUTPUT -d "${cidr}" -j RETURN
done
fi
# Apply outbound IPv6 inclusions.
if [ ${#ipv6_ranges_include[@]} -gt 0 ]; then
if [ "${ipv6_ranges_include[0]}" == "*" ]; then
# Wildcard specified. Redirect all remaining outbound traffic to Envoy.
ip6tables -t nat -A ISTIO_OUTPUT -j ISTIO_REDIRECT
for internalInterface in ${KUBEVIRT_INTERFACES}; do
ip6tables -t nat -I PREROUTING 1 -i "${internalInterface}" -j RETURN
done
else
# User has specified a non-empty list of cidrs to be redirected to Envoy.
for cidr in "${ipv6_ranges_include[@]}"; do
for internalInterface in ${KUBEVIRT_INTERFACES}; do
ip6tables -t nat -I PREROUTING 1 -i "${internalInterface}" -d "${cidr}" -j ISTIO_REDIRECT
done
ip6tables -t nat -A ISTIO_OUTPUT -d "${cidr}" -j ISTIO_REDIRECT
done
# All other traffic is not redirected.
ip6tables -t nat -A ISTIO_OUTPUT -j RETURN
fi
fi
else
IPTABLES_RETRY=false
# Drop all inbound traffic except established connections.
ip6tables -t filter -F INPUT || true
ip6tables -t filter -A INPUT -m state --state ESTABLISHED -j ACCEPT || true
ip6tables -t filter -A INPUT -i lo -d ::1 -j ACCEPT || true
ip6tables -t filter -A INPUT -j REJECT || true
fi