osrg/gobgp

A packet parse bug that causes wrong value for `My AS` field

grandnew opened this issue · 1 comments

There is a parse bug in gobgp.

The config of the under-test node is as follows, and its IP is 10.0.255.6

[global.config]
  as = 65001
  router-id = "192.168.10.6"


[[neighbors]]
  [neighbors.config]
    neighbor-address = "10.0.255.5"
    peer-as = 64512

Send an OPEN packet to this node on the host 10.0.255.5 using the following script:

import socket
from time import sleep

payload = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00;\x01\x04\xfc\x00\x00\x05\xc0\xa8\n\x05\x1e\x02\x1c\x01\x04\x00\x01\x00\x01\x02\x00@\x02\x00xA\x04\x00\x00\x00\x02F\x00G\x06\x00\x01\x01\x01\x00x'


s = socket.socket(type=socket.SOCK_STREAM)
s.connect(("10.0.255.6", 179))
s.send(payload)
sleep(1)
s.close()

Then, the logs of the under-test node (with IP 10.0.255.6) are as follows.

{"level":"info","msg":"gobgpd started","time":"2023-10-21T12:56:25Z"}
{"Topic":"Config","level":"info","msg":"Finished reading the config file","time":"2023-10-21T12:56:25Z"}
{"Key":"10.0.255.5","Topic":"config","level":"info","msg":"Add Peer","time":"2023-10-21T12:56:25Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"info","msg":"Add a peer configuration","time":"2023-10-21T12:56:25Z"}
{"Duration":0,"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"IdleHoldTimer expired","time":"2023-10-21T12:56:25Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"state changed","new":"BGP_FSM_ACTIVE","old":"BGP_FSM_IDLE","reason":{"Type":7,"BGPNotification":null,"Data":null},"time":"2023-10-21T12:56:25Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"try to connect","time":"2023-10-21T12:56:30Z"}
{"Error":"dial tcp 0.0.0.0:0-\u003e10.0.255.5:179: connect: connection refused","Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"failed to connect","time":"2023-10-21T12:56:30Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"Accepted a new passive connection","time":"2023-10-21T12:56:35Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"stop connect loop","time":"2023-10-21T12:56:35Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"state changed","new":"BGP_FSM_OPENSENT","old":"BGP_FSM_ACTIVE","reason":{"Type":11,"BGPNotification":null,"Data":null},"time":"2023-10-21T12:56:35Z"}
{"Data":"as number mismatch expected 64512, received 2","Key":"10.0.255.5","Topic":"Peer","level":"warning","msg":"sent notification","time":"2023-10-21T12:56:35Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"state changed","new":"BGP_FSM_IDLE","old":"BGP_FSM_OPENSENT","reason":{"Type":10,"BGPNotification":{"Header":{"Marker":null,"Len":21,"Type":3},"Body":{"ErrorCode":2,"ErrorSubcode":2,"Data":null}},"Data":null},"time":"2023-10-21T12:56:35Z"}
{"Duration":5,"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"IdleHoldTimer expired","time":"2023-10-21T12:56:40Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"state changed","new":"BGP_FSM_ACTIVE","old":"BGP_FSM_IDLE","reason":{"Type":7,"BGPNotification":null,"Data":null},"time":"2023-10-21T12:56:40Z"}
{"Key":"10.0.255.5","Topic":"Peer","level":"debug","msg":"try to connect","time":"2023-10-21T12:56:45Z"}

The logs indicate that the My AS field is parsed as 2 instead of 64512 (the line with content {"Data":"as number mismatch expected 64512, received 2","Key":"10.0.255.5","Topic":"Peer","level":"warning","msg":"sent notification","time":"2023-10-21T12:56:35Z"})

However, the parse results of the wireshark indicate that the My AS field is 64512, as shown in the sixth packet in BGP_parse_bug.pcap.zip.

Besides, the parse results of scapy also align with that of wireshark:

from scapy.all import *
from scapy.contrib.bgp import BGP

payload = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00;\x01\x04\xfc\x00\x00\x05\xc0\xa8\n\x05\x1e\x02\x1c\x01\x04\x00\x01\x00\x01\x02\x00@\x02\x00xA\x04\x00\x00\x00\x02F\x00G\x06\x00\x01\x01\x01\x00x'

bgp=BGP(payload)
bgp.show()

The output is:

###[ HEADER ]### 
  marker    = 0xffffffffffffffffffffffffffffffff
  len       = 59
  type      = OPEN
###[ OPEN ]### 
     version   = 4
     my_as     = 64512
     hold_time = 5
     bgp_id    = 192.168.10.5
     opt_param_len= 30
     \opt_params\
      |###[ Optional parameter ]### 
      |  param_type= Capabilities
      |  param_length= 28
      |  \param_value\
      |   |###[ Multiprotocol Extensions for BGP-4 ]### 
      |   |  code      = Multiprotocol Extensions for BGP-4
      |   |  length    = 4
      |   |  afi       = IP (IP version 4)
      |   |  reserved  = 0
      |   |  safi      = Network Layer Reachability Information used for unicast forwarding
      |   |###[ Raw ]### 
      |   |     load      = '\x02\x00@\x02\x00xA\x04\x00\x00\x00\x02F\x00G\x06\x00\x01\x01\x01\x00x'
fujita commented

The OPEN message has 4-octet AS number capability (65), which tells that the the AS number is 2.
スクリーンショット 2023-10-24 19 06 53