def _NlAttrTcpMetricsAddr(self, address, is_source):
     version = net_test.GetAddressVersion(address)
     family = net_test.GetAddressFamily(version)
     if version == 5:
         address = address.replace("::ffff:", "")
     nla_name = "TCP_METRICS_ATTR_%s_IPV%d" % ("SADDR" if is_source else
                                               "ADDR", version)
     nla_type = globals()[nla_name]
     return self._NlAttrIPAddress(nla_type, family, address)
Ejemplo n.º 2
0
  def CreateTunnel(self, direction, selector, src, dst, spi, encryption,
                   auth_trunc, mark, output_mark, xfrm_if_id):
    """Create an XFRM Tunnel Consisting of a Policy and an SA.

    Create a unidirectional XFRM tunnel, which entails one Policy and one
    security association.

    Args:
      direction: XFRM_POLICY_IN or XFRM_POLICY_OUT
      selector: An XfrmSelector that specifies the packets to be transformed.
        This is only applied to the policy; the selector in the SA is always
        empty. If the passed-in selector is None, then the tunnel is made
        dual-stack. This requires two policies, one for IPv4 and one for IPv6.
      src: The source address of the tunneled packets
      dst: The destination address of the tunneled packets
      spi: The SPI for the IPsec SA that encapsulates the tunneled packet
      encryption: A tuple (XfrmAlgo, key), the encryption parameters.
      auth_trunc: A tuple (XfrmAlgoAuth, key), the authentication parameters.
      mark: An XfrmMark, the mark used for selecting packets to be tunneled, and
        for matching the security policy and security association. None means
        unspecified.
      output_mark: The mark used to select the underlying network for packets
        outbound from xfrm. None means unspecified.
      xfrm_if_id: The ID of the XFRM interface to use or None.
    """
    outer_family = net_test.GetAddressFamily(net_test.GetAddressVersion(dst))

    self.AddSaInfo(src, dst, spi, XFRM_MODE_TUNNEL, 0, encryption, auth_trunc,
                   None, None, mark, output_mark, xfrm_if_id=xfrm_if_id)

    if selector is None:
      selectors = [EmptySelector(AF_INET), EmptySelector(AF_INET6)]
    else:
      selectors = [selector]

    for selector in selectors:
      policy = UserPolicy(direction, selector)
      tmpl = UserTemplate(outer_family, spi, 0, (src, dst))
      self.AddPolicyInfo(policy, tmpl, mark, xfrm_if_id=xfrm_if_id)
Ejemplo n.º 3
0
def EncryptPacketWithNull(packet, spi, seq, tun_addrs):
  """Apply null encryption to a packet.

  This performs ESP encapsulation on the given packet. The returned packet will
  be a tunnel mode packet if tun_addrs is provided.

  The input packet is assumed to be a UDP packet. The input packet *MUST* have
  its length and checksum fields in IP and UDP headers set appropriately. This
  can be done by "rebuilding" the scapy object. e.g.,
      ip6_packet = scapy.IPv6(str(ip6_packet))

  TODO: Support TCP

  Args:
    packet: a scapy.IPv6 or scapy.IP packet
    spi: security parameter index for ESP header in host byte order
    seq: sequence number for ESP header
    tun_addrs: A tuple of (local, remote) addresses for tunnel mode, or None
      to request a transport mode packet.

  Return:
    The encrypted packet (scapy.IPv6 or scapy.IP)
  """
  # The top-level packet changes in tunnel mode, which would invalidate
  # the passed-in packet pointer. For consistency, this function now returns
  # a new packet and does not modify the user's original packet.
  packet = packet.copy()
  udp_layer = packet.getlayer(scapy.UDP)
  if not udp_layer:
    raise ValueError("Expected a UDP packet")
  # Build an ESP header.
  esp_packet = scapy.Raw(xfrm.EspHdr((spi, seq)).Pack())

  if tun_addrs:
    tsrc_addr, tdst_addr = tun_addrs
    outer_version = net_test.GetAddressVersion(tsrc_addr)
    ip_type = {4: scapy.IP, 6: scapy.IPv6}[outer_version]
    new_ip_layer = ip_type(src=tsrc_addr, dst=tdst_addr)
    inner_layer = packet
    esp_nexthdr = {scapy.IPv6: IPPROTO_IPV6,
                   scapy.IP: IPPROTO_IPIP}[type(packet)]
  else:
    new_ip_layer = None
    inner_layer = udp_layer
    esp_nexthdr = IPPROTO_UDP


  # ESP padding per RFC 4303 section 2.4.
  # For a null cipher with a block size of 1, padding is only necessary to
  # ensure that the 1-byte Pad Length and Next Header fields are right aligned
  # on a 4-byte boundary.
  esplen = (len(inner_layer) + 2)  # UDP length plus Pad Length and Next Header.
  padlen = util.GetPadLength(4, esplen)
  # The pad bytes are consecutive integers starting from 0x01.
  padding = "".join((chr(i) for i in xrange(1, padlen + 1)))
  trailer = padding + struct.pack("BB", padlen, esp_nexthdr)

  # Assemble the packet.
  esp_packet.payload = scapy.Raw(inner_layer)
  packet = new_ip_layer if new_ip_layer else packet
  packet.payload = scapy.Raw(str(esp_packet) + trailer)

  # TODO: Can we simplify this and avoid the initial copy()?
  # Fix the IPv4/IPv6 headers.
  if type(packet) is scapy.IPv6:
    packet.nh = IPPROTO_ESP
    # Recompute plen.
    packet.plen = None
    packet = scapy.IPv6(str(packet))
  elif type(packet) is scapy.IP:
    packet.proto = IPPROTO_ESP
    # Recompute IPv4 len and checksum.
    packet.len = None
    packet.chksum = None
    packet = scapy.IP(str(packet))
  else:
    raise ValueError("First layer in packet should be IPv4 or IPv6: " + repr(packet))
  return packet
