Skip to content

Instantly share code, notes, and snippets.

@ueokande
Last active March 2, 2021 08:00
Show Gist options
  • Select an option

  • Save ueokande/333e5e6e8ea3a2bdc29345ac8a7b8313 to your computer and use it in GitHub Desktop.

Select an option

Save ueokande/333e5e6e8ea3a2bdc29345ac8a7b8313 to your computer and use it in GitHub Desktop.

Revisions

  1. ueokande revised this gist Nov 23, 2020. No changes.
  2. ueokande created this gist Nov 23, 2020.
    182 changes: 182 additions & 0 deletions sidecar-proxy-route-manager.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,182 @@
    #!/bin/bash -e
    # Copyright 2018 Amazon.com, Inc. or its affiliates. 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. A copy of
    # the License is located at
    #
    # http://aws.amazon.com/apache2.0/
    #
    # or in the "license" file accompanying this file. This file 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.
    #

    #
    # Start of configurable options
    #

    # Enable routing on the application start.
    [ -z "$APPMESH_START_ENABLED" ] && APPMESH_START_ENABLED="0"

    # Egress traffic from the processess owned by the following UID/GID will be ignored.
    if [ -z "$APPMESH_IGNORE_UID" ] && [ -z "$APPMESH_IGNORE_GID" ]; then
    echo "Variables APPMESH_IGNORE_UID and/or APPMESH_IGNORE_GID must be set."
    echo "Envoy must run under those IDs to be able to properly route it's egress traffic."
    exit 1
    fi

    # Port numbers Application and Envoy are listening on.
    if [ -z "$APPMESH_ENVOY_EGRESS_PORT" ]; then
    echo "APPMESH_ENVOY_EGRESS_PORT must be defined to forward traffic from the application to the proxy."
    exit 1
    fi

    # If an app port was specified, then we also need to enforce the proxies ingress port so we know where to forward traffic.
    if [ ! -z "$APPMESH_APP_PORTS" ] && [ -z "$APPMESH_ENVOY_INGRESS_PORT" ]; then
    echo "APPMESH_ENVOY_INGRESS_PORT must be defined to forward traffic from the APPMESH_APP_PORTS to the proxy."
    exit 1
    fi

    # Comma separated list of ports for which egress traffic will be ignored, we always refuse to route SSH traffic.
    if [ -z "$APPMESH_EGRESS_IGNORED_PORTS" ]; then
    APPMESH_EGRESS_IGNORED_PORTS="22"
    else
    APPMESH_EGRESS_IGNORED_PORTS="$APPMESH_EGRESS_IGNORED_PORTS,22"
    fi

    #
    # End of configurable options
    #

    APPMESH_LOCAL_ROUTE_TABLE_ID="100"
    APPMESH_PACKET_MARK="0x1e7700ce"

    function initialize() {
    echo "=== Initializing ==="
    if [ ! -z "$APPMESH_APP_PORTS" ]; then
    iptables -t mangle -N APPMESH_INGRESS
    iptables -t nat -N APPMESH_INGRESS
    fi
    iptables -t nat -N APPMESH_EGRESS

    ip rule add fwmark "$APPMESH_PACKET_MARK" lookup $APPMESH_LOCAL_ROUTE_TABLE_ID
    ip route add local default dev lo table $APPMESH_LOCAL_ROUTE_TABLE_ID
    }

    function enable_egress_routing() {
    # Stuff to ignore
    [ ! -z "$APPMESH_IGNORE_UID" ] && \
    iptables -t nat -A APPMESH_EGRESS \
    -m owner --uid-owner $APPMESH_IGNORE_UID \
    -j RETURN

    [ ! -z "$APPMESH_IGNORE_GID" ] && \
    iptables -t nat -A APPMESH_EGRESS \
    -m owner --gid-owner $APPMESH_IGNORE_GID \
    -j RETURN

    [ ! -z "$APPMESH_EGRESS_IGNORED_PORTS" ] && \
    iptables -t nat -A APPMESH_EGRESS \
    -p tcp \
    -m multiport --dports "$APPMESH_EGRESS_IGNORED_PORTS" \
    -j RETURN

    [ ! -z "$APPMESH_EGRESS_IGNORED_IP" ] && \
    iptables -t nat -A APPMESH_EGRESS \
    -p tcp \
    -d "$APPMESH_EGRESS_IGNORED_IP" \
    -j RETURN

    # Redirect everything that is not ignored
    iptables -t nat -A APPMESH_EGRESS \
    -p tcp \
    -j REDIRECT --to $APPMESH_ENVOY_EGRESS_PORT

    # Apply APPMESH_EGRESS chain to non local traffic
    iptables -t nat -A OUTPUT \
    -p tcp \
    -m addrtype ! --dst-type LOCAL \
    -j APPMESH_EGRESS
    }

    function enable_ingress_redirect_routing() {
    # Route everything arriving at the application port to Envoy
    iptables -t nat -A APPMESH_INGRESS \
    -p tcp \
    -m multiport --dports "$APPMESH_APP_PORTS" \
    -j REDIRECT --to-port "$APPMESH_ENVOY_INGRESS_PORT"

    # Apply AppMesh ingress chain to everything non-local
    iptables -t nat -A PREROUTING \
    -p tcp \
    -m addrtype ! --src-type LOCAL \
    -j APPMESH_INGRESS
    }

    function enable_routing() {
    echo "=== Enabling routing ==="
    enable_egress_routing
    if [ ! -z "$APPMESH_APP_PORTS" ]; then
    enable_ingress_redirect_routing
    fi
    }

    function disable_routing() {
    echo "=== Disabling routing ==="
    iptables -F
    iptables -F -t nat
    iptables -F -t mangle
    }

    function dump_status() {
    echo "=== Routing rules ==="
    ip rule
    echo "=== AppMesh routing table ==="
    ip route list table $APPMESH_LOCAL_ROUTE_TABLE_ID
    echo "=== iptables FORWARD table ==="
    iptables -L -v -n
    echo "=== iptables NAT table ==="
    iptables -t nat -L -v -n
    echo "=== iptables MANGLE table ==="
    iptables -t mangle -L -v -n
    }

    function main_loop() {
    echo "=== Entering main loop ==="
    while read -p '> ' cmd; do
    case "$cmd" in
    "quit")
    break
    ;;
    "status")
    dump_status
    ;;
    "enable")
    enable_routing
    ;;
    "disable")
    disable_routing
    ;;
    *)
    echo "Available commands: quit, status, enable, disable"
    ;;
    esac
    done
    }

    function print_config() {
    echo "=== Input configuration ==="
    env | grep APPMESH_ || true
    }

    print_config

    initialize

    if [ "$APPMESH_START_ENABLED" == "1" ]; then
    enable_routing
    fi

    main_loop