{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Analyzing public cloud and hybrid networks\n",
"\n",
"Public cloud and hybrid networks can be hard to debug and secure. Many of the standard tools (e.g., traceroute) do not work in the cloud setting, even though the types of paths that can emerge are highly complicated, depending on whether the endpoints are in the same region, different regions, across physical and virtual infrastructure, or whether public or private IPs of cloud instances are being used. \n",
"\n",
"At same time, the fast pace of evolution of these networks, where new subnets and instances can be spun up rapidly by different groups of people, creates a significant security risk. Network engineers need tools than can provide comprehensive guaratnees that services and applications are available and secure as intended at all possible times.\n",
"\n",
"In this notebook, we show how Batfish can predict and help debug network paths for cloud and hybrid networks and how it can guarantee that the network's availability and security posture is exactly as desired."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Import packages\n",
"%run startup.py\n",
"bf = Session(host=\"localhost\")\n",
"\n",
"\n",
"def show_first_trace(trace_answer_frame):\n",
" \"\"\"\n",
" Prints the first trace in the answer frame.\n",
" \n",
" In the presence of multipath routing, Batfish outputs all traces \n",
" from the source to destination. This function picks the first one.\n",
" \"\"\"\n",
" if len(trace_answer_frame) == 0:\n",
" print(\"No flows found\")\n",
" else:\n",
" show(\"Flow: {}\".format(trace_answer_frame.iloc[0]['Flow']))\n",
" show(trace_answer_frame.iloc[0]['Traces'][0])\n",
" \n",
"def is_reachable(start_location, end_location, headers=None):\n",
" \"\"\"\n",
" Checks if the start_location can reach the end_location using specified packet headers.\n",
" \n",
" All possible headers are considered if headers is None. \n",
" \"\"\"\n",
" ans = bf.q.reachability(pathConstraints=PathConstraints(startLocation=start_location, \n",
" endLocation=end_location),\n",
" headers=headers).answer()\n",
" return len(ans.frame()) > 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Initializing the Network and Snapshot\n",
"\n",
"SNAPSHOT_PATH below can be updated to point to a custom snapshot directory. See [instructions](https://github.com/batfish/batfish/wiki/Packaging-snapshots-for-analysis) for how to package data for analysis. "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'snapshot'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Initialize a network and snapshot\n",
"NETWORK_NAME = \"hybrid-cloud\"\n",
"SNAPSHOT_NAME = \"snapshot\"\n",
"\n",
"SNAPSHOT_PATH = \"networks/hybrid-cloud\"\n",
"\n",
"bf.set_network(NETWORK_NAME)\n",
"bf.init_snapshot(SNAPSHOT_PATH, name=SNAPSHOT_NAME, overwrite=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The network snapshot that we just initialized is illustrated below. It has a datacenter network with the standard leaf-spine design on the left. Though not strictly necessary, we have included a host `srv-101` in this network to enable end-to-end analysis. The exit gateway of the datacenter connects to an Internet service provider (ASN 65200) that we call `isp_dc`.\n",
"\n",
"The AWS network is shown on the right. It is spread across two regions, `us-east-2` and `us-west-2`. Each region has two VPCs, one of which is meant to host Internet-facing services and the other is meant to host only private services. Subnets in the public-facing VPCs use an Internet gateway to send and receive traffic outside of AWS. The two VPCs in a region peer via a transit gateway. Each VPC has two subnets, and we have some instances running as well. \n",
"\n",
"The physical network connects to the AWS network using IPSec tunnels, shown in pink, between `exitgw` and the two transit gateways. BGP sessions run atop these tunnels to make endpoints aware of prefixes on the other side.\n",
"\n",
"You can view configuration files that we used [here](https://github.com/batfish/pybatfish/tree/master/jupyter_notebooks/networks/hybrid-cloud). The AWS portion of the configuration is in the aws_configs subfolder. It has JSON files obtained via AWS APIs. An example script that packages AWS data into a Batfish snapshot is [here](https://github.com/ratulm/bf-aws-snapshot).\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Analyzing network paths\n",
"\n",
"Batfish can help analyze cloud and hybrid networks by showing how exactly traffic flows (or not) in the network, which can help debug and fix configuration errors. Batfish can also help ensure that the network is configured exactly as desired, with respect to reachability and security policies. We illustrate these types of analysis below.\n",
"\n",
"First, lets define a couple of maps to help with the analysis."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"#Instances in AWS in each region and VPC type (public, private)\n",
"hosts = {}\n",
"hosts[\"east2_private\"] = \"i-04cd3db5124a05ee6\"\n",
"hosts[\"east2_public\"] = \"i-01602d9efaed4409a\"\n",
"hosts[\"west2_private\"] = \"i-0a5d64b8b58c6dd09\"\n",
"hosts[\"west2_public\"] = \"i-02cae6eaa9edeed70\"\n",
"\n",
"#Public IPs of instances in AWS\n",
"public_ips = {}\n",
"public_ips[\"east2_public\"] = \"13.59.144.125\" # of i-01602d9efaed4409a\n",
"public_ips[\"west2_public\"] = \"54.191.42.182\" # of i-02cae6eaa9edeed70"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Paths across VPCs within an AWS region\n",
"\n",
"To see how traffic flows between two instances in the same region but across different VPCs, say, from `hosts[\"east2_private\"]` to `hosts[\"east2_public\"]`, we can run a traceroute query across them as follows. \n",
"\n",
"In the query below, we use the name of the instance as the destination for the traceroute. This makes Batfish pick the instance's private (i.e., non-Elastic) IP (`10.20.1.207`). It does not pick the public IP because that those IPs do not reside on instances but are used by the Internet gateway to NAT instance's traffic in and out of AWS (see [documentation](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html)). If an instance has multiple private IPs, Batfish will pick one at random. To make Batfish use a specific IP, supply that IP as the argument to the `dstIps` parameter."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Flow: start=i-04cd3db5124a05ee6 [10.30.1.166:49152->10.20.1.207:22 TCP (SYN)]'"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"ACCEPTED
1. node: i-04cd3db5124a05ee6
ORIGINATED(default)
FORWARDED(Forwarded out interface: eni-05452497daf80ccb3 with resolved next-hop IP: 10.30.1.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: ip 10.30.1.1)])
PERMITTED(~EGRESS_ACL~eni-05452497daf80ccb3 (EGRESS_FILTER))
SETUP_SESSION(Incoming Interfaces: [eni-05452497daf80ccb3], Action: Accept, Match Criteria: [ipProtocol=TCP, srcIp=10.20.1.207, dstIp=10.30.1.166, srcPort=22, dstPort=49152])
TRANSMITTED(eni-05452497daf80ccb3)
2. node: subnet-0cb5f4c094bee5214
RECEIVED(to-instances)
FORWARDED(Forwarded out interface: vpc-0276455718806058a-vrf-tgw-attach-021f89744fac566dd with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 10.20.0.0/16, Next Hop: interface vpc-0276455718806058a-vrf-tgw-attach-021f89744fac566dd ip 169.254.0.1)])
PERMITTED(acl-0b3d0f6b0978f09f8_egress (EGRESS_FILTER))
TRANSMITTED(vpc-0276455718806058a-vrf-tgw-attach-021f89744fac566dd)
3. node: vpc-0276455718806058a
RECEIVED(subnet-0cb5f4c094bee5214-vrf-tgw-attach-021f89744fac566dd)
FORWARDED(Forwarded out interface: tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03 ip 169.254.0.1)])
TRANSMITTED(tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03)
4. node: tgw-06b348adabd13452d
RECEIVED(vpc-0276455718806058a-tgw-rtb-00e37bc5142347b03)
FORWARDED(Forwarded out interface: vpc-0574d08f8d05917e4-tgw-rtb-00e37bc5142347b03 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 10.20.0.0/16, Next Hop: interface vpc-0574d08f8d05917e4-tgw-rtb-00e37bc5142347b03 ip 169.254.0.1)])
TRANSMITTED(vpc-0574d08f8d05917e4-tgw-rtb-00e37bc5142347b03)
5. node: vpc-0574d08f8d05917e4
RECEIVED(tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03)
FORWARDED(Forwarded out interface: subnet-06a692ed4ef84368d-vrf-tgw-attach-0648110513acd6de5 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 10.20.1.0/24, Next Hop: interface subnet-06a692ed4ef84368d-vrf-tgw-attach-0648110513acd6de5 ip 169.254.0.1)])
TRANSMITTED(subnet-06a692ed4ef84368d-vrf-tgw-attach-0648110513acd6de5)
6. node: subnet-06a692ed4ef84368d
RECEIVED(vpc-0574d08f8d05917e4-vrf-tgw-attach-0648110513acd6de5)
PERMITTED(acl-09c0bb4e71ae5f9e4_ingress (INGRESS_FILTER))
FORWARDED(Forwarded out interface: to-instances, Routes: [connected (Network: 10.20.1.0/24, Next Hop: interface to-instances)])
TRANSMITTED(to-instances)
7. node: i-01602d9efaed4409a
RECEIVED(eni-01997085076a9b98a)
PERMITTED(~INGRESS_ACL~eni-01997085076a9b98a (INGRESS_FILTER))
SETUP_SESSION(Originating VRF: default, Action: ForwardOutInterface(Next Hop: subnet-06a692ed4ef84368d, Next Hop Interface: to-instances, Outgoing Interface: eni-01997085076a9b98a), Match Criteria: [ipProtocol=TCP, srcIp=10.20.1.207, dstIp=10.30.1.166, srcPort=22, dstPort=49152])
ACCEPTED(eni-01997085076a9b98a)"
],
"text/plain": [
"Trace(disposition='ACCEPTED', hops=[Hop(node='i-04cd3db5124a05ee6', steps=[Step(detail=OriginateStepDetail(originatingVrf='default'), action='ORIGINATED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='0.0.0.0/0', nextHop=NextHopIp(ip='10.30.1.1', type='ip'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='eni-05452497daf80ccb3', resolvedNextHopIp='10.30.1.1', type='ForwardedOutInterface'), arpIp='10.30.1.1', outputInterface='eni-05452497daf80ccb3'), action='FORWARDED'), Step(detail=FilterStepDetail(filter='~EGRESS_ACL~eni-05452497daf80ccb3', filterType='EGRESS_FILTER', inputInterface='', flow=Flow(dscp=0, dstIp='10.20.1.207', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-04cd3db5124a05ee6', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.30.1.166', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=SetupSessionStepDetail(sessionScope=IncomingSessionScope(incomingInterfaces=['eni-05452497daf80ccb3']), sessionAction=Accept(), matchCriteria=SessionMatchExpr(ipProtocol='TCP', srcIp='10.20.1.207', dstIp='10.30.1.166', srcPort=22, dstPort=49152), transformation=[]), action='SETUP_SESSION'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='eni-05452497daf80ccb3', transformedFlow=None), action='TRANSMITTED')]), Hop(node='subnet-0cb5f4c094bee5214', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='to-instances', inputVrf='default'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='10.20.0.0/16', nextHop=NextHopInterface(interface='vpc-0276455718806058a-vrf-tgw-attach-021f89744fac566dd', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='vpc-0276455718806058a-vrf-tgw-attach-021f89744fac566dd', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='vpc-0276455718806058a-vrf-tgw-attach-021f89744fac566dd'), action='FORWARDED'), Step(detail=FilterStepDetail(filter='acl-0b3d0f6b0978f09f8_egress', filterType='EGRESS_FILTER', inputInterface='to-instances', flow=Flow(dscp=0, dstIp='10.20.1.207', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-04cd3db5124a05ee6', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.30.1.166', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='vpc-0276455718806058a-vrf-tgw-attach-021f89744fac566dd', transformedFlow=None), action='TRANSMITTED')]), Hop(node='vpc-0276455718806058a', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='subnet-0cb5f4c094bee5214-vrf-tgw-attach-021f89744fac566dd', inputVrf='vrf-tgw-attach-021f89744fac566dd'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='0.0.0.0/0', nextHop=NextHopInterface(interface='tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03', transformedFlow=None), action='TRANSMITTED')]), Hop(node='tgw-06b348adabd13452d', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='vpc-0276455718806058a-tgw-rtb-00e37bc5142347b03', inputVrf='vrf-tgw-rtb-00e37bc5142347b03'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='10.20.0.0/16', nextHop=NextHopInterface(interface='vpc-0574d08f8d05917e4-tgw-rtb-00e37bc5142347b03', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='vpc-0574d08f8d05917e4-tgw-rtb-00e37bc5142347b03', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='vpc-0574d08f8d05917e4-tgw-rtb-00e37bc5142347b03'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='vpc-0574d08f8d05917e4-tgw-rtb-00e37bc5142347b03', transformedFlow=None), action='TRANSMITTED')]), Hop(node='vpc-0574d08f8d05917e4', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='tgw-06b348adabd13452d-tgw-rtb-00e37bc5142347b03', inputVrf='vrf-tgw-attach-0648110513acd6de5'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='10.20.1.0/24', nextHop=NextHopInterface(interface='subnet-06a692ed4ef84368d-vrf-tgw-attach-0648110513acd6de5', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='subnet-06a692ed4ef84368d-vrf-tgw-attach-0648110513acd6de5', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='subnet-06a692ed4ef84368d-vrf-tgw-attach-0648110513acd6de5'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='subnet-06a692ed4ef84368d-vrf-tgw-attach-0648110513acd6de5', transformedFlow=None), action='TRANSMITTED')]), Hop(node='subnet-06a692ed4ef84368d', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='vpc-0574d08f8d05917e4-vrf-tgw-attach-0648110513acd6de5', inputVrf='default'), action='RECEIVED'), Step(detail=FilterStepDetail(filter='acl-09c0bb4e71ae5f9e4_ingress', filterType='INGRESS_FILTER', inputInterface='vpc-0574d08f8d05917e4-vrf-tgw-attach-0648110513acd6de5', flow=Flow(dscp=0, dstIp='10.20.1.207', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-04cd3db5124a05ee6', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.30.1.166', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='connected', network='10.20.1.0/24', nextHop=NextHopInterface(interface='to-instances', ip=None, type='interface'), nextHopIp=None, admin=0, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='to-instances', resolvedNextHopIp=None, type='ForwardedOutInterface'), arpIp=None, outputInterface='to-instances'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='to-instances', transformedFlow=None), action='TRANSMITTED')]), Hop(node='i-01602d9efaed4409a', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='eni-01997085076a9b98a', inputVrf='default'), action='RECEIVED'), Step(detail=FilterStepDetail(filter='~INGRESS_ACL~eni-01997085076a9b98a', filterType='INGRESS_FILTER', inputInterface='eni-01997085076a9b98a', flow=Flow(dscp=0, dstIp='10.20.1.207', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-04cd3db5124a05ee6', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.30.1.166', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=SetupSessionStepDetail(sessionScope=OriginatingSessionScope(originatingVrf='default'), sessionAction=ForwardOutInterface(nextHopHostname='subnet-06a692ed4ef84368d', nextHopInterface='to-instances', outgoingInterface='eni-01997085076a9b98a'), matchCriteria=SessionMatchExpr(ipProtocol='TCP', srcIp='10.20.1.207', dstIp='10.30.1.166', srcPort=22, dstPort=49152), transformation=[]), action='SETUP_SESSION'), Step(detail=InboundStepDetail(interface='eni-01997085076a9b98a'), action='ACCEPTED')])])"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# traceroute between instances in the same region, using SSH\n",
"ans = bf.q.traceroute(startLocation=hosts[\"east2_private\"], \n",
" headers=HeaderConstraints(dstIps=hosts[\"east2_public\"], \n",
" applications=\"ssh\")).answer()\n",
"show_first_trace(ans.frame())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The trace above shows how traffic goes from `host[\"east2_private\"]` to `host[\"east2_public\"]` -- via the source subnet and VPC, then to the transit gateway, and finally to the destination VPC and subnet. Along the way, it also shows where the flow encounters security groups (at both instances) and network ACLs (at subnets). In this instance, all security groups and network ACLs permit this particular flow.\n",
"\n",
"This type of insight into traffic paths, which helps understand and debug network configuration, is difficult to obtain otherwise. Traceroutes on the live AWS network do not yield any information if the flow does not make it through, and do not show why or where a packet is dropped."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Paths across AWS regions\n",
"\n",
"The traceroute query below shows paths across instances in two different regions."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Flow: start=i-01602d9efaed4409a [10.20.1.207:49152->10.40.2.80:22 TCP (SYN)]'"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"DENIED_OUT
1. node: i-01602d9efaed4409a
ORIGINATED(default)
FORWARDED(Forwarded out interface: eni-01997085076a9b98a with resolved next-hop IP: 10.20.1.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: ip 10.20.1.1)])
PERMITTED(~EGRESS_ACL~eni-01997085076a9b98a (EGRESS_FILTER))
SETUP_SESSION(Incoming Interfaces: [eni-01997085076a9b98a], Action: Accept, Match Criteria: [ipProtocol=TCP, srcIp=10.40.2.80, dstIp=10.20.1.207, srcPort=22, dstPort=49152])
TRANSMITTED(eni-01997085076a9b98a)
2. node: subnet-06a692ed4ef84368d
RECEIVED(to-instances)
FORWARDED(Forwarded out interface: vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7 ip 169.254.0.1)])
PERMITTED(acl-09c0bb4e71ae5f9e4_egress (EGRESS_FILTER))
TRANSMITTED(vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7)
3. node: vpc-0574d08f8d05917e4
RECEIVED(subnet-06a692ed4ef84368d-vrf-igw-02fd68f94367a67c7)
FORWARDED(Forwarded out interface: igw-02fd68f94367a67c7 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface igw-02fd68f94367a67c7 ip 169.254.0.1)])
TRANSMITTED(igw-02fd68f94367a67c7)
4. node: igw-02fd68f94367a67c7
RECEIVED(vpc-0574d08f8d05917e4)
PERMITTED(~DENY~UNASSOCIATED~PRIVATE~IPs~ (INGRESS_FILTER))
FORWARDED(Forwarded out interface: backbone with resolved next-hop IP: 169.254.0.1, Routes: [bgp (Network: 0.0.0.0/0, Next Hop: interface backbone ip 169.254.0.1)])
TRANSFORMED(SOURCE_NAT srcIp: 10.20.1.207 -> 13.59.144.125)
TRANSMITTED(backbone)
5. node: isp_16509
RECEIVED(To-igw-02fd68f94367a67c7-backbone)
FORWARDED(Forwarded out interface: To-Internet with resolved next-hop IP: 169.254.0.1, Routes: [bgp (Network: 0.0.0.0/0, Next Hop: interface To-Internet ip 169.254.0.1)])
DENIED(Block outgoing traffic using reserved addresses (EGRESS_FILTER))"
],
"text/plain": [
"Trace(disposition='DENIED_OUT', hops=[Hop(node='i-01602d9efaed4409a', steps=[Step(detail=OriginateStepDetail(originatingVrf='default'), action='ORIGINATED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='0.0.0.0/0', nextHop=NextHopIp(ip='10.20.1.1', type='ip'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='eni-01997085076a9b98a', resolvedNextHopIp='10.20.1.1', type='ForwardedOutInterface'), arpIp='10.20.1.1', outputInterface='eni-01997085076a9b98a'), action='FORWARDED'), Step(detail=FilterStepDetail(filter='~EGRESS_ACL~eni-01997085076a9b98a', filterType='EGRESS_FILTER', inputInterface='', flow=Flow(dscp=0, dstIp='10.40.2.80', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.20.1.207', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=SetupSessionStepDetail(sessionScope=IncomingSessionScope(incomingInterfaces=['eni-01997085076a9b98a']), sessionAction=Accept(), matchCriteria=SessionMatchExpr(ipProtocol='TCP', srcIp='10.40.2.80', dstIp='10.20.1.207', srcPort=22, dstPort=49152), transformation=[]), action='SETUP_SESSION'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='eni-01997085076a9b98a', transformedFlow=None), action='TRANSMITTED')]), Hop(node='subnet-06a692ed4ef84368d', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='to-instances', inputVrf='default'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='0.0.0.0/0', nextHop=NextHopInterface(interface='vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7'), action='FORWARDED'), Step(detail=FilterStepDetail(filter='acl-09c0bb4e71ae5f9e4_egress', filterType='EGRESS_FILTER', inputInterface='to-instances', flow=Flow(dscp=0, dstIp='10.40.2.80', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.20.1.207', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7', transformedFlow=None), action='TRANSMITTED')]), Hop(node='vpc-0574d08f8d05917e4', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='subnet-06a692ed4ef84368d-vrf-igw-02fd68f94367a67c7', inputVrf='vrf-igw-02fd68f94367a67c7'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='0.0.0.0/0', nextHop=NextHopInterface(interface='igw-02fd68f94367a67c7', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='igw-02fd68f94367a67c7', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='igw-02fd68f94367a67c7'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='igw-02fd68f94367a67c7', transformedFlow=None), action='TRANSMITTED')]), Hop(node='igw-02fd68f94367a67c7', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='vpc-0574d08f8d05917e4', inputVrf='default'), action='RECEIVED'), Step(detail=FilterStepDetail(filter='~DENY~UNASSOCIATED~PRIVATE~IPs~', filterType='INGRESS_FILTER', inputInterface='vpc-0574d08f8d05917e4', flow=Flow(dscp=0, dstIp='10.40.2.80', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.20.1.207', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='bgp', network='0.0.0.0/0', nextHop=NextHopInterface(interface='backbone', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=20, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='backbone', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='backbone'), action='FORWARDED'), Step(detail=TransformationStepDetail(transformationType='SOURCE_NAT', flowDiffs=[FlowDiff(fieldName='srcIp', oldValue='10.20.1.207', newValue='13.59.144.125')]), action='TRANSFORMED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='backbone', transformedFlow={'dscp': 0, 'dstIp': '10.40.2.80', 'dstPort': 22, 'ecn': 0, 'fragmentOffset': 0, 'ingressNode': 'i-01602d9efaed4409a', 'ingressVrf': 'default', 'ipProtocol': 'TCP', 'packetLength': 512, 'srcIp': '13.59.144.125', 'srcPort': 49152, 'state': 'NEW', 'tag': 'tag', 'tcpFlagsAck': 0, 'tcpFlagsCwr': 0, 'tcpFlagsEce': 0, 'tcpFlagsFin': 0, 'tcpFlagsPsh': 0, 'tcpFlagsRst': 0, 'tcpFlagsSyn': 1, 'tcpFlagsUrg': 0}), action='TRANSMITTED')]), Hop(node='isp_16509', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='To-igw-02fd68f94367a67c7-backbone', inputVrf='default'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='bgp', network='0.0.0.0/0', nextHop=NextHopInterface(interface='To-Internet', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=20, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='To-Internet', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='To-Internet'), action='FORWARDED'), Step(detail=FilterStepDetail(filter='Block outgoing traffic using reserved addresses', filterType='EGRESS_FILTER', inputInterface='To-igw-02fd68f94367a67c7-backbone', flow=Flow(dscp=0, dstIp='10.40.2.80', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='13.59.144.125', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='DENIED')])])"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# traceroute between instances across region using the destination's private IP\n",
"ans = bf.q.traceroute(startLocation=hosts[\"east2_public\"], \n",
" headers=HeaderConstraints(dstIps=hosts[\"west2_public\"],\n",
" applications=\"ssh\")).answer()\n",
"show_first_trace(ans.frame())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that such traffic does not reach the destination but instead is dropped by the AWS backbone (ASN 16509). This happens because, in our network, there is no (transit gateway or VPC) peering between VPCs in different regions. So, the source subnet is unaware of the address space of the destination subnet, which makes it use the default route that points to the Internet gateway (`igw-02fd68f94367a67c7`). The Internet gateway forwards the packet to `aws-backbone`, after NAT'ing its source IP. The packet is eventually dropped as it is using a private address as destination. Recall that using the instance name as destination amounts to using its private IP.\n",
"\n",
"The behavior is different if we use the public IP instead, as shown below."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Flow: start=i-01602d9efaed4409a [10.20.1.207:49152->54.191.42.182:22 TCP (SYN)]'"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"ACCEPTED
1. node: i-01602d9efaed4409a
ORIGINATED(default)
FORWARDED(Forwarded out interface: eni-01997085076a9b98a with resolved next-hop IP: 10.20.1.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: ip 10.20.1.1)])
PERMITTED(~EGRESS_ACL~eni-01997085076a9b98a (EGRESS_FILTER))
SETUP_SESSION(Incoming Interfaces: [eni-01997085076a9b98a], Action: Accept, Match Criteria: [ipProtocol=TCP, srcIp=54.191.42.182, dstIp=10.20.1.207, srcPort=22, dstPort=49152])
TRANSMITTED(eni-01997085076a9b98a)
2. node: subnet-06a692ed4ef84368d
RECEIVED(to-instances)
FORWARDED(Forwarded out interface: vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7 ip 169.254.0.1)])
PERMITTED(acl-09c0bb4e71ae5f9e4_egress (EGRESS_FILTER))
TRANSMITTED(vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7)
3. node: vpc-0574d08f8d05917e4
RECEIVED(subnet-06a692ed4ef84368d-vrf-igw-02fd68f94367a67c7)
FORWARDED(Forwarded out interface: igw-02fd68f94367a67c7 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface igw-02fd68f94367a67c7 ip 169.254.0.1)])
TRANSMITTED(igw-02fd68f94367a67c7)
4. node: igw-02fd68f94367a67c7
RECEIVED(vpc-0574d08f8d05917e4)
PERMITTED(~DENY~UNASSOCIATED~PRIVATE~IPs~ (INGRESS_FILTER))
FORWARDED(Forwarded out interface: backbone with resolved next-hop IP: 169.254.0.1, Routes: [bgp (Network: 0.0.0.0/0, Next Hop: interface backbone ip 169.254.0.1)])
TRANSFORMED(SOURCE_NAT srcIp: 10.20.1.207 -> 13.59.144.125)
TRANSMITTED(backbone)
5. node: isp_16509
RECEIVED(To-igw-02fd68f94367a67c7-backbone)
FORWARDED(Forwarded out interface: To-igw-0a8309f3192e7cea3-backbone with resolved next-hop IP: 169.254.0.1, Routes: [bgp (Network: 54.191.42.182/32, Next Hop: interface To-igw-0a8309f3192e7cea3-backbone ip 169.254.0.1)])
TRANSMITTED(To-igw-0a8309f3192e7cea3-backbone)
6. node: igw-0a8309f3192e7cea3
RECEIVED(backbone)
TRANSFORMED(DEST_NAT dstIp: 54.191.42.182 -> 10.40.2.80)
FORWARDED(Forwarded out interface: vpc-00b65e98077106059 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 10.40.0.0/16, Next Hop: interface vpc-00b65e98077106059 ip 169.254.0.1)])
TRANSMITTED(vpc-00b65e98077106059)
7. node: vpc-00b65e98077106059
RECEIVED(igw-0a8309f3192e7cea3)
FORWARDED(Forwarded out interface: subnet-06005943afe32f714-vrf-igw-0a8309f3192e7cea3 with resolved next-hop IP: 169.254.0.1, Routes: [static (Network: 10.40.2.0/24, Next Hop: interface subnet-06005943afe32f714-vrf-igw-0a8309f3192e7cea3 ip 169.254.0.1)])
TRANSMITTED(subnet-06005943afe32f714-vrf-igw-0a8309f3192e7cea3)
8. node: subnet-06005943afe32f714
RECEIVED(vpc-00b65e98077106059-vrf-igw-0a8309f3192e7cea3)
PERMITTED(acl-087574e8620270842_ingress (INGRESS_FILTER))
FORWARDED(Forwarded out interface: to-instances, Routes: [connected (Network: 10.40.2.0/24, Next Hop: interface to-instances)])
TRANSMITTED(to-instances)
9. node: i-02cae6eaa9edeed70
RECEIVED(eni-087e18628dadd9b48)
PERMITTED(~INGRESS_ACL~eni-087e18628dadd9b48 (INGRESS_FILTER))
SETUP_SESSION(Originating VRF: default, Action: ForwardOutInterface(Next Hop: subnet-06005943afe32f714, Next Hop Interface: to-instances, Outgoing Interface: eni-087e18628dadd9b48), Match Criteria: [ipProtocol=TCP, srcIp=10.40.2.80, dstIp=13.59.144.125, srcPort=22, dstPort=49152])
ACCEPTED(eni-087e18628dadd9b48)"
],
"text/plain": [
"Trace(disposition='ACCEPTED', hops=[Hop(node='i-01602d9efaed4409a', steps=[Step(detail=OriginateStepDetail(originatingVrf='default'), action='ORIGINATED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='0.0.0.0/0', nextHop=NextHopIp(ip='10.20.1.1', type='ip'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='eni-01997085076a9b98a', resolvedNextHopIp='10.20.1.1', type='ForwardedOutInterface'), arpIp='10.20.1.1', outputInterface='eni-01997085076a9b98a'), action='FORWARDED'), Step(detail=FilterStepDetail(filter='~EGRESS_ACL~eni-01997085076a9b98a', filterType='EGRESS_FILTER', inputInterface='', flow=Flow(dscp=0, dstIp='54.191.42.182', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.20.1.207', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=SetupSessionStepDetail(sessionScope=IncomingSessionScope(incomingInterfaces=['eni-01997085076a9b98a']), sessionAction=Accept(), matchCriteria=SessionMatchExpr(ipProtocol='TCP', srcIp='54.191.42.182', dstIp='10.20.1.207', srcPort=22, dstPort=49152), transformation=[]), action='SETUP_SESSION'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='eni-01997085076a9b98a', transformedFlow=None), action='TRANSMITTED')]), Hop(node='subnet-06a692ed4ef84368d', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='to-instances', inputVrf='default'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='0.0.0.0/0', nextHop=NextHopInterface(interface='vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7'), action='FORWARDED'), Step(detail=FilterStepDetail(filter='acl-09c0bb4e71ae5f9e4_egress', filterType='EGRESS_FILTER', inputInterface='to-instances', flow=Flow(dscp=0, dstIp='54.191.42.182', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.20.1.207', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='vpc-0574d08f8d05917e4-vrf-igw-02fd68f94367a67c7', transformedFlow=None), action='TRANSMITTED')]), Hop(node='vpc-0574d08f8d05917e4', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='subnet-06a692ed4ef84368d-vrf-igw-02fd68f94367a67c7', inputVrf='vrf-igw-02fd68f94367a67c7'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='0.0.0.0/0', nextHop=NextHopInterface(interface='igw-02fd68f94367a67c7', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='igw-02fd68f94367a67c7', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='igw-02fd68f94367a67c7'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='igw-02fd68f94367a67c7', transformedFlow=None), action='TRANSMITTED')]), Hop(node='igw-02fd68f94367a67c7', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='vpc-0574d08f8d05917e4', inputVrf='default'), action='RECEIVED'), Step(detail=FilterStepDetail(filter='~DENY~UNASSOCIATED~PRIVATE~IPs~', filterType='INGRESS_FILTER', inputInterface='vpc-0574d08f8d05917e4', flow=Flow(dscp=0, dstIp='54.191.42.182', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='10.20.1.207', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='bgp', network='0.0.0.0/0', nextHop=NextHopInterface(interface='backbone', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=20, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='backbone', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='backbone'), action='FORWARDED'), Step(detail=TransformationStepDetail(transformationType='SOURCE_NAT', flowDiffs=[FlowDiff(fieldName='srcIp', oldValue='10.20.1.207', newValue='13.59.144.125')]), action='TRANSFORMED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='backbone', transformedFlow={'dscp': 0, 'dstIp': '54.191.42.182', 'dstPort': 22, 'ecn': 0, 'fragmentOffset': 0, 'ingressNode': 'i-01602d9efaed4409a', 'ingressVrf': 'default', 'ipProtocol': 'TCP', 'packetLength': 512, 'srcIp': '13.59.144.125', 'srcPort': 49152, 'state': 'NEW', 'tag': 'tag', 'tcpFlagsAck': 0, 'tcpFlagsCwr': 0, 'tcpFlagsEce': 0, 'tcpFlagsFin': 0, 'tcpFlagsPsh': 0, 'tcpFlagsRst': 0, 'tcpFlagsSyn': 1, 'tcpFlagsUrg': 0}), action='TRANSMITTED')]), Hop(node='isp_16509', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='To-igw-02fd68f94367a67c7-backbone', inputVrf='default'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='bgp', network='54.191.42.182/32', nextHop=NextHopInterface(interface='To-igw-0a8309f3192e7cea3-backbone', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=20, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='To-igw-0a8309f3192e7cea3-backbone', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='To-igw-0a8309f3192e7cea3-backbone'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='To-igw-0a8309f3192e7cea3-backbone', transformedFlow=None), action='TRANSMITTED')]), Hop(node='igw-0a8309f3192e7cea3', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='backbone', inputVrf='default'), action='RECEIVED'), Step(detail=TransformationStepDetail(transformationType='DEST_NAT', flowDiffs=[FlowDiff(fieldName='dstIp', oldValue='54.191.42.182', newValue='10.40.2.80')]), action='TRANSFORMED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='10.40.0.0/16', nextHop=NextHopInterface(interface='vpc-00b65e98077106059', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='vpc-00b65e98077106059', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='vpc-00b65e98077106059'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='vpc-00b65e98077106059', transformedFlow={'dscp': 0, 'dstIp': '10.40.2.80', 'dstPort': 22, 'ecn': 0, 'fragmentOffset': 0, 'ingressNode': 'i-01602d9efaed4409a', 'ingressVrf': 'default', 'ipProtocol': 'TCP', 'packetLength': 512, 'srcIp': '13.59.144.125', 'srcPort': 49152, 'state': 'NEW', 'tag': 'tag', 'tcpFlagsAck': 0, 'tcpFlagsCwr': 0, 'tcpFlagsEce': 0, 'tcpFlagsFin': 0, 'tcpFlagsPsh': 0, 'tcpFlagsRst': 0, 'tcpFlagsSyn': 1, 'tcpFlagsUrg': 0}), action='TRANSMITTED')]), Hop(node='vpc-00b65e98077106059', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='igw-0a8309f3192e7cea3', inputVrf='vrf-igw-0a8309f3192e7cea3'), action='RECEIVED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='static', network='10.40.2.0/24', nextHop=NextHopInterface(interface='subnet-06005943afe32f714-vrf-igw-0a8309f3192e7cea3', ip='169.254.0.1', type='interface'), nextHopIp=None, admin=1, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='subnet-06005943afe32f714-vrf-igw-0a8309f3192e7cea3', resolvedNextHopIp='169.254.0.1', type='ForwardedOutInterface'), arpIp='169.254.0.1', outputInterface='subnet-06005943afe32f714-vrf-igw-0a8309f3192e7cea3'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='subnet-06005943afe32f714-vrf-igw-0a8309f3192e7cea3', transformedFlow=None), action='TRANSMITTED')]), Hop(node='subnet-06005943afe32f714', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='vpc-00b65e98077106059-vrf-igw-0a8309f3192e7cea3', inputVrf='default'), action='RECEIVED'), Step(detail=FilterStepDetail(filter='acl-087574e8620270842_ingress', filterType='INGRESS_FILTER', inputInterface='vpc-00b65e98077106059-vrf-igw-0a8309f3192e7cea3', flow=Flow(dscp=0, dstIp='10.40.2.80', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='13.59.144.125', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=RoutingStepDetail(routes=[RouteInfo(protocol='connected', network='10.40.2.0/24', nextHop=NextHopInterface(interface='to-instances', ip=None, type='interface'), nextHopIp=None, admin=0, metric=0)], forwardingDetail=ForwardedOutInterface(outputInterface='to-instances', resolvedNextHopIp=None, type='ForwardedOutInterface'), arpIp=None, outputInterface='to-instances'), action='FORWARDED'), Step(detail=ExitOutputIfaceStepDetail(outputInterface='to-instances', transformedFlow=None), action='TRANSMITTED')]), Hop(node='i-02cae6eaa9edeed70', steps=[Step(detail=EnterInputIfaceStepDetail(inputInterface='eni-087e18628dadd9b48', inputVrf='default'), action='RECEIVED'), Step(detail=FilterStepDetail(filter='~INGRESS_ACL~eni-087e18628dadd9b48', filterType='INGRESS_FILTER', inputInterface='eni-087e18628dadd9b48', flow=Flow(dscp=0, dstIp='10.40.2.80', dstPort=22, ecn=0, fragmentOffset=0, icmpCode=None, icmpVar=None, ingressInterface=None, ingressNode='i-01602d9efaed4409a', ingressVrf='default', ipProtocol='TCP', packetLength=512, srcIp='13.59.144.125', srcPort=49152, tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=1, tcpFlagsUrg=0)), action='PERMITTED'), Step(detail=SetupSessionStepDetail(sessionScope=OriginatingSessionScope(originatingVrf='default'), sessionAction=ForwardOutInterface(nextHopHostname='subnet-06005943afe32f714', nextHopInterface='to-instances', outgoingInterface='eni-087e18628dadd9b48'), matchCriteria=SessionMatchExpr(ipProtocol='TCP', srcIp='10.40.2.80', dstIp='13.59.144.125', srcPort=22, dstPort=49152), transformation=[]), action='SETUP_SESSION'), Step(detail=InboundStepDetail(interface='eni-087e18628dadd9b48'), action='ACCEPTED')])])"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# traceroute betwee instances across region using the destination's public IP\n",
"ans = bf.q.traceroute(startLocation=hosts[\"east2_public\"], \n",
" headers=HeaderConstraints(dstIps=public_ips[\"west2_public\"],\n",
" applications=\"ssh\")).answer()\n",
"show_first_trace(ans.frame())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This traceroute starts out like the previous one, up until the AWS backbone (`isp_16509`) -- from source subnet to the Internet gateway which forwards it to the backbone, after source NAT'ing the packet. The backbone carries it to the internet gateway in the destination region (`igw-0a8309f3192e7cea3`), and this gateway NATs the packet's destination from the public IP to the instance's private IP. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Connectivity between DC and AWS\n",
"\n",
"A common mode to connect to AWS is using VPNs and BGP, that is, establish IPSec tunnels between exit gateways on the physical side and AWS gateways and run BGP on top of these tunnels to exchange prefixes. Incompatibility in either IPSec or BGP settings on the two sides means that connectivity between the DC and AWS will not work. \n",
"\n",
"Batfish can determine if the two sides are compatibly configured with respect to IPSec and BGP settings and if those sessions will come up. \n",
"\n",
"The query below lists the status of all IPSec sessions between the `exitgw` and AWS transit gateways (specified using the regular expression `^tgw-` that matches those node names). This filtering lets us ignore any other IPSec sessions that may exist in our network and focus on DC-AWS connectivity."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"
| \n", " | Node | \n", "Node_Interface | \n", "Node_IP | \n", "Remote_Node | \n", "Remote_Node_Interface | \n", "Remote_Node_IP | \n", "Tunnel_Interfaces | \n", "Status | \n", "
|---|---|---|---|---|---|---|---|---|
| 0 | \n", "exitgw | \n", "exitgw[GigabitEthernet3] | \n", "147.75.69.27 | \n", "tgw-06b348adabd13452d | \n", "tgw-06b348adabd13452d[external-vpn-01c45673532d3e33e-1] | \n", "3.19.24.131 | \n", "Tunnel1 -> vpn-vpn-01c45673532d3e33e-1 | \n", "IPSEC_SESSION_ESTABLISHED | \n", "
| 1 | \n", "exitgw | \n", "exitgw[GigabitEthernet3] | \n", "147.75.69.27 | \n", "tgw-06b348adabd13452d | \n", "tgw-06b348adabd13452d[external-vpn-01c45673532d3e33e-2] | \n", "52.14.53.162 | \n", "Tunnel2 -> vpn-vpn-01c45673532d3e33e-2 | \n", "IPSEC_SESSION_ESTABLISHED | \n", "
| 2 | \n", "exitgw | \n", "exitgw[GigabitEthernet3] | \n", "147.75.69.27 | \n", "tgw-0888a76c8a371246d | \n", "tgw-0888a76c8a371246d[external-vpn-0dc7abdb974ff8a69-1] | \n", "34.209.88.227 | \n", "Tunnel3 -> vpn-vpn-0dc7abdb974ff8a69-1 | \n", "IPSEC_SESSION_ESTABLISHED | \n", "
| 3 | \n", "exitgw | \n", "exitgw[GigabitEthernet3] | \n", "147.75.69.27 | \n", "tgw-0888a76c8a371246d | \n", "tgw-0888a76c8a371246d[external-vpn-0dc7abdb974ff8a69-2] | \n", "44.227.244.7 | \n", "Tunnel4 -> vpn-vpn-0dc7abdb974ff8a69-2 | \n", "IPSEC_SESSION_ESTABLISHED | \n", "
| \n", " | Node | \n", "VRF | \n", "Local_AS | \n", "Local_Interface | \n", "Local_IP | \n", "Remote_AS | \n", "Remote_Node | \n", "Remote_Interface | \n", "Remote_IP | \n", "Address_Families | \n", "Session_Type | \n", "Established_Status | \n", "
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | \n", "exitgw | \n", "default | \n", "65100 | \n", "None | \n", "169.254.252.78 | \n", "64512 | \n", "tgw-0888a76c8a371246d | \n", "None | \n", "169.254.252.77 | \n", "IPV4_UNICAST | \n", "EBGP_SINGLEHOP | \n", "ESTABLISHED | \n", "
| 1 | \n", "exitgw | \n", "default | \n", "65100 | \n", "None | \n", "169.254.25.162 | \n", "64512 | \n", "tgw-06b348adabd13452d | \n", "None | \n", "169.254.25.161 | \n", "IPV4_UNICAST | \n", "EBGP_SINGLEHOP | \n", "ESTABLISHED | \n", "
| 2 | \n", "exitgw | \n", "default | \n", "65100 | \n", "None | \n", "169.254.172.2 | \n", "64512 | \n", "tgw-06b348adabd13452d | \n", "None | \n", "169.254.172.1 | \n", "IPV4_UNICAST | \n", "EBGP_SINGLEHOP | \n", "ESTABLISHED | \n", "
| 3 | \n", "exitgw | \n", "default | \n", "65100 | \n", "None | \n", "169.254.215.82 | \n", "64512 | \n", "tgw-0888a76c8a371246d | \n", "None | \n", "169.254.215.81 | \n", "IPV4_UNICAST | \n", "EBGP_SINGLEHOP | \n", "ESTABLISHED | \n", "
| \n", " | Node | \n", "Filter_Name | \n", "Flow | \n", "Action | \n", "Line_Content | \n", "Trace | \n", "
|---|---|---|---|---|---|---|
| 0 | \n", "i-01602d9efaed4409a | \n", "~INGRESS_ACL~eni-01997085076a9b98a | \n", "Start Location: i-01602d9efaed4409a Src IP: 8.8.8.8 Src Port: 49152 Dst IP: 10.20.1.207 Dst Port: 3306 IP Protocol: TCP (SYN) | \n",
" PERMIT | \n", "Security Group launch-wizard-1 | \n", "
| \n",
"