Ejemplo n.º 4
0
    def _CheckVtiInputOutput(self, vti, inner_version):
        local_outer = vti.local
        remote_outer = vti.remote

        # Create a socket to receive packets.
        read_sock = socket(net_test.GetAddressFamily(inner_version),
                           SOCK_DGRAM, 0)
        read_sock.bind((net_test.GetWildcardAddress(inner_version), 0))
        # The second parameter of the tuple is the port number regardless of AF.
        port = read_sock.getsockname()[1]
        # Guard against the eventuality of the receive failing.
        csocket.SetSocketTimeout(read_sock, 100)

        # Send a packet out via the vti-backed network, bound for the port number
        # of the input socket.
        write_sock = socket(net_test.GetAddressFamily(inner_version),
                            SOCK_DGRAM, 0)
        self.SelectInterface(write_sock, vti.netid, "mark")
        write_sock.sendto(net_test.UDP_PAYLOAD,
                          (_GetRemoteInnerAddress(inner_version), port))

        # Read a tunneled IP packet on the underlying (outbound) network
        # verifying that it is an ESP packet.
        self.assertSentPacket(vti)
        pkt = self._ExpectEspPacketOn(vti.underlying_netid, vti.out_spi,
                                      vti.tx, None, local_outer, remote_outer)

        # Perform an address switcheroo so that the inner address of the remote
        # end of the tunnel is now the address on the local VTI interface; this
        # way, the twisted inner packet finds a destination via the VTI once
        # decrypted.
        remote = _GetRemoteInnerAddress(inner_version)
        local = vti.addrs[inner_version]
        self._SwapInterfaceAddress(vti.iface, new_addr=remote, old_addr=local)
        try:
            # Swap the packet's IP headers and write it back to the
            # underlying network.
            pkt = TunTwister.TwistPacket(pkt)
            self.ReceivePacketOn(vti.underlying_netid, pkt)
            self.assertReceivedPacket(vti)
            # Receive the decrypted packet on the dest port number.
            read_packet = read_sock.recv(4096)
            self.assertEquals(read_packet, net_test.UDP_PAYLOAD)
        finally:
            # Unwind the switcheroo
            self._SwapInterfaceAddress(vti.iface,
                                       new_addr=local,
                                       old_addr=remote)

        # Now attempt to provoke an ICMP error.
        # TODO: deduplicate with multinetwork_test.py.
        version = net_test.GetAddressVersion(vti.remote)
        dst_prefix, intermediate = {
            4: ("172.19.", "172.16.9.12"),
            6: ("2001:db8::", "2001:db8::1")
        }[version]

        write_sock.sendto(net_test.UDP_PAYLOAD,
                          (_GetRemoteInnerAddress(inner_version), port))
        self.assertSentPacket(vti)
        pkt = self._ExpectEspPacketOn(vti.underlying_netid, vti.out_spi,
                                      vti.tx, None, local_outer, remote_outer)
        myaddr = self.MyAddress(version, vti.underlying_netid)
        _, toobig = packets.ICMPPacketTooBig(version, intermediate, myaddr,
                                             pkt)
        self.ReceivePacketOn(vti.underlying_netid, toobig)

        # Check that the packet too big reduced the MTU.
        routes = self.iproute.GetRoutes(vti.remote, 0, vti.underlying_netid,
                                        None)
        self.assertEquals(1, len(routes))
        rtmsg, attributes = routes[0]
        self.assertEquals(iproute.RTN_UNICAST, rtmsg.type)
        self.assertEquals(packets.PTB_MTU,
                          attributes["RTA_METRICS"]["RTAX_MTU"])

        # Clear PMTU information so that future tests don't have to worry about it.
        self.InvalidateDstCache(version, vti.underlying_netid)