-
Notifications
You must be signed in to change notification settings - Fork 91
prepare_proxy: add support for excluding external traffic #573
Conversation
Add generic support for including and excluding outbound traffic based on CIDR blocks. Default behavior is opt-out where all outbound traffic is redirected to proxy unless explicitly opted-opt with "-e" option. When the "-i" option is used the behavior changes to opt-in and only outbound traffic explicitly specified with "-i" is redirected to the proxy. The "-i" option takes precedence over "-e" the option if both are specified. As part of this change the iptable rules were refactored to make it easier differentiate redirect from bypass cases, e.g. '-j ISTIO_REDIRECT' vs. '-j RETURN'.
Can we reduce the confusion on opt-out and opt-in and just have one? Like a set of -i flags. With no -i, all traffic goes through proxy. With -i, operators could restrict traffic capture to specific CIDR blocks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, looks pretty well done. Thanks for the extensive comments. Few minor issues in the PR.
docker/prepare_proxy.sh
Outdated
# (i.e. proxy aware) or not from the proxy itself is redirected proxy port. | ||
iptables -t nat -A OUTPUT -p tcp -j REDIRECT ! -s 127.0.0.1/32 \ | ||
--to-port ${ISTIO_PROXY_PORT} -m owner '!' --uid-owner ${ISTIO_PROXY_UID} | ||
iptables -t nat -F |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to flush nat?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't. It was useful for unit testing but can be removed since prepare_proxy_test.sh restarts the pods for each test iteration.
docker/prepare_proxy.sh
Outdated
# the common Istio proxy port. | ||
iptables -t nat -N ISTIO_REDIRECT -m comment --comment "istio/redirect-common-chain" | ||
iptables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports ${ISTIO_PROXY_PORT} -m comment --comment "istio/redirect-to-proxy-port" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nicely done! Thanks for these comments and clean documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change istio proxy to Envoy everywhere to align with rest of documentation
docker/prepare_proxy.sh
Outdated
iptables -t nat -N ISTIO_REDIRECT -m comment --comment "istio/redirect-common-chain" | ||
iptables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports ${ISTIO_PROXY_PORT} -m comment --comment "istio/redirect-to-proxy-port" | ||
|
||
# Redirect all inbound traffic to the proxy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inbound traffic into the pod
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add -m comment to all commands?
docker/prepare_proxy.sh
Outdated
# istio and attach it the OUTPUT rule for all tcp traffic. '-j RETURN' | ||
# bypasses the proxy port; '-j ISTIO_REDIRECT' redirects to the proxy | ||
# port. | ||
iptables -t nat -N ISTIO_OUTPUT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And what is -j ISTIO_OUTPUT ? (Missing comments).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The preceding comment was intended to cover lines 68 and 69 (i.e. create chain and attach to OUTPUT rule). I'll split this up to make it more clear.
docker/prepare_proxy.sh
Outdated
# Locally routed traffic is not captured by PREROUTING chain. Redirect | ||
# loopback back traffic when the DST_IP is not explicitly the loopback | ||
# address to handles appN => proxy (client) => proxy (server) => appN. | ||
iptables -t nat -A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -j ISTIO_REDIRECT -m comment --comment "istio/implicit-loopback" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably best to describe the use case instead of the data flow. E.g., when kubelet accesses the app for health checks (??), or app calls itself via http://podIP/..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And shouldn't this be restricted to tcp?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only jump to ISTIO_OUTPUT for tcp protocol traffic (line 69) so the -p tcp
seemed redundant. I can add it back if that makes things more clear though.
docker/prepare_proxy.sh
Outdated
# container-to-container traffic which explicitly use localhost. | ||
iptables -t nat -A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN -m comment --comment "istio/explicit-loopback" | ||
|
||
# The default outobund redirection policy is opt-out. IP ranges may be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo. Outbound
docker/prepare_proxy.sh
Outdated
for cidr in ${ISTIO_IP_RANGES_INCLUDE}; do | ||
iptables -t nat -A ISTIO_OUTPUT -d ${cidr} -j ISTIO_REDIRECT -m comment --comment "istio/include-cidr-block-${cidr}" | ||
done | ||
iptables -t nat -A ISTIO_OUTPUT -j RETURN -m comment --comment "istio/default-opt-out-redirect" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we follow the suggestion I made earlier (just have -i cidr), then this else block moves to the top doesn't it? We would no longer require the default catch all policy either.
docker/prepare_proxy_test.sh
Outdated
|
||
if false; then | ||
# exclude specific external traffic (opt-out) | ||
EXCLUDE_CIDR=$(host httpbin.org | cut -f4 -d' ' | sed -e 's|$|/32|' | paste -sd ",") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the point of this if block ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It creates a comma-separated list of IP ranges for httpbin.org to be excluded from redirection.
$ host httpbin.org | cut -f4 -d' ' | sed -e 's|$|/32|' | paste -sd ","
107.21.206.81/32,50.19.93.247/32,54.225.109.133/32,54.243.85.55/32,23.23.128.123/32,23.23.223.197/32,23.21.77.86/32,23.23.117.228/32
```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I meant the if false
block. This is never going to be executed is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, this was for manual testing. I'll added a flag at the top of control this as part of the refactoring to remove the EXCLUDE option.
docker/prepare_proxy_test.sh
Outdated
INCLUDE_CIDR=$(gcloud container clusters describe ${GCLOUD_CLUSTER_NAME} --zone=${GCLOUD_CLUSTER_ZONE} | | ||
grep -e clusterIpv4Cidr -e servicesIpv4Cidr | | ||
cut -f2 -d' ' | paste -sd ",") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you perhaps abstract this function out so that people could test this on say minikube or their local k8s clusters?
1) remove exlude option 2) rename proxy to Envoy throughout 3) add some additional comments
…raffic-bypass-flag
docker/prepare_proxy.sh
Outdated
# redirection with ISTIO_IP_RANGES_INCLUDE. | ||
# Only redirect outbound traffic to selective IP ranges when | ||
# ISTIO_IP_RANGES_INCLUDE is non-empty. Otherwise redirect all | ||
# outbound traffic not already handled by the previous rules to Envoy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would reuse a previous version of this comment as it looked better.
All outbound traffic will be redirected to Envoy by default. If ISTIO_IP_RANGES_INCLUDE is non-empty, only traffic bound for the destinations specified in this list will be captured.
…raffic-bypass-flag
…ager into add-outbound-traffic-bypass-flag
Fixes #515 for alpha. |
docker/prepare_proxy_test.sh
Outdated
CLIENT_PORT=81 | ||
OTHER_PORT=82 | ||
TEST_IP_RANGE_INCLUDE=0 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a variable: PLATFORM="gcloud"
docker/prepare_proxy_test.sh
Outdated
# list, e.g. 10.0.0.1/32,10.2.0.1/16. This function is GKE specific | ||
# and must modified for other providers, e.g. minikube. | ||
function k8sClusterAndServiceIPRange() { | ||
echo $(gcloud container clusters describe ${GCLOUD_CLUSTER_NAME} --zone=${GCLOUD_CLUSTER_ZONE} | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
case $platform in
gcloud)
echo..
*)
echo ""
esac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couple of comments in the test script
docker/prepare_proxy.sh
Outdated
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' | ||
echo ' -i: Comma separated list of IP ranges in CIDR form to redirection to envoy (optional)' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"for redirection"?
docker/prepare_proxy.sh
Outdated
;; | ||
h) | ||
usage | ||
usagey |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo?
docker/prepare_proxy.sh
Outdated
ENVOY_UID=${OPTARG} | ||
;; | ||
i) | ||
ISTIO_IP_RANGES_INCLUDE=${OPTARG} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why rename ISTIO_PROXY_PORT
but keep this ISTIO_
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's not much specific to envoy in this script btw
docker/prepare_proxy.sh
Outdated
# Create a new chain for redirecting inbound and outbound traffic to | ||
# the common Envoy port. | ||
iptables -t nat -N ISTIO_REDIRECT -m comment --comment "istio/redirect-common-chain" | ||
iptables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports ${ENVOY_PORT} -m comment --comment "istio/redirect-to-envoy-port" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"to-ports"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either will work, but changed to "to-port" to avoid confusion.
@@ -0,0 +1,238 @@ | |||
#!/bin/sh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd really prefer not have these long bash test scripts. They are close to unmaintainable...
# 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 -m comment --comment "istio/bypass-explicit-loopback" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have difficulty understanding all implications of these rules, so I trust @rshriram carefully reviewed these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Most of the setup/teardown code can be shared with the other integration tests. Maybe after release we can split that out into its own test package and have individual tests consume that that?
…raffic-bypass-flag
…ager into add-outbound-traffic-bypass-flag
Jenkins job manager/presubmit passed |
Jenkins job manager/e2e-smoketest passed |
Jenkins job manager/presubmit passed |
Jenkins job manager/e2e-smoketest passed |
docker_build( | ||
name = "init", | ||
base = "@docker_ubuntu//:xenial", | ||
manager_docker_build( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please put those back in jenkinsfile if you need them.
(Note for reviewers: prepare_proxy.sh is ready for review. prepare_proxy_test.sh is functional with some hand edits required for the configuration. It could probably be rewritten in golang to make it more readable.)
Short term solution to #515 for external traffic.
Add generic support for including and excluding outbound traffic based
on CIDR blocks. Default behavior is opt-out where all outbound traffic
is redirected to proxy unless explicitly opted-opt with "-e"
option. When the "-i" option is used the behavior changes to opt-in
and only outbound traffic explicitly specified with "-i" is redirected
to the proxy. The "-i" option takes precedence over "-e" the option if
both are specified.
As part of this change the iptable rules were refactored to make it
easier differentiate redirect from bypass cases, e.g. '-j
ISTIO_REDIRECT' vs. '-j RETURN'.