Setting up BGP Layer Using Scapy

Question:

I am trying to use Scapy to send packets that have a BGP layer

I am currently stuck on a rudimentary part of this problem because I am unable to set up the BGP layer. I followed the instructions to set up the regular IP and TCP Layer.

Eg:

>>a=IP(src="192.168.1.1",dst="192.168.1.2")/TCP(sport=179,dport=50)

But the problem arises when I do this:

>>a=a/BGP()
NameError: name BGP is not defined

I have seen the BGP implementations in the contrib file from Scapy Github (https://github.com/secdev/scapy/blob/9201f1cf1318edd5768d7e2ee968b7fba0a24c5e/scapy/contrib/bgp.py) so I think Scapy does support BGP implementations

I am new to networking so I was wondering if you could help me set up the BGP layer

Thanks for taking the time to read this!

Asked By: James Butler

||

Answers:

Just going to try and help here. I have zero experience with BGP type packets, but… I copied the bgp.py file from the link you provided into scapy/layers. Using ls() I found the following:

BGPAuthenticationData : BGP Authentication Data
BGPErrorSubcodes : BGP Error Subcodes
BGPHeader  : BGP header
BGPNotification : BGP Notification fields
BGPOpen    : BGP Open Header
BGPOptionalParameter : BGP Optional Parameters
BGPPathAttribute : BGP Attribute fields
BGPUpdate  : BGP Update fields

I could then use say ls(BGPUpdate) to show this:

withdrawn_len : ShortField           = (None)
withdrawn  : FieldListField       = ([])
tp_len     : ShortField           = (None)
total_path : PacketListField      = ([])
nlri       : FieldListField       = ([])

and was able to create this packet:

pkt = pkt = IP()/TCP()/BGPUpdate()
pkt.show()
###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     = 
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 127.0.0.1
  dst       = 127.0.0.1
  options   
###[ TCP ]###
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = {}
###[ BGP Update fields ]###
        withdrawn_len= None
        withdrawn = []
        tp_len    = None
        total_path
        nlri      = []

I’m not sure what all of the different types of BGP layers/packets are used for or where the Communities Number would be set. Possibly in BGPPathAttribute(type=x). Type 5 is “LOCAL_PREF” which may correspond to Community Values. Try this Link.

pkt = BGPPathAttribute(type=5)
pkt.show()
###[ BGP Attribute fields ]###
  flags     = Transitive
  type      = LOCAL_PREF
  attr_len  = None
  value     = ''

Anyway, hope that helps a little.

Edit:
Forgot. I also added “bgp” to the load_layers section of scapy/config.py. Line 373. Like this:

   load_layers =  ["l2", "inet", "dhcp", "dns", "dot11", "gprs", "hsrp", "inet6", "ir", "isakmp", "l2tp",
               "mgcp", "mobileip", "netbios", "netflow", "ntp", "ppp", "radius", "rip", "rtp",
               "sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth", "dhcp6", "llmnr", "sctp", "vrrp",
               "ipsec","bgp"]   
Answered By: Noob123

We want a BGP Layer using scapy. As BGP travels over TCP. So we must have a established (3 way handshake) tcp socket. And TCP travels over IP. Thus we can represent full packet in the below format.

packet = IP Layer / TCP Layer / BGP Layer
But BGP itself is divided in two parts, BGP Header and BGP Payload (EG: OPEN, UPDATE, etc ). So the above layer is represented as given below.

packet = IP Layer / TCP Layer / BGP Header / BGP payload
Here BGP Header specifies authentication, length and type of BGP Payload.To represent whole thing in scapy, we can do the following excercise. (I am assuming here that you have an established TCP socket.)

from scapy.layers.inet import IP, TCP
from scapy.contrib.bgp import BGPHeader, BGPUpdate, BGPPathAttr, BGPNLRI_IPv4, BGPPALocalPref

base = IP(src=src_ipv4_addr, dst=dst_ipv4_addr, proto=6, ttl=255)  # proto=6 represents that, TCP will be travelling above this layer. This is simple IPV4 communication.
tcp = TCP(sport=established_port, dport=179, seq=current_seq_num, ack=expected_seq_num, flags='PA')  # dport=179 means, we are communicating with bgp port of the destination router/ host. sport is a random port over which tcp is established. seq and ack are the sequence number and acknowledgement numbers. flags = PA are the PUSH and ACK flags.
hdr = BGPHeader(type=2, marker=0xffffffffffffffffffffffffffffffff)  # type=2 means UPDATE packet will be the BGP Payload, marker field is for authentication. max hex int (all f) are used for no auth.
up = BGPUpdate(path_attr=[BGPPathAttr(type_flags=64, type_code=5, attribute=BGPPALocalPref(local_pref=100))], nlri=BGPNLRI_IPv4(prefix=NLRI_PREFIX))      # update packet consist of path attributes and NLRI (Network layer reachability information),  type_code in path attributes is for which type of path attribute it is. [more][3]

packet = base / tcp / hdr / up
packet.show2()

Using the following variable values (for example purpose).

src_ipv4_addr = '10.110.99.2'  # eth0
dst_ipv4_addr = '10.110.99.50'
established_port = 1223
expected_seq_num=1000 # ack
current_seq_num=1500 # seq
NLRI_PREFIX = '10.110.99.0/24'

Output will be following.

###[ IP ]### 
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 74
  id        = 1
  flags     = 
  frag      = 0
  ttl       = 255
  proto     = tcp
  chksum    = 0xe09c
  src       = 10.110.99.2
  dst       = 10.110.99.50
  options   
###[ TCP ]### 
     sport     = 1223
     dport     = bgp
     seq       = 1500
     ack       = 1000
     dataofs   = 5
     reserved  = 0
     flags     = PA
     window    = 8192
     chksum    = 0x102d
     urgptr    = 0
     options   = []
###[ HEADER ]### 
        marker    = 0xffffffffffffffffffffffffffffffff
        len       = 34
        type      = UPDATE
###[ UPDATE ]### 
           withdrawn_routes_len= 0
           withdrawn_routes
           path_attr_len= 7
           path_attr 
            |###[ BGPPathAttr ]### 
            |  type_flags= Transitive
            |  type_code = LOCAL_PREF
            |  attr_len  = 4
            |  attribute 
            |   |###[ LOCAL_PREF ]### 
            |   |  local_pref= 100
           nlri      
            |###[ IPv4 NLRI ]### 
            |  prefix    = 10.110.99.0/24
Answered By: MSS
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.