Reputation: 1
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!
Upvotes: -2
Views: 3984
Reputation: 131
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
Upvotes: 1
Reputation: 548
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"]
Upvotes: 0